From 32881126b74efd328f08b432eda3cdc59c898cb0 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sat, 30 Nov 2024 18:51:38 -0300 Subject: [PATCH 01/18] creating parameters parser class and tests --- lib/config/parameters_parser.js | 34 ++++++ tests/configuration/parameters_parser_test.js | 113 ++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 lib/config/parameters_parser.js create mode 100644 tests/configuration/parameters_parser_test.js diff --git a/lib/config/parameters_parser.js b/lib/config/parameters_parser.js new file mode 100644 index 00000000..e661c4ce --- /dev/null +++ b/lib/config/parameters_parser.js @@ -0,0 +1,34 @@ +/** + * I transform a list of parameters into a valid configuration object. + */ + +export class ParametersParser { + generateConfigurationFromParams(params) { + let generatedParams = {}; + params.forEach(param => { + const runParameter = this.generateRunParameter(param); + generatedParams = { ...generatedParams, ...runParameter }; + }); + + return generatedParams; + } + + generateRunParameter(param) { + if (param === '-f' || param === '--fail-fast') { + return { failFast: true }; + } + + if (param === '-r' || param === '--randomize') { + return { randomOrder: true }; + } + if (this.isLanguageParam(param)) { + const options = param.split(' '); + return { language: options[1] }; + } + } + + isLanguageParam(param) { + const options = param.split(' '); + return options[0] === '-l' || options[0] === '--language'; + } +} diff --git a/tests/configuration/parameters_parser_test.js b/tests/configuration/parameters_parser_test.js new file mode 100644 index 00000000..81aa55d4 --- /dev/null +++ b/tests/configuration/parameters_parser_test.js @@ -0,0 +1,113 @@ +import { assert, suite, test } from '../../lib/testy.js'; +import { ParametersParser } from '../../lib/config/parameters_parser.js'; + +suite('Parameters parser', () => { + + test('returns empty configuration if passing an empty params list', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams([]); + assert.areEqual(configuration, {}); + }); + + test('returns configuration with fail fast mode enabled if passing -f option', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams(['-f']); + assert.areEqual(configuration, { failFast: true }); + }); + + test('returns configuration with fail fast mode enabled if passing --fail-fast option', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams(['--fail-fast']); + assert.areEqual(configuration, { failFast: true }); + }); + + test('returns configuration with randomize mode enabled if passing -r option', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams(['-r']); + assert.areEqual(configuration, { randomOrder: true }); + }); + + test('returns configuration with randomize enabled if passing --randomize', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams(['--randomize']); + assert.areEqual(configuration, { randomOrder: true }); + }); + + test('returns configuration with english language enabled if passing \'-l en\' en option', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams(['-l en']); + assert.areEqual(configuration, { language: 'en' }); + }); + + test('returns configuration with english language enabled if passing \'-language en\' en option', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams(['--language en']); + assert.areEqual(configuration, { language: 'en' }); + }); + + test('returns configuration with spanish language enabled if passing \'-l es\' en option', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams(['-l es']); + assert.areEqual(configuration, { language: 'es' }); + }); + + test('returns configuration with english language enabled if passing \'-language es\' en option', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams(['--language es']); + assert.areEqual(configuration, { language: 'es' }); + }); + + test('returns configuration with italian language enabled if passing \'-l it\' en option', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams(['-l it']); + assert.areEqual(configuration, { language: 'it' }); + }); + + test('returns configuration with italian language enabled if passing \'-language it\' en option', () => { + const parametersParser = new ParametersParser(); + const configuration = parametersParser.generateConfigurationFromParams(['--language it']); + assert.areEqual(configuration, { language: 'it' }); + }); + + test('returns configuration with fail fast and randomize modes enabled no matter the order the params are sent', () => { + const parametersParser = new ParametersParser(); + const configuration1 = parametersParser.generateConfigurationFromParams(['-f', '-r']); + const configuration2 = parametersParser.generateConfigurationFromParams(['-r', '-f']); + + assert.areEqual(configuration1, { failFast: true, randomOrder: true }); + assert.areEqual(configuration2, { failFast: true, randomOrder: true }); + }); + + test('returns configuration with fail fast, randomize and english language enabled no matter the order the params are sent', () => { + const parametersParser = new ParametersParser(); + const configuration1 = parametersParser.generateConfigurationFromParams(['-f', '-r', '-l en']); + const configuration2 = parametersParser.generateConfigurationFromParams(['-f', '-l en', '-r']); + const configuration3 = parametersParser.generateConfigurationFromParams(['-l en', '-f', '-r']); + + assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); + assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); + assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); + }); + + test('returns configuration with fail fast, randomize and english language enabled when using long commands versions no matter the order the params are sent', () => { + const parametersParser = new ParametersParser(); + const configuration1 = parametersParser.generateConfigurationFromParams(['--fail-fast', '--randomize', '--language en']); + const configuration2 = parametersParser.generateConfigurationFromParams(['--fail-fast', '--language en', '--randomize']); + const configuration3 = parametersParser.generateConfigurationFromParams(['--language en', '--fail-fast', '--randomize']); + + assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); + assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); + assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); + }); + + test('returns configuration with fail fast, randomize and english language enabled when mixing long and short commands no matter the order the params are sent', () => { + const parametersParser = new ParametersParser(); + const configuration1 = parametersParser.generateConfigurationFromParams(['-f', '--randomize', '-l en']); + const configuration2 = parametersParser.generateConfigurationFromParams(['--fail-fast', '-l en', '-r']); + const configuration3 = parametersParser.generateConfigurationFromParams(['--language en', '-f', '-r']); + + assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); + assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); + assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); + }); +}); From 5b910db50e7c746b0afcd23072b9b99cf6945134 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 1 Dec 2024 13:17:12 -0300 Subject: [PATCH 02/18] sending generated configuration to Testy --- lib/config/configuration.js | 4 ++ lib/config/parameters_parser.js | 69 +++++++++++++++---- lib/script_action.js | 9 ++- tests/configuration/parameters_parser_test.js | 65 ++++++++--------- 4 files changed, 93 insertions(+), 54 deletions(-) diff --git a/lib/config/configuration.js b/lib/config/configuration.js index 1234671a..207327c1 100644 --- a/lib/config/configuration.js +++ b/lib/config/configuration.js @@ -33,6 +33,10 @@ export class Configuration { return new this(userConfiguration, defaultConfiguration); } + static withConfiguration(aConfiguration) { + const defaultConfiguration = require('./default_configuration.json'); + return new this(aConfiguration, defaultConfiguration); + } constructor(userConfiguration, defaultConfiguration) { this.#userConfigurationOptions = userConfiguration; this.#defaultConfigurationOptions = defaultConfiguration; diff --git a/lib/config/parameters_parser.js b/lib/config/parameters_parser.js index e661c4ce..26524c0b 100644 --- a/lib/config/parameters_parser.js +++ b/lib/config/parameters_parser.js @@ -1,34 +1,73 @@ /** - * I transform a list of parameters into a valid configuration object. + * I transform a list of console parameters into a valid configuration object. */ export class ParametersParser { - generateConfigurationFromParams(params) { + static generateRunConfigurationFromParams(params) { let generatedParams = {}; params.forEach(param => { - const runParameter = this.generateRunParameter(param); + const runParameter = this.#generateRunConfigurationParameter(param); generatedParams = { ...generatedParams, ...runParameter }; }); return generatedParams; } - generateRunParameter(param) { - if (param === '-f' || param === '--fail-fast') { - return { failFast: true }; - } + static #generateRunConfigurationParameter(param) { + const paramParser = [FailFastConfigurationParameterParser, RandomizeConfigurationParameterParser, LanguageConfigurationParameterParser, InvalidConfigurationParameter].find(configurationParameterParser => configurationParameterParser.canHandle(param)) + return paramParser.handle(param) + } +} + +class FailFastConfigurationParameterParser { + static canHandle(consoleParam) { + return this.#isFailFastParam(consoleParam); + } + + static handle(_consoleParam) { + return { failFast: true }; + } + + static #isFailFastParam(param) { + return param === '-f' || param === '--fail-fast' + } +} + +class RandomizeConfigurationParameterParser { + static canHandle(consoleParam) { + return this.#isRandomizeParam(consoleParam); + } - if (param === '-r' || param === '--randomize') { - return { randomOrder: true }; - } - if (this.isLanguageParam(param)) { - const options = param.split(' '); - return { language: options[1] }; - } + static handle(_consoleParam) { + return { randomOrder: true} } - isLanguageParam(param) { + static #isRandomizeParam(param) { + return param === '-r' || param === '--randomize' + } +} + +class LanguageConfigurationParameterParser { + static canHandle(consoleParam) { + return this.#isLanguageParam(consoleParam); + } + + static handle(consoleParam) { + const options = consoleParam.split(' '); + return { language: options[1] }; + } + static #isLanguageParam(param) { const options = param.split(' '); return options[0] === '-l' || options[0] === '--language'; } } + +class InvalidConfigurationParameter { + static canHandle(_consoleParam) { + return true + } + + static handle(configurationParam) { + throw Error(`Cannot parse invalid run configuration parameter ${configurationParam}. Please provide a valid configuration to run the tests.`) + } +} \ No newline at end of file diff --git a/lib/script_action.js b/lib/script_action.js index b39df6d8..450b9c39 100644 --- a/lib/script_action.js +++ b/lib/script_action.js @@ -7,6 +7,7 @@ import { InvalidConfigurationError } from './errors.js'; // Change to import assertions when reaching Node 18 import { createRequire } from 'module'; +import {ParametersParser} from "./config/parameters_parser.js"; const require = createRequire(import.meta.url); export const ScriptAction = { @@ -64,6 +65,8 @@ const ShowHelp = { console.log('Options: \n'); console.log(' -h, --help Displays this text'); console.log(' -v, --version Displays the current version'); + console.log(' -f, --fail-fast Enables fail fast option for running tests'); + console.log(' -r, --randomize Enables random order option for running tests'); this._exitSuccessfully(); }, }; @@ -78,8 +81,10 @@ const RunTests = { async execute(params) { try { - const testyInstance = Testy.configuredWith(Configuration.current()); - await testyInstance.run(params); + const sentConfigurationParams = params.slice(1) + const selectedConfiguration = ParametersParser.generateRunConfigurationFromParams(sentConfigurationParams) + const testyInstance = Testy.configuredWith(Configuration.withConfiguration(selectedConfiguration)); + await testyInstance.run(params.slice(0,1)); this._exitSuccessfully(); } catch (error) { if (error instanceof InvalidConfigurationError) { diff --git a/tests/configuration/parameters_parser_test.js b/tests/configuration/parameters_parser_test.js index 81aa55d4..7943ae6b 100644 --- a/tests/configuration/parameters_parser_test.js +++ b/tests/configuration/parameters_parser_test.js @@ -4,85 +4,72 @@ import { ParametersParser } from '../../lib/config/parameters_parser.js'; suite('Parameters parser', () => { test('returns empty configuration if passing an empty params list', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams([]); + const configuration = ParametersParser.generateRunConfigurationFromParams([]); assert.areEqual(configuration, {}); }); test('returns configuration with fail fast mode enabled if passing -f option', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams(['-f']); + const configuration = ParametersParser.generateRunConfigurationFromParams(['-f']); assert.areEqual(configuration, { failFast: true }); }); test('returns configuration with fail fast mode enabled if passing --fail-fast option', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams(['--fail-fast']); + const configuration = ParametersParser.generateRunConfigurationFromParams(['--fail-fast']); assert.areEqual(configuration, { failFast: true }); }); test('returns configuration with randomize mode enabled if passing -r option', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams(['-r']); + const configuration = ParametersParser.generateRunConfigurationFromParams(['-r']); assert.areEqual(configuration, { randomOrder: true }); }); test('returns configuration with randomize enabled if passing --randomize', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams(['--randomize']); + const configuration = ParametersParser.generateRunConfigurationFromParams(['--randomize']); assert.areEqual(configuration, { randomOrder: true }); }); test('returns configuration with english language enabled if passing \'-l en\' en option', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams(['-l en']); + const configuration = ParametersParser.generateRunConfigurationFromParams(['-l en']); assert.areEqual(configuration, { language: 'en' }); }); test('returns configuration with english language enabled if passing \'-language en\' en option', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams(['--language en']); + const configuration = ParametersParser.generateRunConfigurationFromParams(['--language en']); assert.areEqual(configuration, { language: 'en' }); }); test('returns configuration with spanish language enabled if passing \'-l es\' en option', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams(['-l es']); + const configuration = ParametersParser.generateRunConfigurationFromParams(['-l es']); assert.areEqual(configuration, { language: 'es' }); }); test('returns configuration with english language enabled if passing \'-language es\' en option', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams(['--language es']); + const configuration = ParametersParser.generateRunConfigurationFromParams(['--language es']); assert.areEqual(configuration, { language: 'es' }); }); test('returns configuration with italian language enabled if passing \'-l it\' en option', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams(['-l it']); + const configuration = ParametersParser.generateRunConfigurationFromParams(['-l it']); assert.areEqual(configuration, { language: 'it' }); }); test('returns configuration with italian language enabled if passing \'-language it\' en option', () => { - const parametersParser = new ParametersParser(); - const configuration = parametersParser.generateConfigurationFromParams(['--language it']); + const configuration = ParametersParser.generateRunConfigurationFromParams(['--language it']); assert.areEqual(configuration, { language: 'it' }); }); test('returns configuration with fail fast and randomize modes enabled no matter the order the params are sent', () => { - const parametersParser = new ParametersParser(); - const configuration1 = parametersParser.generateConfigurationFromParams(['-f', '-r']); - const configuration2 = parametersParser.generateConfigurationFromParams(['-r', '-f']); + const configuration1 = ParametersParser.generateRunConfigurationFromParams(['-f', '-r']); + const configuration2 = ParametersParser.generateRunConfigurationFromParams(['-r', '-f']); assert.areEqual(configuration1, { failFast: true, randomOrder: true }); assert.areEqual(configuration2, { failFast: true, randomOrder: true }); }); test('returns configuration with fail fast, randomize and english language enabled no matter the order the params are sent', () => { - const parametersParser = new ParametersParser(); - const configuration1 = parametersParser.generateConfigurationFromParams(['-f', '-r', '-l en']); - const configuration2 = parametersParser.generateConfigurationFromParams(['-f', '-l en', '-r']); - const configuration3 = parametersParser.generateConfigurationFromParams(['-l en', '-f', '-r']); + const configuration1 = ParametersParser.generateRunConfigurationFromParams(['-f', '-r', '-l en']); + const configuration2 = ParametersParser.generateRunConfigurationFromParams(['-f', '-l en', '-r']); + const configuration3 = ParametersParser.generateRunConfigurationFromParams(['-l en', '-f', '-r']); assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); @@ -90,10 +77,9 @@ suite('Parameters parser', () => { }); test('returns configuration with fail fast, randomize and english language enabled when using long commands versions no matter the order the params are sent', () => { - const parametersParser = new ParametersParser(); - const configuration1 = parametersParser.generateConfigurationFromParams(['--fail-fast', '--randomize', '--language en']); - const configuration2 = parametersParser.generateConfigurationFromParams(['--fail-fast', '--language en', '--randomize']); - const configuration3 = parametersParser.generateConfigurationFromParams(['--language en', '--fail-fast', '--randomize']); + const configuration1 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '--randomize', '--language en']); + const configuration2 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '--language en', '--randomize']); + const configuration3 = ParametersParser.generateRunConfigurationFromParams(['--language en', '--fail-fast', '--randomize']); assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); @@ -101,13 +87,18 @@ suite('Parameters parser', () => { }); test('returns configuration with fail fast, randomize and english language enabled when mixing long and short commands no matter the order the params are sent', () => { - const parametersParser = new ParametersParser(); - const configuration1 = parametersParser.generateConfigurationFromParams(['-f', '--randomize', '-l en']); - const configuration2 = parametersParser.generateConfigurationFromParams(['--fail-fast', '-l en', '-r']); - const configuration3 = parametersParser.generateConfigurationFromParams(['--language en', '-f', '-r']); + const configuration1 = ParametersParser.generateRunConfigurationFromParams(['-f', '--randomize', '-l en']); + const configuration2 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '-l en', '-r']); + const configuration3 = ParametersParser.generateRunConfigurationFromParams(['--language en', '-f', '-r']); assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); }); + + test('throws an error when sending unknown params', () => { + assert + .that(() => ParametersParser.generateRunConfigurationFromParams(['fake param'])) + .raises(new Error(`Cannot parse invalid run configuration parameter ${`fake param`}. Please provide a valid configuration to run the tests.`)); + }) }); From 8055e9207c8e71218941b8a0422cd8386ed30421 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 1 Dec 2024 18:42:52 -0300 Subject: [PATCH 03/18] allowing to run multiple files with configuration parameters --- lib/config/parameters_parser.js | 76 ++++++++++++++----- lib/script_action.js | 6 +- lib/utils.js | 14 ++++ tests/configuration/parameters_parser_test.js | 54 ++++++++++++- 4 files changed, 128 insertions(+), 22 deletions(-) diff --git a/lib/config/parameters_parser.js b/lib/config/parameters_parser.js index 26524c0b..667a1c87 100644 --- a/lib/config/parameters_parser.js +++ b/lib/config/parameters_parser.js @@ -1,65 +1,105 @@ /** * I transform a list of console parameters into a valid configuration object. */ +import {isFailFastParam, isLanguageParam, isRandomizeParam} from "../utils.js"; +const LANGUAGE_OPTIONS = ['es', 'en', 'it'] export class ParametersParser { static generateRunConfigurationFromParams(params) { + const sanitizedParams = this.sanitizeParameters(params) + return this.generateRunConfigurationFromSanitizedParams(sanitizedParams); + } + + static generateRunConfigurationFromSanitizedParams(sanitizedParams) { let generatedParams = {}; - params.forEach(param => { + sanitizedParams.forEach(param => { const runParameter = this.#generateRunConfigurationParameter(param); generatedParams = { ...generatedParams, ...runParameter }; }); return generatedParams; } - static #generateRunConfigurationParameter(param) { const paramParser = [FailFastConfigurationParameterParser, RandomizeConfigurationParameterParser, LanguageConfigurationParameterParser, InvalidConfigurationParameter].find(configurationParameterParser => configurationParameterParser.canHandle(param)) return paramParser.handle(param) } + + static sanitizeParameters(params) { + const languageParamIndex = params.findIndex(p => p === '-l' || p === '--language') + if(languageParamIndex >= 0) { + return this.#sanitizeLanguageParamOptions(params, languageParamIndex); + } + return params + } + + static #sanitizeLanguageParamOptions(params, languageParamIndex) { + const languageOption = this.#validateLanguageOption(params, languageParamIndex) + const languageConfig = [`-l ${languageOption}`] + this.#removeLanguageParameters(params, languageParamIndex) + return [...params, ...languageConfig] + } + + static #validateLanguageOption(params, languageParamIndex) { + const languageOption = params[languageParamIndex + 1] + if(!LANGUAGE_OPTIONS.includes(languageOption)) { + throw Error(`Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian`) + } + return languageOption + } + + static #removeLanguageParameters(params, languageParamIndex) { + params.splice(languageParamIndex, 2) + } + + static getPathsAndConfigurationParams(allParams) { + const firstConfigParamIndex = allParams.findIndex(param => this.isConfigurationParam(param)) + if(firstConfigParamIndex >= 0) { + return { + pathsParams: allParams.slice(0, firstConfigParamIndex), + configurationParams: allParams.slice(firstConfigParamIndex) + } + } + + return { + pathsParams: allParams, + configurationParams: [] + } + } + + static isConfigurationParam(param) { + return isFailFastParam(param) || isRandomizeParam(param) || isLanguageParam(param) + } } class FailFastConfigurationParameterParser { static canHandle(consoleParam) { - return this.#isFailFastParam(consoleParam); + return isFailFastParam(consoleParam); } static handle(_consoleParam) { return { failFast: true }; } - - static #isFailFastParam(param) { - return param === '-f' || param === '--fail-fast' - } } class RandomizeConfigurationParameterParser { static canHandle(consoleParam) { - return this.#isRandomizeParam(consoleParam); + return isRandomizeParam(consoleParam); } static handle(_consoleParam) { return { randomOrder: true} } - - static #isRandomizeParam(param) { - return param === '-r' || param === '--randomize' - } } class LanguageConfigurationParameterParser { static canHandle(consoleParam) { - return this.#isLanguageParam(consoleParam); + return isLanguageParam(consoleParam); } static handle(consoleParam) { const options = consoleParam.split(' '); return { language: options[1] }; } - static #isLanguageParam(param) { - const options = param.split(' '); - return options[0] === '-l' || options[0] === '--language'; - } } class InvalidConfigurationParameter { @@ -68,6 +108,6 @@ class InvalidConfigurationParameter { } static handle(configurationParam) { - throw Error(`Cannot parse invalid run configuration parameter ${configurationParam}. Please provide a valid configuration to run the tests.`) + throw Error(`Cannot parse invalid run configuration parameter ${configurationParam}. Please run --help option to check available options.`) } } \ No newline at end of file diff --git a/lib/script_action.js b/lib/script_action.js index 450b9c39..ff67a4c3 100644 --- a/lib/script_action.js +++ b/lib/script_action.js @@ -81,10 +81,10 @@ const RunTests = { async execute(params) { try { - const sentConfigurationParams = params.slice(1) - const selectedConfiguration = ParametersParser.generateRunConfigurationFromParams(sentConfigurationParams) + const {pathsParams, configurationParams} = ParametersParser.getPathsAndConfigurationParams(params) + const selectedConfiguration = ParametersParser.generateRunConfigurationFromParams(configurationParams) const testyInstance = Testy.configuredWith(Configuration.withConfiguration(selectedConfiguration)); - await testyInstance.run(params.slice(0,1)); + await testyInstance.run(pathsParams); this._exitSuccessfully(); } catch (error) { if (error instanceof InvalidConfigurationError) { diff --git a/lib/utils.js b/lib/utils.js index bf5125d9..5fcdf115 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -78,6 +78,16 @@ const isFunction = object => const isUndefined = object => typeof object === 'undefined'; +const isFailFastParam = string => + isString(string) && (string === '-f' || string === '--fail-fast') + +const isRandomizeParam = string => + isString(string) && (string === '-r' || string === '--randomize') + +const isLanguageParam = param => { + const options = param.split(' '); + return isString(options[0]) && (options[0] === '-l' || options[0] === '--language'); +} const notNullOrUndefined = object => !isUndefined(object) && object !== null; @@ -173,4 +183,8 @@ export { errorDetailOf, // metaprogramming detectUserCallingLocation, + // parsing + isFailFastParam, + isRandomizeParam, + isLanguageParam }; diff --git a/tests/configuration/parameters_parser_test.js b/tests/configuration/parameters_parser_test.js index 7943ae6b..5bfaf04b 100644 --- a/tests/configuration/parameters_parser_test.js +++ b/tests/configuration/parameters_parser_test.js @@ -99,6 +99,58 @@ suite('Parameters parser', () => { test('throws an error when sending unknown params', () => { assert .that(() => ParametersParser.generateRunConfigurationFromParams(['fake param'])) - .raises(new Error(`Cannot parse invalid run configuration parameter ${`fake param`}. Please provide a valid configuration to run the tests.`)); + .raises(new Error(`Cannot parse invalid run configuration parameter ${`fake param`}. Please run --help option to check available options.`)); }) + + test('splits between path params and configuration params', () => { + const testPath1 = 'I am a test path' + const testPath2 = 'I am another test path' + + const {pathsParams, configurationParams} = ParametersParser.getPathsAndConfigurationParams([testPath1, testPath2, '-f', '-r']) + assert.areEqual(pathsParams, [testPath1, testPath2]) + assert.areEqual(configurationParams, ['-f', '-r']) + }); + + test('splits between path params and configuration params when path params are empty', () => { + const {pathsParams, configurationParams} = ParametersParser.getPathsAndConfigurationParams(['-f', '-r']) + assert.areEqual(pathsParams, []) + assert.areEqual(configurationParams, ['-f', '-r']) + }); + + test('splits between path params and configuration params when configuration params are empty', () => { + const testPath1 = 'I am a test path' + const testPath2 = 'I am another test path' + + const {pathsParams, configurationParams} = ParametersParser.getPathsAndConfigurationParams([testPath1, testPath2]) + assert.areEqual(pathsParams, [testPath1, testPath2]) + assert.areEqual(configurationParams, []) + }); + + test('splits between path params and configuration params when both are empty', () => { + const {pathsParams, configurationParams} = ParametersParser.getPathsAndConfigurationParams([]) + assert.areEqual(pathsParams, []) + assert.areEqual(configurationParams, []) + }) + + test('returns sanitized params when passing a valid list of params', () => { + const sanitizedParams = ParametersParser.sanitizeParameters(['-f', '-r']) + assert.areEqual(sanitizedParams, ['-f', '-r']) + }); + + test('returns sanitized params when passing a valid list of params including language params', () => { + const sanitizedParams = ParametersParser.sanitizeParameters(['-f', '-l', 'it', '-r']) + assert.areEqual(sanitizedParams, ['-f', '-r', '-l it']) + }); + + test('throws an error when sending invalid language option', () => { + assert + .that(() => ParametersParser.sanitizeParameters(['-l', 'fakeLanguage'])) + .raises(new Error(`Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian`)); + }) + + test('throws an error when language parameters do not have the proper order', () => { + assert + .that(() => ParametersParser.sanitizeParameters(['it', '-l'])) + .raises(new Error(`Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian`)); + }) }); From 41fbadfa0cc4be5db872363457c266b0296adf21 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 1 Dec 2024 20:06:01 -0300 Subject: [PATCH 04/18] fixing linter --- lib/config/parameters_parser.js | 56 +++++----- lib/script_action.js | 6 +- lib/utils.js | 8 +- tests/configuration/parameters_parser_test.js | 104 +++++++++--------- 4 files changed, 87 insertions(+), 87 deletions(-) diff --git a/lib/config/parameters_parser.js b/lib/config/parameters_parser.js index 667a1c87..9f98eb96 100644 --- a/lib/config/parameters_parser.js +++ b/lib/config/parameters_parser.js @@ -1,12 +1,12 @@ /** * I transform a list of console parameters into a valid configuration object. */ -import {isFailFastParam, isLanguageParam, isRandomizeParam} from "../utils.js"; +import { isFailFastParam, isLanguageParam, isRandomizeParam } from '../utils.js'; -const LANGUAGE_OPTIONS = ['es', 'en', 'it'] +const LANGUAGE_OPTIONS = ['es', 'en', 'it']; export class ParametersParser { static generateRunConfigurationFromParams(params) { - const sanitizedParams = this.sanitizeParameters(params) + const sanitizedParams = this.sanitizeParameters(params); return this.generateRunConfigurationFromSanitizedParams(sanitizedParams); } @@ -20,54 +20,54 @@ export class ParametersParser { return generatedParams; } static #generateRunConfigurationParameter(param) { - const paramParser = [FailFastConfigurationParameterParser, RandomizeConfigurationParameterParser, LanguageConfigurationParameterParser, InvalidConfigurationParameter].find(configurationParameterParser => configurationParameterParser.canHandle(param)) - return paramParser.handle(param) + const paramParser = [FailFastConfigurationParameterParser, RandomizeConfigurationParameterParser, LanguageConfigurationParameterParser, InvalidConfigurationParameter].find(configurationParameterParser => configurationParameterParser.canHandle(param)); + return paramParser.handle(param); } static sanitizeParameters(params) { - const languageParamIndex = params.findIndex(p => p === '-l' || p === '--language') - if(languageParamIndex >= 0) { + const languageParamIndex = params.findIndex(param => param === '-l' || param === '--language'); + if (languageParamIndex >= 0) { return this.#sanitizeLanguageParamOptions(params, languageParamIndex); } - return params + return params; } static #sanitizeLanguageParamOptions(params, languageParamIndex) { - const languageOption = this.#validateLanguageOption(params, languageParamIndex) - const languageConfig = [`-l ${languageOption}`] - this.#removeLanguageParameters(params, languageParamIndex) - return [...params, ...languageConfig] + const languageOption = this.#validateLanguageOption(params, languageParamIndex); + const languageConfig = [`-l ${languageOption}`]; + this.#removeLanguageParameters(params, languageParamIndex); + return [...params, ...languageConfig]; } static #validateLanguageOption(params, languageParamIndex) { - const languageOption = params[languageParamIndex + 1] - if(!LANGUAGE_OPTIONS.includes(languageOption)) { - throw Error(`Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian`) + const languageOption = params[languageParamIndex + 1]; + if (!LANGUAGE_OPTIONS.includes(languageOption)) { + throw Error('Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian'); } - return languageOption + return languageOption; } static #removeLanguageParameters(params, languageParamIndex) { - params.splice(languageParamIndex, 2) + params.splice(languageParamIndex, 2); } static getPathsAndConfigurationParams(allParams) { - const firstConfigParamIndex = allParams.findIndex(param => this.isConfigurationParam(param)) - if(firstConfigParamIndex >= 0) { + const firstConfigParamIndex = allParams.findIndex(param => this.isConfigurationParam(param)); + if (firstConfigParamIndex >= 0) { return { pathsParams: allParams.slice(0, firstConfigParamIndex), - configurationParams: allParams.slice(firstConfigParamIndex) - } + configurationParams: allParams.slice(firstConfigParamIndex), + }; } return { pathsParams: allParams, - configurationParams: [] - } + configurationParams: [], + }; } static isConfigurationParam(param) { - return isFailFastParam(param) || isRandomizeParam(param) || isLanguageParam(param) + return isFailFastParam(param) || isRandomizeParam(param) || isLanguageParam(param); } } @@ -87,7 +87,7 @@ class RandomizeConfigurationParameterParser { } static handle(_consoleParam) { - return { randomOrder: true} + return { randomOrder: true }; } } @@ -104,10 +104,10 @@ class LanguageConfigurationParameterParser { class InvalidConfigurationParameter { static canHandle(_consoleParam) { - return true + return true; } static handle(configurationParam) { - throw Error(`Cannot parse invalid run configuration parameter ${configurationParam}. Please run --help option to check available options.`) + throw Error(`Cannot parse invalid run configuration parameter ${configurationParam}. Please run --help option to check available options.`); } -} \ No newline at end of file +} diff --git a/lib/script_action.js b/lib/script_action.js index ff67a4c3..dcfb1f0a 100644 --- a/lib/script_action.js +++ b/lib/script_action.js @@ -7,7 +7,7 @@ import { InvalidConfigurationError } from './errors.js'; // Change to import assertions when reaching Node 18 import { createRequire } from 'module'; -import {ParametersParser} from "./config/parameters_parser.js"; +import { ParametersParser } from './config/parameters_parser.js'; const require = createRequire(import.meta.url); export const ScriptAction = { @@ -81,8 +81,8 @@ const RunTests = { async execute(params) { try { - const {pathsParams, configurationParams} = ParametersParser.getPathsAndConfigurationParams(params) - const selectedConfiguration = ParametersParser.generateRunConfigurationFromParams(configurationParams) + const { pathsParams, configurationParams } = ParametersParser.getPathsAndConfigurationParams(params); + const selectedConfiguration = ParametersParser.generateRunConfigurationFromParams(configurationParams); const testyInstance = Testy.configuredWith(Configuration.withConfiguration(selectedConfiguration)); await testyInstance.run(pathsParams); this._exitSuccessfully(); diff --git a/lib/utils.js b/lib/utils.js index 5fcdf115..b27bb913 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -79,15 +79,15 @@ const isUndefined = object => typeof object === 'undefined'; const isFailFastParam = string => - isString(string) && (string === '-f' || string === '--fail-fast') + isString(string) && (string === '-f' || string === '--fail-fast'); const isRandomizeParam = string => - isString(string) && (string === '-r' || string === '--randomize') + isString(string) && (string === '-r' || string === '--randomize'); const isLanguageParam = param => { const options = param.split(' '); return isString(options[0]) && (options[0] === '-l' || options[0] === '--language'); -} +}; const notNullOrUndefined = object => !isUndefined(object) && object !== null; @@ -186,5 +186,5 @@ export { // parsing isFailFastParam, isRandomizeParam, - isLanguageParam + isLanguageParam, }; diff --git a/tests/configuration/parameters_parser_test.js b/tests/configuration/parameters_parser_test.js index 5bfaf04b..1598b1f3 100644 --- a/tests/configuration/parameters_parser_test.js +++ b/tests/configuration/parameters_parser_test.js @@ -76,81 +76,81 @@ suite('Parameters parser', () => { assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); }); - test('returns configuration with fail fast, randomize and english language enabled when using long commands versions no matter the order the params are sent', () => { - const configuration1 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '--randomize', '--language en']); - const configuration2 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '--language en', '--randomize']); - const configuration3 = ParametersParser.generateRunConfigurationFromParams(['--language en', '--fail-fast', '--randomize']); - - assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); - assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); - assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); - }); - - test('returns configuration with fail fast, randomize and english language enabled when mixing long and short commands no matter the order the params are sent', () => { - const configuration1 = ParametersParser.generateRunConfigurationFromParams(['-f', '--randomize', '-l en']); - const configuration2 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '-l en', '-r']); - const configuration3 = ParametersParser.generateRunConfigurationFromParams(['--language en', '-f', '-r']); - - assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); - assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); - assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); - }); - - test('throws an error when sending unknown params', () => { - assert - .that(() => ParametersParser.generateRunConfigurationFromParams(['fake param'])) - .raises(new Error(`Cannot parse invalid run configuration parameter ${`fake param`}. Please run --help option to check available options.`)); - }) + test('returns configuration with fail fast, randomize and english language enabled when using long commands versions no matter the order the params are sent', () => { + const configuration1 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '--randomize', '--language en']); + const configuration2 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '--language en', '--randomize']); + const configuration3 = ParametersParser.generateRunConfigurationFromParams(['--language en', '--fail-fast', '--randomize']); + + assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); + assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); + assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); + }); + + test('returns configuration with fail fast, randomize and english language enabled when mixing long and short commands no matter the order the params are sent', () => { + const configuration1 = ParametersParser.generateRunConfigurationFromParams(['-f', '--randomize', '-l en']); + const configuration2 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '-l en', '-r']); + const configuration3 = ParametersParser.generateRunConfigurationFromParams(['--language en', '-f', '-r']); + + assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); + assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); + assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); + }); + + test('throws an error when sending unknown params', () => { + assert + .that(() => ParametersParser.generateRunConfigurationFromParams(['fake param'])) + .raises(new Error(`Cannot parse invalid run configuration parameter ${'fake param'}. Please run --help option to check available options.`)); + }); test('splits between path params and configuration params', () => { - const testPath1 = 'I am a test path' - const testPath2 = 'I am another test path' + const testPath1 = 'I am a test path'; + const testPath2 = 'I am another test path'; - const {pathsParams, configurationParams} = ParametersParser.getPathsAndConfigurationParams([testPath1, testPath2, '-f', '-r']) - assert.areEqual(pathsParams, [testPath1, testPath2]) - assert.areEqual(configurationParams, ['-f', '-r']) + const { pathsParams, configurationParams } = ParametersParser.getPathsAndConfigurationParams([testPath1, testPath2, '-f', '-r']); + assert.areEqual(pathsParams, [testPath1, testPath2]); + assert.areEqual(configurationParams, ['-f', '-r']); }); test('splits between path params and configuration params when path params are empty', () => { - const {pathsParams, configurationParams} = ParametersParser.getPathsAndConfigurationParams(['-f', '-r']) - assert.areEqual(pathsParams, []) - assert.areEqual(configurationParams, ['-f', '-r']) + const { pathsParams, configurationParams } = ParametersParser.getPathsAndConfigurationParams(['-f', '-r']); + assert.areEqual(pathsParams, []); + assert.areEqual(configurationParams, ['-f', '-r']); }); test('splits between path params and configuration params when configuration params are empty', () => { - const testPath1 = 'I am a test path' - const testPath2 = 'I am another test path' + const testPath1 = 'I am a test path'; + const testPath2 = 'I am another test path'; - const {pathsParams, configurationParams} = ParametersParser.getPathsAndConfigurationParams([testPath1, testPath2]) - assert.areEqual(pathsParams, [testPath1, testPath2]) - assert.areEqual(configurationParams, []) + const { pathsParams, configurationParams } = ParametersParser.getPathsAndConfigurationParams([testPath1, testPath2]); + assert.areEqual(pathsParams, [testPath1, testPath2]); + assert.areEqual(configurationParams, []); }); test('splits between path params and configuration params when both are empty', () => { - const {pathsParams, configurationParams} = ParametersParser.getPathsAndConfigurationParams([]) - assert.areEqual(pathsParams, []) - assert.areEqual(configurationParams, []) - }) + const { pathsParams, configurationParams } = ParametersParser.getPathsAndConfigurationParams([]); + assert.areEqual(pathsParams, []); + assert.areEqual(configurationParams, []); + }); test('returns sanitized params when passing a valid list of params', () => { - const sanitizedParams = ParametersParser.sanitizeParameters(['-f', '-r']) - assert.areEqual(sanitizedParams, ['-f', '-r']) + const sanitizedParams = ParametersParser.sanitizeParameters(['-f', '-r']); + assert.areEqual(sanitizedParams, ['-f', '-r']); }); test('returns sanitized params when passing a valid list of params including language params', () => { - const sanitizedParams = ParametersParser.sanitizeParameters(['-f', '-l', 'it', '-r']) - assert.areEqual(sanitizedParams, ['-f', '-r', '-l it']) + const sanitizedParams = ParametersParser.sanitizeParameters(['-f', '-l', 'it', '-r']); + assert.areEqual(sanitizedParams, ['-f', '-r', '-l it']); }); test('throws an error when sending invalid language option', () => { assert - .that(() => ParametersParser.sanitizeParameters(['-l', 'fakeLanguage'])) - .raises(new Error(`Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian`)); - }) + .that(() => ParametersParser.sanitizeParameters(['-l', 'fakeLanguage'])) + .raises(new Error('Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian')); + }); test('throws an error when language parameters do not have the proper order', () => { assert - .that(() => ParametersParser.sanitizeParameters(['it', '-l'])) - .raises(new Error(`Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian`)); - }) + .that(() => ParametersParser.sanitizeParameters(['it', '-l'])) + .raises(new Error('Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian')); + }); }); From 3b4de44c5c1377cf53e4cbd9c1e68cd901b6ee96 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 1 Dec 2024 20:14:07 -0300 Subject: [PATCH 05/18] updating readmes with new console parameters info --- README.md | 12 ++- README_es.md | 266 +++++++++++++++++++++++++++------------------------ 2 files changed, 150 insertions(+), 128 deletions(-) diff --git a/README.md b/README.md index 36598fb6..cbb9bdc3 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,9 @@ ![release-date](https://img.shields.io/github/release-date/ngarbezza/testy.svg?logo=npm) + [![all-contributors](https://img.shields.io/github/all-contributors/ngarbezza/testy?logo=open-source-initiative)](#Contributors) + A very simple JS testing framework, for educational purposes. Live at npm at [@pmoo/testy](https://www.npmjs.com/package/@pmoo/testy). @@ -104,13 +106,21 @@ Testy will look for a `.testyrc.json` configuration file in the project root dir { "directory": "./tests", // directory including your test files "filter": ".*_test.js$", // which convention to use to recognize test files - "language": "en", // language of the output messages. "es" and "en" supported for now + "language": "en", // language of the output messages. "es", "it" and "en" supported for now "failFast": false, // enable/disable fail fast mode (stop as soon as a failed test appears) "randomOrder": false // enable/disable execution of tests in random order "timeoutMs": 1000 // sets the per-test timeout in milliseconds } ``` +You can also pass a configuration through the console when running tests by adding these available options after your test file path: + +- `-f` or `--fail-fast` to enable fail fast mode. +- `-r` or `--randomize` to enable the execution of tests in random order. +- `-l xx` or `--language xx` where `xx` must be either `es` for Spanish, `en` for English or `it` for Italian. + +These console parameters can be sent in any order and combined as you want. + These are all the configuration parameters you can set. Feel free to change it according to your needs. When declaring this configuration, every test suite under the `tests` directory (matching files ending with `*test.js`) will be executed. diff --git a/README_es.md b/README_es.md index 25da5511..49ac166f 100644 --- a/README_es.md +++ b/README_es.md @@ -16,7 +16,7 @@ ![open-issues](https://img.shields.io/github/issues-raw/ngarbezza/testy?logo=github) ![closed-issues](https://img.shields.io/github/issues-closed-raw/ngarbezza/testy?logo=github) ![open-prs](https://img.shields.io/github/issues-pr-raw/ngarbezza/testy?logo=github) - \ +\ ![downloads](https://img.shields.io/npm/dt/@pmoo/testy.svg?logo=npm) ![dependencies](https://img.shields.io/librariesio/release/npm/@pmoo/testy?logo=npm) \ @@ -25,7 +25,9 @@ ![release-date](https://img.shields.io/github/release-date/ngarbezza/testy.svg?logo=npm) + [![all-contributors](https://img.shields.io/github/all-contributors/ngarbezza/testy?logo=open-source-initiative)](#Contribuyentes) + Una simple herramienta de testeo en Javascript, para propósitos educativos. Disponible en npm: [@pmoo/testy](https://www.npmjs.com/package/@pmoo/testy). @@ -47,23 +49,23 @@ o de seguridad listadas [aquí](https://endoflife.date/nodejs)) ## Uso -### Escribiendo suites de test +### Escribiendo suites de test Una suite de test no es más que un archivo cuyo nombre finaliza con `_test.js` y tiene la siguiente forma: ```javascript -import { suite, test, assert } from '@pmoo/testy'; +import { suite, test, assert } from "@pmoo/testy"; -suite('una suite de tests aburrida', () => { - test('42 es 42, no nos sorprende', () => { +suite("una suite de tests aburrida", () => { + test("42 es 42, no nos sorprende", () => { assert.that(42).isEqualTo(42); }); }); ``` -Una suite representa un agrupamiento de tests, y se define llamando a la función `suite(name, body)`, que toma como parámetro el nombre de este agrupamiendo y una función sin argumentos, que representa el contenido de la suite. +Una suite representa un agrupamiento de tests, y se define llamando a la función `suite(name, body)`, que toma como parámetro el nombre de este agrupamiendo y una función sin argumentos, que representa el contenido de la suite. -Un test se escribe llamando a la función `test(name, body)`, que toma como parámetro el nombre del caso de test y una función sin parámetros que representa el cuerpo del test. +Un test se escribe llamando a la función `test(name, body)`, que toma como parámetro el nombre del caso de test y una función sin parámetros que representa el cuerpo del test. Dentro del test se pueden evaluar diferentes aserciones que están documentadas más adelante. @@ -72,13 +74,13 @@ Dentro del test se pueden evaluar diferentes aserciones que están documentadas Puedes ejecutar una suite de test con el siguiente comando: ``` -$ npx testy my_test.js +$ npx testy my_test.js ``` Or, al ejecutar `testy` sin argumentos se ejecutarán todos los tests, por defecto, que están dentro del directorio `tests`: ``` -$ npx testy +$ npx testy ``` También se puede registrar `testy` como script de `test` script en `package.json`: @@ -110,85 +112,94 @@ Testy se puede configurar a través de un archivo llamado `.testyrc.json` que de } ``` +Tambien puedes configurar Testy a traves de la consola de comandos agregando estas opciones detras de la ruta del test a ejecutar: + +- `-f` o `--fail-fast` para habilitar el modo "fail fast" (detener la ejecución en el primer fallo). +- `-r` o `--randomize` para habilitar la ejecución de tests en orden aleatorio. +- `-l xx` o `--language xx` donde `xx` debe ser `es` para Español, `en` para Inglés o `it` para Italiano. + +Estos parámetros pueden ser enviados en cualquier orden y combinados como quieras. + Estos son todos los parámetros de configuración que existen, ajústalos de acuerdo a tus necesidades. Siguiendo este ejemplo de configuración, lo que se va a ejecutar es cada suite de test dentro del directorio `tests`, cuyos nombres de archivos finalicen con `*test.js`. ### Ejemplos y aserciones disponibles -* Aserciones sobre valores booleanos: - * `assert.that(boolean).isTrue()` o `assert.isTrue(boolean)`. Realiza una comparación estricta contra `true` (`object === true`) - * `assert.that(boolean).isFalse()` o `assert.isFalse(boolean)`. Realiza una comparación estricta contra `false` (`object === false`) -* Aserciones de igualdad de objetos: - * `assert.that(actual).isEqualTo(expected)` o `assert.areEqual(actual, expected)`. - * `assert.that(actual).isNotEqualTo(expected)` o `assert.areNotEqual(actual, expected)` - * Las aserciones de igualdad utilizan una comparación (_deep_) basada en el módulo `assert` de Node, y falla si los objetos que están siendo comparados tienen referencias cíclicas. - * El criterio de igualdad en objetos no primitivos puede ser especificado: - * Pasando una función adicional de comparación de dos parámetros a `isEqualTo(expected, criteria)` o `areEqual(actual, expected, criteria)` - * Pasando un nombre de método que el objeto `actual` comprenda: `isEqualTo(expected, 'myEqMessage')` o `areEqual(actual, expected, 'myEqMessage')` - * Por defecto, si `actual` entiende el mensaje `equals`, será utilizado para determinar la comparación - * Si comparamos `undefined` con `undefined` usando `isEqualTo()`, el test fallará. Para chequear explícitamente por el valor `undefined`, se debe utilizar las aserciones `isUndefined()` o `isNotUndefined()` documentadas más adelante. -* Aserciones de identidad de objetos: - * `assert.that(actual).isIdenticalTo(expected)` o `assert.areIdentical(actual, expected)` - * `assert.that(actual).isNotIdenticalTo(expected)` o `assert.areNotIdentical(actual, expected)` - * Las aserciones de identidad comprueban si dos referencias apuntan al mismo objeto utilizando el operador `===`. -* Validar si un objeto es o no `undefined`: - * `assert.that(aValue).isUndefined()` o `assert.isUndefined(aValue)` - * `assert.that(aValue).isNotUndefined()` o `assert.isNotUndefined(aValue)` -* Validar si un objeto es o no `null`: - * `assert.that(aValue).isNull()` o `assert.isNull(aValue)` - * `assert.that(aValue).isNotNull()` o `assert.isNotNull(aValue)` -* Testeo de errores: - * `assert.that(() => { ... }).raises(error)` o con una expresión regular `.raises(/part of message/)` - * `assert.that(() => { ... }).doesNotRaise(error)` - * `assert.that(() => { ... }).doesNotRaiseAnyErrors()` -* Aserciones numéricas: - * Comparación: - * `assert.that(aNumber).isGreaterThan(anotherNumber)` - * `assert.that(aNumber).isLessThan(anotherNumber)` - * `assert.that(aNumber).isGreaterThanOrEqualTo(anotherNumber)` - * `assert.that(aNumber).isLessThanOrEqualTo(anotherNumber)` - * Redondeo - * `assert.that(aNumber).isNearTo(anotherNumber)`. Se puede pasar un segundo parámetro adicional que indica el número de dígitos de precisión que se van a considerar. Por defecto, son `4`. -* Aserciones sobre strings: - * `assert.that(string).matches(regexOrString)` o `assert.isMatching(string, regexOrString)` -* Inclusión de objetos en colecciones (`Array` y `Set`): - * `assert.that(collection).includes(object)` - * `assert.that(collection).doesNotInclude(object)` - * `assert.that(collection).includesExactly(...objects)` -* Verificar si una colección es o no vacía: - * `assert.that(collection).isEmpty()` or `assert.isEmpty(collection)` - * `assert.that(collection).isNotEmpty()` or `assert.isNotEmpty(collection)` - * la colección a verificar puede ser un `Array`, un `String` o un `Set` +- Aserciones sobre valores booleanos: + - `assert.that(boolean).isTrue()` o `assert.isTrue(boolean)`. Realiza una comparación estricta contra `true` (`object === true`) + - `assert.that(boolean).isFalse()` o `assert.isFalse(boolean)`. Realiza una comparación estricta contra `false` (`object === false`) +- Aserciones de igualdad de objetos: + - `assert.that(actual).isEqualTo(expected)` o `assert.areEqual(actual, expected)`. + - `assert.that(actual).isNotEqualTo(expected)` o `assert.areNotEqual(actual, expected)` + - Las aserciones de igualdad utilizan una comparación (_deep_) basada en el módulo `assert` de Node, y falla si los objetos que están siendo comparados tienen referencias cíclicas. + - El criterio de igualdad en objetos no primitivos puede ser especificado: + - Pasando una función adicional de comparación de dos parámetros a `isEqualTo(expected, criteria)` o `areEqual(actual, expected, criteria)` + - Pasando un nombre de método que el objeto `actual` comprenda: `isEqualTo(expected, 'myEqMessage')` o `areEqual(actual, expected, 'myEqMessage')` + - Por defecto, si `actual` entiende el mensaje `equals`, será utilizado para determinar la comparación + - Si comparamos `undefined` con `undefined` usando `isEqualTo()`, el test fallará. Para chequear explícitamente por el valor `undefined`, se debe utilizar las aserciones `isUndefined()` o `isNotUndefined()` documentadas más adelante. +- Aserciones de identidad de objetos: + - `assert.that(actual).isIdenticalTo(expected)` o `assert.areIdentical(actual, expected)` + - `assert.that(actual).isNotIdenticalTo(expected)` o `assert.areNotIdentical(actual, expected)` + - Las aserciones de identidad comprueban si dos referencias apuntan al mismo objeto utilizando el operador `===`. +- Validar si un objeto es o no `undefined`: + - `assert.that(aValue).isUndefined()` o `assert.isUndefined(aValue)` + - `assert.that(aValue).isNotUndefined()` o `assert.isNotUndefined(aValue)` +- Validar si un objeto es o no `null`: + - `assert.that(aValue).isNull()` o `assert.isNull(aValue)` + - `assert.that(aValue).isNotNull()` o `assert.isNotNull(aValue)` +- Testeo de errores: + - `assert.that(() => { ... }).raises(error)` o con una expresión regular `.raises(/part of message/)` + - `assert.that(() => { ... }).doesNotRaise(error)` + - `assert.that(() => { ... }).doesNotRaiseAnyErrors()` +- Aserciones numéricas: + - Comparación: + - `assert.that(aNumber).isGreaterThan(anotherNumber)` + - `assert.that(aNumber).isLessThan(anotherNumber)` + - `assert.that(aNumber).isGreaterThanOrEqualTo(anotherNumber)` + - `assert.that(aNumber).isLessThanOrEqualTo(anotherNumber)` + - Redondeo + - `assert.that(aNumber).isNearTo(anotherNumber)`. Se puede pasar un segundo parámetro adicional que indica el número de dígitos de precisión que se van a considerar. Por defecto, son `4`. +- Aserciones sobre strings: + - `assert.that(string).matches(regexOrString)` o `assert.isMatching(string, regexOrString)` +- Inclusión de objetos en colecciones (`Array` y `Set`): + - `assert.that(collection).includes(object)` + - `assert.that(collection).doesNotInclude(object)` + - `assert.that(collection).includesExactly(...objects)` +- Verificar si una colección es o no vacía: + - `assert.that(collection).isEmpty()` or `assert.isEmpty(collection)` + - `assert.that(collection).isNotEmpty()` or `assert.isNotEmpty(collection)` + - la colección a verificar puede ser un `Array`, un `String` o un `Set` En la carpeta `tests` podrás encontrar más ejemplos y todas las posibles aserciones que puedes escribir. Testy está testeado en sí mismo. ### Otras funcionalidades -* **Ejecutar código antes y después de cada test**: al igual que muchas herramientas de testing, existe una forma de -ejecutar código antes y después de cada test haciendo uso de `before()` y `after()` como parte de la definición de una -_suite_. `before()` y `after()` reciben una función como parámetro y pueden utilizarse una sola vez por _suite_. Ejemplo: - - ```javascript - import { suite, test, assert, before, after } from '@pmoo/testy'; - - suite('usando las funciones before() y after()', () => { - let answer; - - before(() => { - answer = 42; - }); - - test('la respuesta es 42', () => { - assert.that(answer).isEqualTo(42); - }); - - after(() => { - answer = undefined; +- **Ejecutar código antes y después de cada test**: al igual que muchas herramientas de testing, existe una forma de + ejecutar código antes y después de cada test haciendo uso de `before()` y `after()` como parte de la definición de una + _suite_. `before()` y `after()` reciben una función como parámetro y pueden utilizarse una sola vez por _suite_. Ejemplo: + + ```javascript + import { suite, test, assert, before, after } from '@pmoo/testy'; + + suite('usando las funciones before() y after()', () => { + let answer; + + before(() => { + answer = 42; + }); + + test('la respuesta es 42', () => { + assert.that(answer).isEqualTo(42); + }); + + after(() => { + answer = undefined; + }); }); - }); - ``` -* **Soporte para tests pendientes**: un test que no tenga cuerpo, será reportado como pendiente (`[PENDIENTE]`) y no se considerará una falla. -* **Soporte para tests excluidos**: un test se puede excluir añadiendo `.skip()` al final de su definición, esto lo reportará como `[NO EJECUTADO]`. + ``` + +- **Soporte para tests pendientes**: un test que no tenga cuerpo, será reportado como pendiente (`[PENDIENTE]`) y no se considerará una falla. +- **Soporte para tests excluidos**: un test se puede excluir añadiendo `.skip()` al final de su definición, esto lo reportará como `[NO EJECUTADO]`. ```javascript import { suite, test, assert } from '@pmoo/testy'; @@ -200,62 +211,63 @@ _suite_. `before()` y `after()` reciben una función como parámetro y pueden ut }); ``` -* **Soporte para tests asíncronos**: si el código que estás testeando requiere de `async`, es posible hacer `await` -dentro de la definicion del test y luego escribir las aserciones. También es posible hacer llamados asincrónicos en -`before()` y `after()`. Ejemplo: - - ```javascript - import { suite, test, assert, before } from '@pmoo/testy'; - - const promesaUno = async () => Promise.resolve(42); - const promesaDos = async () => Promise.resolve(21); - - suite('usando async y await', () => { - let respuestaUno; - - before(async () => { - respuestaUno = await promesaUno(); - }); - - test('comparando resultados de promesas', async () => { - const respuestaDos = await promesaDos(); - assert.that(respuestaUno).isEqualTo(42); - assert.that(respuestaDos).isEqualTo(21); +- **Soporte para tests asíncronos**: si el código que estás testeando requiere de `async`, es posible hacer `await` + dentro de la definicion del test y luego escribir las aserciones. También es posible hacer llamados asincrónicos en + `before()` y `after()`. Ejemplo: + + ```javascript + import { suite, test, assert, before } from '@pmoo/testy'; + + const promesaUno = async () => Promise.resolve(42); + const promesaDos = async () => Promise.resolve(21); + + suite('usando async y await', () => { + let respuestaUno; + + before(async () => { + respuestaUno = await promesaUno(); + }); + + test('comparando resultados de promesas', async () => { + const respuestaDos = await promesaDos(); + assert.that(respuestaUno).isEqualTo(42); + assert.that(respuestaDos).isEqualTo(21); + }); }); - }); - ``` -* **Modo "fail-fast"**: cuando está habilitado, se detiene apenas encuentra un test que falle o lance un error. Los tests restantes serán marcados como no ejecutados (_skipped_). -* **Ejecutar tests en orden aleatorio**: una buena suite de tests no depende de un orden particular de tests para ejecutarse correctamentee. Activando esta configuración es una buena forma de asegurar eso. -* **Chequeo estricto de presencia de aserciones**: si un test no evalúa ninguna aserción durante su ejecución, el resultado se considera un error. Básicamente, un test que no tiene aserciones es un "mal" test. -* **Explícitamente, marcar un test como fallido o pendiente**: Ejemplos: - - ```javascript - import { suite, test, fail, pending } from '@pmoo/testy'; - - suite('marcando tests explícitamente como fallidos o pendientes', () => { - test('marcando como fallido', () => - fail.with('no debería estar aquí')); - - test('marcando como pendiente', () => - pending.dueTo('no hubo tiempo de finalizarlo')); - }); - ``` - - Al ejecutar veremos los siguientes mensajes: - ``` - [FALLIDO] marcando como fallido - => no debería estar aquí - [PENDIENTE] marcando como pendiente - => no hubo tiempo de finalizarlo - ``` + ``` + +- **Modo "fail-fast"**: cuando está habilitado, se detiene apenas encuentra un test que falle o lance un error. Los tests restantes serán marcados como no ejecutados (_skipped_). +- **Ejecutar tests en orden aleatorio**: una buena suite de tests no depende de un orden particular de tests para ejecutarse correctamentee. Activando esta configuración es una buena forma de asegurar eso. +- **Chequeo estricto de presencia de aserciones**: si un test no evalúa ninguna aserción durante su ejecución, el resultado se considera un error. Básicamente, un test que no tiene aserciones es un "mal" test. +- **Explícitamente, marcar un test como fallido o pendiente**: Ejemplos: + + ```javascript + import { suite, test, fail, pending } from "@pmoo/testy"; + + suite("marcando tests explícitamente como fallidos o pendientes", () => { + test("marcando como fallido", () => fail.with("no debería estar aquí")); + + test("marcando como pendiente", () => + pending.dueTo("no hubo tiempo de finalizarlo")); + }); + ``` + + Al ejecutar veremos los siguientes mensajes: + + ``` + [FALLIDO] marcando como fallido + => no debería estar aquí + [PENDIENTE] marcando como pendiente + => no hubo tiempo de finalizarlo + ``` ## ¿Por qué? ¿Por qué tener una herramienta de tests cuando ya existen otras? La razón principal es que deseamos mantener la simplicidad, algo que no se puede encontrar en las principales herramientas de testing conocidas. -* **Cero dependencias:** Este proyecto no depende de ningún otro paquete de npm para funcionar, lo que facilita su instalación, y lo hace más rápido: esencial para obtener feedback inmediato desarrollando con TDD. Esto es algo bueno también para instalar en lugares donde la conexión a internet no es buena y no queremos perder tiempo descargando múltiples dependencias. -* **Código orientado a objetos entendible:** Esta herramienta es utilizada para enseñar, así que es muy común durante las clases mirar el código para entender cómo se ejecutan los tests, para entender lo que sucede. El objetivo es que los alumnos puedan comprender la herramienta e incluso realizar contribuciones a ella. Intentamos seguir buenas prácticas de diseño con objetos y de _clean code_ en general. -* **Conjunto único de funcionalidad:** Esta herramienta no sigue ninguna especificación ni trata de copiar la funcionalidad de enfoques conocidos de testing (como la forma "xUnit" la forma "xSpec"). La funcionalidad que existe, es la que tiene sentido que esté. +- **Cero dependencias:** Este proyecto no depende de ningún otro paquete de npm para funcionar, lo que facilita su instalación, y lo hace más rápido: esencial para obtener feedback inmediato desarrollando con TDD. Esto es algo bueno también para instalar en lugares donde la conexión a internet no es buena y no queremos perder tiempo descargando múltiples dependencias. +- **Código orientado a objetos entendible:** Esta herramienta es utilizada para enseñar, así que es muy común durante las clases mirar el código para entender cómo se ejecutan los tests, para entender lo que sucede. El objetivo es que los alumnos puedan comprender la herramienta e incluso realizar contribuciones a ella. Intentamos seguir buenas prácticas de diseño con objetos y de _clean code_ en general. +- **Conjunto único de funcionalidad:** Esta herramienta no sigue ninguna especificación ni trata de copiar la funcionalidad de enfoques conocidos de testing (como la forma "xUnit" la forma "xSpec"). La funcionalidad que existe, es la que tiene sentido que esté. ["Design Principles Behind Smalltalk"](https://www.cs.virginia.edu/~evans/cs655/readings/smalltalk.html) es una gran fuente de inspiración para este trabajo. Intentamos seguir los mismos principios aquí. From f76017316fd282e6a2b8cbd89727e4be4b795af8 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 1 Dec 2024 20:20:17 -0300 Subject: [PATCH 06/18] updating ParameterParser class documentation --- lib/config/parameters_parser.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/config/parameters_parser.js b/lib/config/parameters_parser.js index 9f98eb96..79452a6f 100644 --- a/lib/config/parameters_parser.js +++ b/lib/config/parameters_parser.js @@ -1,5 +1,6 @@ /** * I transform a list of console parameters into a valid configuration object. + * I can also differentiate between path parameters and configuration parameters. */ import { isFailFastParam, isLanguageParam, isRandomizeParam } from '../utils.js'; From b668ab2f47f68c5042e59f380895309860dbcfc6 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 1 Dec 2024 20:22:43 -0300 Subject: [PATCH 07/18] fixing typo --- lib/config/parameters_parser.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/config/parameters_parser.js b/lib/config/parameters_parser.js index 79452a6f..ec45c6c1 100644 --- a/lib/config/parameters_parser.js +++ b/lib/config/parameters_parser.js @@ -6,6 +6,7 @@ import { isFailFastParam, isLanguageParam, isRandomizeParam } from '../utils.js' const LANGUAGE_OPTIONS = ['es', 'en', 'it']; export class ParametersParser { + static generateRunConfigurationFromParams(params) { const sanitizedParams = this.sanitizeParameters(params); return this.generateRunConfigurationFromSanitizedParams(sanitizedParams); @@ -20,6 +21,7 @@ export class ParametersParser { return generatedParams; } + static #generateRunConfigurationParameter(param) { const paramParser = [FailFastConfigurationParameterParser, RandomizeConfigurationParameterParser, LanguageConfigurationParameterParser, InvalidConfigurationParameter].find(configurationParameterParser => configurationParameterParser.canHandle(param)); return paramParser.handle(param); @@ -43,7 +45,7 @@ export class ParametersParser { static #validateLanguageOption(params, languageParamIndex) { const languageOption = params[languageParamIndex + 1]; if (!LANGUAGE_OPTIONS.includes(languageOption)) { - throw Error('Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian'); + throw Error('Invalid language option. Please choose an option between es for Spanish, en for English or it for Italian'); } return languageOption; } @@ -73,6 +75,7 @@ export class ParametersParser { } class FailFastConfigurationParameterParser { + static canHandle(consoleParam) { return isFailFastParam(consoleParam); } @@ -83,6 +86,7 @@ class FailFastConfigurationParameterParser { } class RandomizeConfigurationParameterParser { + static canHandle(consoleParam) { return isRandomizeParam(consoleParam); } @@ -93,11 +97,13 @@ class RandomizeConfigurationParameterParser { } class LanguageConfigurationParameterParser { + static canHandle(consoleParam) { return isLanguageParam(consoleParam); } static handle(consoleParam) { + const options = consoleParam.split(' '); return { language: options[1] }; } From 3df7af58c4acf17b57dc83441c37adb4bc8ad86e Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Thu, 5 Dec 2024 18:31:04 -0300 Subject: [PATCH 08/18] fixing broken tests --- lib/config/parameters_parser.js | 4 ++-- tests/configuration/parameters_parser_test.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/config/parameters_parser.js b/lib/config/parameters_parser.js index ec45c6c1..94cba3dd 100644 --- a/lib/config/parameters_parser.js +++ b/lib/config/parameters_parser.js @@ -45,7 +45,7 @@ export class ParametersParser { static #validateLanguageOption(params, languageParamIndex) { const languageOption = params[languageParamIndex + 1]; if (!LANGUAGE_OPTIONS.includes(languageOption)) { - throw Error('Invalid language option. Please choose an option between es for Spanish, en for English or it for Italian'); + throw new Error('Invalid language option. Please choose an option between es for Spanish, en for English or it for Italian'); } return languageOption; } @@ -115,6 +115,6 @@ class InvalidConfigurationParameter { } static handle(configurationParam) { - throw Error(`Cannot parse invalid run configuration parameter ${configurationParam}. Please run --help option to check available options.`); + throw new Error(`Cannot parse invalid run configuration parameter ${configurationParam}. Please run --help option to check available options.`); } } diff --git a/tests/configuration/parameters_parser_test.js b/tests/configuration/parameters_parser_test.js index 1598b1f3..48bcfdf8 100644 --- a/tests/configuration/parameters_parser_test.js +++ b/tests/configuration/parameters_parser_test.js @@ -145,12 +145,12 @@ suite('Parameters parser', () => { test('throws an error when sending invalid language option', () => { assert .that(() => ParametersParser.sanitizeParameters(['-l', 'fakeLanguage'])) - .raises(new Error('Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian')); + .raises(new Error('Invalid language option. Please choose an option between es for Spanish, en for English or it for Italian')); }); test('throws an error when language parameters do not have the proper order', () => { assert .that(() => ParametersParser.sanitizeParameters(['it', '-l'])) - .raises(new Error('Invalid language option. Please choose between an option between es for Spanish, en for English or it for Italian')); + .raises(new Error('Invalid language option. Please choose an option between es for Spanish, en for English or it for Italian')); }); }); From 5d8f8140ed1fe8aeb55e6979481aadb71eab0789 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sat, 7 Dec 2024 17:28:16 -0300 Subject: [PATCH 09/18] removing redundant tests --- tests/configuration/parameters_parser_test.js | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/tests/configuration/parameters_parser_test.js b/tests/configuration/parameters_parser_test.js index 48bcfdf8..53363ee8 100644 --- a/tests/configuration/parameters_parser_test.js +++ b/tests/configuration/parameters_parser_test.js @@ -28,26 +28,6 @@ suite('Parameters parser', () => { assert.areEqual(configuration, { randomOrder: true }); }); - test('returns configuration with english language enabled if passing \'-l en\' en option', () => { - const configuration = ParametersParser.generateRunConfigurationFromParams(['-l en']); - assert.areEqual(configuration, { language: 'en' }); - }); - - test('returns configuration with english language enabled if passing \'-language en\' en option', () => { - const configuration = ParametersParser.generateRunConfigurationFromParams(['--language en']); - assert.areEqual(configuration, { language: 'en' }); - }); - - test('returns configuration with spanish language enabled if passing \'-l es\' en option', () => { - const configuration = ParametersParser.generateRunConfigurationFromParams(['-l es']); - assert.areEqual(configuration, { language: 'es' }); - }); - - test('returns configuration with english language enabled if passing \'-language es\' en option', () => { - const configuration = ParametersParser.generateRunConfigurationFromParams(['--language es']); - assert.areEqual(configuration, { language: 'es' }); - }); - test('returns configuration with italian language enabled if passing \'-l it\' en option', () => { const configuration = ParametersParser.generateRunConfigurationFromParams(['-l it']); assert.areEqual(configuration, { language: 'it' }); @@ -58,14 +38,6 @@ suite('Parameters parser', () => { assert.areEqual(configuration, { language: 'it' }); }); - test('returns configuration with fail fast and randomize modes enabled no matter the order the params are sent', () => { - const configuration1 = ParametersParser.generateRunConfigurationFromParams(['-f', '-r']); - const configuration2 = ParametersParser.generateRunConfigurationFromParams(['-r', '-f']); - - assert.areEqual(configuration1, { failFast: true, randomOrder: true }); - assert.areEqual(configuration2, { failFast: true, randomOrder: true }); - }); - test('returns configuration with fail fast, randomize and english language enabled no matter the order the params are sent', () => { const configuration1 = ParametersParser.generateRunConfigurationFromParams(['-f', '-r', '-l en']); const configuration2 = ParametersParser.generateRunConfigurationFromParams(['-f', '-l en', '-r']); @@ -76,16 +48,6 @@ suite('Parameters parser', () => { assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); }); - test('returns configuration with fail fast, randomize and english language enabled when using long commands versions no matter the order the params are sent', () => { - const configuration1 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '--randomize', '--language en']); - const configuration2 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '--language en', '--randomize']); - const configuration3 = ParametersParser.generateRunConfigurationFromParams(['--language en', '--fail-fast', '--randomize']); - - assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); - assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); - assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); - }); - test('returns configuration with fail fast, randomize and english language enabled when mixing long and short commands no matter the order the params are sent', () => { const configuration1 = ParametersParser.generateRunConfigurationFromParams(['-f', '--randomize', '-l en']); const configuration2 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '-l en', '-r']); From f4329262924c695e5ae56a7b371bc9c5ecc9d395 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sat, 7 Dec 2024 17:32:38 -0300 Subject: [PATCH 10/18] deleting redundant test scenario --- tests/configuration/parameters_parser_test.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/configuration/parameters_parser_test.js b/tests/configuration/parameters_parser_test.js index 53363ee8..acda7587 100644 --- a/tests/configuration/parameters_parser_test.js +++ b/tests/configuration/parameters_parser_test.js @@ -38,16 +38,6 @@ suite('Parameters parser', () => { assert.areEqual(configuration, { language: 'it' }); }); - test('returns configuration with fail fast, randomize and english language enabled no matter the order the params are sent', () => { - const configuration1 = ParametersParser.generateRunConfigurationFromParams(['-f', '-r', '-l en']); - const configuration2 = ParametersParser.generateRunConfigurationFromParams(['-f', '-l en', '-r']); - const configuration3 = ParametersParser.generateRunConfigurationFromParams(['-l en', '-f', '-r']); - - assert.areEqual(configuration1, { failFast: true, randomOrder: true, language: 'en' }); - assert.areEqual(configuration2, { failFast: true, randomOrder: true, language: 'en' }); - assert.areEqual(configuration3, { failFast: true, randomOrder: true, language: 'en' }); - }); - test('returns configuration with fail fast, randomize and english language enabled when mixing long and short commands no matter the order the params are sent', () => { const configuration1 = ParametersParser.generateRunConfigurationFromParams(['-f', '--randomize', '-l en']); const configuration2 = ParametersParser.generateRunConfigurationFromParams(['--fail-fast', '-l en', '-r']); From 878175a76f866c7283386da107feeaf3bc087be6 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sat, 7 Dec 2024 18:40:41 -0300 Subject: [PATCH 11/18] Adding language parameter description to help command --- lib/script_action.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/script_action.js b/lib/script_action.js index dcfb1f0a..991488aa 100644 --- a/lib/script_action.js +++ b/lib/script_action.js @@ -63,10 +63,11 @@ const ShowHelp = { console.log('Usage: \n'); console.log(' testy [-h --help] [-v --version] ...test files or folders...\n'); console.log('Options: \n'); - console.log(' -h, --help Displays this text'); - console.log(' -v, --version Displays the current version'); - console.log(' -f, --fail-fast Enables fail fast option for running tests'); - console.log(' -r, --randomize Enables random order option for running tests'); + console.log(' -h, --help Displays this text'); + console.log(' -v, --version Displays the current version'); + console.log(' -f, --fail-fast Enables fail fast option for running tests'); + console.log(' -r, --randomize Enables random order option for running tests'); + console.log(' -l, --language xx Sets a language for running tests. Available options are \'es\' for Spanish, \'en\' for English and \'it\' for Italian'); this._exitSuccessfully(); }, }; From babd2251854f2dcdacf68e68def6c66606d49678 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 8 Dec 2024 20:33:50 -0300 Subject: [PATCH 12/18] Adding test for withConfiguration method for Configuration class --- tests/core/configuration_test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/core/configuration_test.js b/tests/core/configuration_test.js index 661350a7..a14b7282 100644 --- a/tests/core/configuration_test.js +++ b/tests/core/configuration_test.js @@ -52,4 +52,10 @@ suite('Configuration parameters', () => { assert.that(() => userCustomizedConfiguration.failFastMode()) .raises(new InvalidConfigurationError('Expected a boolean value for failFast configuration, got: I AM AN INVALID VALUE')); }); + + test('can send a configuration and values not present will default to default configuration', () => { + const userCustomizedConfiguration = Configuration.withConfiguration({language: "es", failFast: true}); + assert.areEqual(userCustomizedConfiguration.language(), 'es'); + assert.areEqual(userCustomizedConfiguration.failFastMode(), FailFast.default()); + }); }); From 5ffdac29f51b8435d33661dd55c992c3ee581315 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 29 Dec 2024 12:57:29 -0300 Subject: [PATCH 13/18] Using I18n to know supported languages. Adding test for path parameters sent after configuration parameters --- lib/config/parameters_parser.js | 52 +++++++++++++------ lib/i18n/i18n.js | 6 ++- lib/utils.js | 14 ----- tests/configuration/parameters_parser_test.js | 12 ++++- tests/core/configuration_test.js | 2 +- 5 files changed, 52 insertions(+), 34 deletions(-) diff --git a/lib/config/parameters_parser.js b/lib/config/parameters_parser.js index 94cba3dd..15b7963a 100644 --- a/lib/config/parameters_parser.js +++ b/lib/config/parameters_parser.js @@ -2,9 +2,9 @@ * I transform a list of console parameters into a valid configuration object. * I can also differentiate between path parameters and configuration parameters. */ -import { isFailFastParam, isLanguageParam, isRandomizeParam } from '../utils.js'; +import { I18n } from '../i18n/i18n.js'; +import { isString } from '../utils.js'; -const LANGUAGE_OPTIONS = ['es', 'en', 'it']; export class ParametersParser { static generateRunConfigurationFromParams(params) { @@ -15,14 +15,14 @@ export class ParametersParser { static generateRunConfigurationFromSanitizedParams(sanitizedParams) { let generatedParams = {}; sanitizedParams.forEach(param => { - const runParameter = this.#generateRunConfigurationParameter(param); + const runParameter = this.generateRunConfigurationParameter(param); generatedParams = { ...generatedParams, ...runParameter }; }); return generatedParams; } - static #generateRunConfigurationParameter(param) { + static generateRunConfigurationParameter(param) { const paramParser = [FailFastConfigurationParameterParser, RandomizeConfigurationParameterParser, LanguageConfigurationParameterParser, InvalidConfigurationParameter].find(configurationParameterParser => configurationParameterParser.canHandle(param)); return paramParser.handle(param); } @@ -30,33 +30,40 @@ export class ParametersParser { static sanitizeParameters(params) { const languageParamIndex = params.findIndex(param => param === '-l' || param === '--language'); if (languageParamIndex >= 0) { - return this.#sanitizeLanguageParamOptions(params, languageParamIndex); + return this.sanitizeLanguageParamOptions(params, languageParamIndex); } return params; } - static #sanitizeLanguageParamOptions(params, languageParamIndex) { - const languageOption = this.#validateLanguageOption(params, languageParamIndex); + static sanitizeLanguageParamOptions(params, languageParamIndex) { + const languageOption = this.validateLanguageOption(params, languageParamIndex); const languageConfig = [`-l ${languageOption}`]; - this.#removeLanguageParameters(params, languageParamIndex); + this.removeLanguageParameters(params, languageParamIndex); return [...params, ...languageConfig]; } - static #validateLanguageOption(params, languageParamIndex) { + static validateLanguageOption(params, languageParamIndex) { const languageOption = params[languageParamIndex + 1]; - if (!LANGUAGE_OPTIONS.includes(languageOption)) { - throw new Error('Invalid language option. Please choose an option between es for Spanish, en for English or it for Italian'); + const supportedLanguages = I18n.supportedLanguages(); + if (!supportedLanguages.includes(languageOption)) { + I18n.unsupportedLanguageException(languageOption, supportedLanguages); } return languageOption; } - static #removeLanguageParameters(params, languageParamIndex) { + static removeLanguageParameters(params, languageParamIndex) { params.splice(languageParamIndex, 2); } static getPathsAndConfigurationParams(allParams) { const firstConfigParamIndex = allParams.findIndex(param => this.isConfigurationParam(param)); + if (firstConfigParamIndex >= 0) { + const paramsAfterFirstConfigurationParam = allParams.slice(firstConfigParamIndex); + const thereIsPathParamAfterConfigParams = paramsAfterFirstConfigurationParam.some(param => !this.isConfigurationParam(param)); + if (thereIsPathParamAfterConfigParams) { + throw new Error('Run configuration parameters should always be sent at the end of test paths routes'); + } return { pathsParams: allParams.slice(0, firstConfigParamIndex), configurationParams: allParams.slice(firstConfigParamIndex), @@ -70,14 +77,27 @@ export class ParametersParser { } static isConfigurationParam(param) { - return isFailFastParam(param) || isRandomizeParam(param) || isLanguageParam(param); + return this.isFailFastParam(param) || this.isRandomizeParam(param) || this.isLanguageParam(param); + } + + static isFailFastParam(string) { + return isString(string) && (string === '-f' || string === '--fail-fast'); } + + static isRandomizeParam(string) { + return isString(string) && (string === '-r' || string === '--randomize'); + } + + static isLanguageParam(param) { + const options = param.split(' '); + return isString(options[0]) && (options[0] === '-l' || options[0] === '--language'); + }; } class FailFastConfigurationParameterParser { static canHandle(consoleParam) { - return isFailFastParam(consoleParam); + return ParametersParser.isFailFastParam(consoleParam); } static handle(_consoleParam) { @@ -88,7 +108,7 @@ class FailFastConfigurationParameterParser { class RandomizeConfigurationParameterParser { static canHandle(consoleParam) { - return isRandomizeParam(consoleParam); + return ParametersParser.isRandomizeParam(consoleParam); } static handle(_consoleParam) { @@ -99,7 +119,7 @@ class RandomizeConfigurationParameterParser { class LanguageConfigurationParameterParser { static canHandle(consoleParam) { - return isLanguageParam(consoleParam); + return ParametersParser.isLanguageParam(consoleParam); } static handle(consoleParam) { diff --git a/lib/i18n/i18n.js b/lib/i18n/i18n.js index e3825e45..07ec0c4d 100644 --- a/lib/i18n/i18n.js +++ b/lib/i18n/i18n.js @@ -37,6 +37,10 @@ class I18n { return `Translation key '${key}' not found in translations for language: ${languageCode}!`; } + static unsupportedLanguageException(languageCode, supportedLanguages) { + throw new Error(`Language '${languageCode}' is not supported. Allowed values: ${supportedLanguages.join(', ')}`); + } + constructor(languageCode, translations = TRANSLATIONS) { this.#assertLanguageIsSupported(languageCode, translations); this.#languageCode = languageCode; @@ -55,7 +59,7 @@ class I18n { #assertLanguageIsSupported(languageCode, translations) { const supportedLanguages = I18n.supportedLanguages(translations); if (!supportedLanguages.includes(languageCode)) { - throw new Error(`Language '${languageCode}' is not supported. Allowed values: ${supportedLanguages.join(', ')}`); + I18n.unsupportedLanguageException(languageCode, supportedLanguages); } } diff --git a/lib/utils.js b/lib/utils.js index b27bb913..bf5125d9 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -78,16 +78,6 @@ const isFunction = object => const isUndefined = object => typeof object === 'undefined'; -const isFailFastParam = string => - isString(string) && (string === '-f' || string === '--fail-fast'); - -const isRandomizeParam = string => - isString(string) && (string === '-r' || string === '--randomize'); - -const isLanguageParam = param => { - const options = param.split(' '); - return isString(options[0]) && (options[0] === '-l' || options[0] === '--language'); -}; const notNullOrUndefined = object => !isUndefined(object) && object !== null; @@ -183,8 +173,4 @@ export { errorDetailOf, // metaprogramming detectUserCallingLocation, - // parsing - isFailFastParam, - isRandomizeParam, - isLanguageParam, }; diff --git a/tests/configuration/parameters_parser_test.js b/tests/configuration/parameters_parser_test.js index acda7587..447d4444 100644 --- a/tests/configuration/parameters_parser_test.js +++ b/tests/configuration/parameters_parser_test.js @@ -1,5 +1,6 @@ import { assert, suite, test } from '../../lib/testy.js'; import { ParametersParser } from '../../lib/config/parameters_parser.js'; +import { I18n } from '../../lib/i18n/i18n.js'; suite('Parameters parser', () => { @@ -84,6 +85,13 @@ suite('Parameters parser', () => { assert.areEqual(configurationParams, []); }); + test('throws an error when file path params are sent after configuration parameters', () => { + const testPath1 = 'I am a test path'; + assert + .that(() => ParametersParser.getPathsAndConfigurationParams(['-f', testPath1])) + .raises(new Error('Run configuration parameters should always be sent at the end of test paths routes')); + }); + test('returns sanitized params when passing a valid list of params', () => { const sanitizedParams = ParametersParser.sanitizeParameters(['-f', '-r']); assert.areEqual(sanitizedParams, ['-f', '-r']); @@ -97,12 +105,12 @@ suite('Parameters parser', () => { test('throws an error when sending invalid language option', () => { assert .that(() => ParametersParser.sanitizeParameters(['-l', 'fakeLanguage'])) - .raises(new Error('Invalid language option. Please choose an option between es for Spanish, en for English or it for Italian')); + .raises(new Error(`Language '${'fakeLanguage'}' is not supported. Allowed values: ${I18n.supportedLanguages().join(', ')}`)); }); test('throws an error when language parameters do not have the proper order', () => { assert .that(() => ParametersParser.sanitizeParameters(['it', '-l'])) - .raises(new Error('Invalid language option. Please choose an option between es for Spanish, en for English or it for Italian')); + .raises(new Error(`Language '${undefined}' is not supported. Allowed values: ${I18n.supportedLanguages().join(', ')}`)); }); }); diff --git a/tests/core/configuration_test.js b/tests/core/configuration_test.js index a14b7282..8242f9ae 100644 --- a/tests/core/configuration_test.js +++ b/tests/core/configuration_test.js @@ -54,7 +54,7 @@ suite('Configuration parameters', () => { }); test('can send a configuration and values not present will default to default configuration', () => { - const userCustomizedConfiguration = Configuration.withConfiguration({language: "es", failFast: true}); + const userCustomizedConfiguration = Configuration.withConfiguration({ language: 'es', failFast: true }); assert.areEqual(userCustomizedConfiguration.language(), 'es'); assert.areEqual(userCustomizedConfiguration.failFastMode(), FailFast.default()); }); From 3947dfe5fed93de41a03b502e8bde4810a5a47e8 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 29 Dec 2024 13:38:54 -0300 Subject: [PATCH 14/18] Merging user configuration from file with desired configuration from console --- lib/config/configuration.js | 3 ++- lib/config/parameters_parser.js | 16 +++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/config/configuration.js b/lib/config/configuration.js index 207327c1..428ac0bc 100644 --- a/lib/config/configuration.js +++ b/lib/config/configuration.js @@ -35,7 +35,8 @@ export class Configuration { static withConfiguration(aConfiguration) { const defaultConfiguration = require('./default_configuration.json'); - return new this(aConfiguration, defaultConfiguration); + const userConfiguration = require(resolvePathFor(CONFIGURATION_FILE_NAME)); + return new this({ ...userConfiguration, ...aConfiguration }, defaultConfiguration); } constructor(userConfiguration, defaultConfiguration) { this.#userConfigurationOptions = userConfiguration; diff --git a/lib/config/parameters_parser.js b/lib/config/parameters_parser.js index 15b7963a..27c4dbff 100644 --- a/lib/config/parameters_parser.js +++ b/lib/config/parameters_parser.js @@ -1,10 +1,10 @@ +import { I18n } from '../i18n/i18n.js'; +import { isString } from '../utils.js'; + /** * I transform a list of console parameters into a valid configuration object. * I can also differentiate between path parameters and configuration parameters. */ -import { I18n } from '../i18n/i18n.js'; -import { isString } from '../utils.js'; - export class ParametersParser { static generateRunConfigurationFromParams(params) { @@ -56,11 +56,11 @@ export class ParametersParser { } static getPathsAndConfigurationParams(allParams) { - const firstConfigParamIndex = allParams.findIndex(param => this.isConfigurationParam(param)); + const firstConfigParamIndex = allParams.findIndex(param => this.isRawConfigurationParam(param)); if (firstConfigParamIndex >= 0) { const paramsAfterFirstConfigurationParam = allParams.slice(firstConfigParamIndex); - const thereIsPathParamAfterConfigParams = paramsAfterFirstConfigurationParam.some(param => !this.isConfigurationParam(param)); + const thereIsPathParamAfterConfigParams = paramsAfterFirstConfigurationParam.some(param => !this.isRawConfigurationParam(param)); if (thereIsPathParamAfterConfigParams) { throw new Error('Run configuration parameters should always be sent at the end of test paths routes'); } @@ -80,6 +80,12 @@ export class ParametersParser { return this.isFailFastParam(param) || this.isRandomizeParam(param) || this.isLanguageParam(param); } + static isRawConfigurationParam(param) { + // pre sanitization + const supportedLanguages = I18n.supportedLanguages(); + return this.isConfigurationParam(param) || supportedLanguages.includes(param); + } + static isFailFastParam(string) { return isString(string) && (string === '-f' || string === '--fail-fast'); } From df898c3597e8901cd40c305cc2ece8b5e1706003 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 29 Dec 2024 13:50:13 -0300 Subject: [PATCH 15/18] Reverting changes in Readme file --- README.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/README.md b/README.md index cbb9bdc3..36598fb6 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,7 @@ ![release-date](https://img.shields.io/github/release-date/ngarbezza/testy.svg?logo=npm) - [![all-contributors](https://img.shields.io/github/all-contributors/ngarbezza/testy?logo=open-source-initiative)](#Contributors) - A very simple JS testing framework, for educational purposes. Live at npm at [@pmoo/testy](https://www.npmjs.com/package/@pmoo/testy). @@ -106,21 +104,13 @@ Testy will look for a `.testyrc.json` configuration file in the project root dir { "directory": "./tests", // directory including your test files "filter": ".*_test.js$", // which convention to use to recognize test files - "language": "en", // language of the output messages. "es", "it" and "en" supported for now + "language": "en", // language of the output messages. "es" and "en" supported for now "failFast": false, // enable/disable fail fast mode (stop as soon as a failed test appears) "randomOrder": false // enable/disable execution of tests in random order "timeoutMs": 1000 // sets the per-test timeout in milliseconds } ``` -You can also pass a configuration through the console when running tests by adding these available options after your test file path: - -- `-f` or `--fail-fast` to enable fail fast mode. -- `-r` or `--randomize` to enable the execution of tests in random order. -- `-l xx` or `--language xx` where `xx` must be either `es` for Spanish, `en` for English or `it` for Italian. - -These console parameters can be sent in any order and combined as you want. - These are all the configuration parameters you can set. Feel free to change it according to your needs. When declaring this configuration, every test suite under the `tests` directory (matching files ending with `*test.js`) will be executed. From 763574fc2af947fe23f80b5447c142ff1fd1a412 Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 29 Dec 2024 13:50:56 -0300 Subject: [PATCH 16/18] Reverting changes in Readme_es file --- README_es.md | 266 ++++++++++++++++++++++++--------------------------- 1 file changed, 127 insertions(+), 139 deletions(-) diff --git a/README_es.md b/README_es.md index 49ac166f..25da5511 100644 --- a/README_es.md +++ b/README_es.md @@ -16,7 +16,7 @@ ![open-issues](https://img.shields.io/github/issues-raw/ngarbezza/testy?logo=github) ![closed-issues](https://img.shields.io/github/issues-closed-raw/ngarbezza/testy?logo=github) ![open-prs](https://img.shields.io/github/issues-pr-raw/ngarbezza/testy?logo=github) -\ + \ ![downloads](https://img.shields.io/npm/dt/@pmoo/testy.svg?logo=npm) ![dependencies](https://img.shields.io/librariesio/release/npm/@pmoo/testy?logo=npm) \ @@ -25,9 +25,7 @@ ![release-date](https://img.shields.io/github/release-date/ngarbezza/testy.svg?logo=npm) - [![all-contributors](https://img.shields.io/github/all-contributors/ngarbezza/testy?logo=open-source-initiative)](#Contribuyentes) - Una simple herramienta de testeo en Javascript, para propósitos educativos. Disponible en npm: [@pmoo/testy](https://www.npmjs.com/package/@pmoo/testy). @@ -49,23 +47,23 @@ o de seguridad listadas [aquí](https://endoflife.date/nodejs)) ## Uso -### Escribiendo suites de test +### Escribiendo suites de test Una suite de test no es más que un archivo cuyo nombre finaliza con `_test.js` y tiene la siguiente forma: ```javascript -import { suite, test, assert } from "@pmoo/testy"; +import { suite, test, assert } from '@pmoo/testy'; -suite("una suite de tests aburrida", () => { - test("42 es 42, no nos sorprende", () => { +suite('una suite de tests aburrida', () => { + test('42 es 42, no nos sorprende', () => { assert.that(42).isEqualTo(42); }); }); ``` -Una suite representa un agrupamiento de tests, y se define llamando a la función `suite(name, body)`, que toma como parámetro el nombre de este agrupamiendo y una función sin argumentos, que representa el contenido de la suite. +Una suite representa un agrupamiento de tests, y se define llamando a la función `suite(name, body)`, que toma como parámetro el nombre de este agrupamiendo y una función sin argumentos, que representa el contenido de la suite. -Un test se escribe llamando a la función `test(name, body)`, que toma como parámetro el nombre del caso de test y una función sin parámetros que representa el cuerpo del test. +Un test se escribe llamando a la función `test(name, body)`, que toma como parámetro el nombre del caso de test y una función sin parámetros que representa el cuerpo del test. Dentro del test se pueden evaluar diferentes aserciones que están documentadas más adelante. @@ -74,13 +72,13 @@ Dentro del test se pueden evaluar diferentes aserciones que están documentadas Puedes ejecutar una suite de test con el siguiente comando: ``` -$ npx testy my_test.js +$ npx testy my_test.js ``` Or, al ejecutar `testy` sin argumentos se ejecutarán todos los tests, por defecto, que están dentro del directorio `tests`: ``` -$ npx testy +$ npx testy ``` También se puede registrar `testy` como script de `test` script en `package.json`: @@ -112,94 +110,85 @@ Testy se puede configurar a través de un archivo llamado `.testyrc.json` que de } ``` -Tambien puedes configurar Testy a traves de la consola de comandos agregando estas opciones detras de la ruta del test a ejecutar: - -- `-f` o `--fail-fast` para habilitar el modo "fail fast" (detener la ejecución en el primer fallo). -- `-r` o `--randomize` para habilitar la ejecución de tests en orden aleatorio. -- `-l xx` o `--language xx` donde `xx` debe ser `es` para Español, `en` para Inglés o `it` para Italiano. - -Estos parámetros pueden ser enviados en cualquier orden y combinados como quieras. - Estos son todos los parámetros de configuración que existen, ajústalos de acuerdo a tus necesidades. Siguiendo este ejemplo de configuración, lo que se va a ejecutar es cada suite de test dentro del directorio `tests`, cuyos nombres de archivos finalicen con `*test.js`. ### Ejemplos y aserciones disponibles -- Aserciones sobre valores booleanos: - - `assert.that(boolean).isTrue()` o `assert.isTrue(boolean)`. Realiza una comparación estricta contra `true` (`object === true`) - - `assert.that(boolean).isFalse()` o `assert.isFalse(boolean)`. Realiza una comparación estricta contra `false` (`object === false`) -- Aserciones de igualdad de objetos: - - `assert.that(actual).isEqualTo(expected)` o `assert.areEqual(actual, expected)`. - - `assert.that(actual).isNotEqualTo(expected)` o `assert.areNotEqual(actual, expected)` - - Las aserciones de igualdad utilizan una comparación (_deep_) basada en el módulo `assert` de Node, y falla si los objetos que están siendo comparados tienen referencias cíclicas. - - El criterio de igualdad en objetos no primitivos puede ser especificado: - - Pasando una función adicional de comparación de dos parámetros a `isEqualTo(expected, criteria)` o `areEqual(actual, expected, criteria)` - - Pasando un nombre de método que el objeto `actual` comprenda: `isEqualTo(expected, 'myEqMessage')` o `areEqual(actual, expected, 'myEqMessage')` - - Por defecto, si `actual` entiende el mensaje `equals`, será utilizado para determinar la comparación - - Si comparamos `undefined` con `undefined` usando `isEqualTo()`, el test fallará. Para chequear explícitamente por el valor `undefined`, se debe utilizar las aserciones `isUndefined()` o `isNotUndefined()` documentadas más adelante. -- Aserciones de identidad de objetos: - - `assert.that(actual).isIdenticalTo(expected)` o `assert.areIdentical(actual, expected)` - - `assert.that(actual).isNotIdenticalTo(expected)` o `assert.areNotIdentical(actual, expected)` - - Las aserciones de identidad comprueban si dos referencias apuntan al mismo objeto utilizando el operador `===`. -- Validar si un objeto es o no `undefined`: - - `assert.that(aValue).isUndefined()` o `assert.isUndefined(aValue)` - - `assert.that(aValue).isNotUndefined()` o `assert.isNotUndefined(aValue)` -- Validar si un objeto es o no `null`: - - `assert.that(aValue).isNull()` o `assert.isNull(aValue)` - - `assert.that(aValue).isNotNull()` o `assert.isNotNull(aValue)` -- Testeo de errores: - - `assert.that(() => { ... }).raises(error)` o con una expresión regular `.raises(/part of message/)` - - `assert.that(() => { ... }).doesNotRaise(error)` - - `assert.that(() => { ... }).doesNotRaiseAnyErrors()` -- Aserciones numéricas: - - Comparación: - - `assert.that(aNumber).isGreaterThan(anotherNumber)` - - `assert.that(aNumber).isLessThan(anotherNumber)` - - `assert.that(aNumber).isGreaterThanOrEqualTo(anotherNumber)` - - `assert.that(aNumber).isLessThanOrEqualTo(anotherNumber)` - - Redondeo - - `assert.that(aNumber).isNearTo(anotherNumber)`. Se puede pasar un segundo parámetro adicional que indica el número de dígitos de precisión que se van a considerar. Por defecto, son `4`. -- Aserciones sobre strings: - - `assert.that(string).matches(regexOrString)` o `assert.isMatching(string, regexOrString)` -- Inclusión de objetos en colecciones (`Array` y `Set`): - - `assert.that(collection).includes(object)` - - `assert.that(collection).doesNotInclude(object)` - - `assert.that(collection).includesExactly(...objects)` -- Verificar si una colección es o no vacía: - - `assert.that(collection).isEmpty()` or `assert.isEmpty(collection)` - - `assert.that(collection).isNotEmpty()` or `assert.isNotEmpty(collection)` - - la colección a verificar puede ser un `Array`, un `String` o un `Set` +* Aserciones sobre valores booleanos: + * `assert.that(boolean).isTrue()` o `assert.isTrue(boolean)`. Realiza una comparación estricta contra `true` (`object === true`) + * `assert.that(boolean).isFalse()` o `assert.isFalse(boolean)`. Realiza una comparación estricta contra `false` (`object === false`) +* Aserciones de igualdad de objetos: + * `assert.that(actual).isEqualTo(expected)` o `assert.areEqual(actual, expected)`. + * `assert.that(actual).isNotEqualTo(expected)` o `assert.areNotEqual(actual, expected)` + * Las aserciones de igualdad utilizan una comparación (_deep_) basada en el módulo `assert` de Node, y falla si los objetos que están siendo comparados tienen referencias cíclicas. + * El criterio de igualdad en objetos no primitivos puede ser especificado: + * Pasando una función adicional de comparación de dos parámetros a `isEqualTo(expected, criteria)` o `areEqual(actual, expected, criteria)` + * Pasando un nombre de método que el objeto `actual` comprenda: `isEqualTo(expected, 'myEqMessage')` o `areEqual(actual, expected, 'myEqMessage')` + * Por defecto, si `actual` entiende el mensaje `equals`, será utilizado para determinar la comparación + * Si comparamos `undefined` con `undefined` usando `isEqualTo()`, el test fallará. Para chequear explícitamente por el valor `undefined`, se debe utilizar las aserciones `isUndefined()` o `isNotUndefined()` documentadas más adelante. +* Aserciones de identidad de objetos: + * `assert.that(actual).isIdenticalTo(expected)` o `assert.areIdentical(actual, expected)` + * `assert.that(actual).isNotIdenticalTo(expected)` o `assert.areNotIdentical(actual, expected)` + * Las aserciones de identidad comprueban si dos referencias apuntan al mismo objeto utilizando el operador `===`. +* Validar si un objeto es o no `undefined`: + * `assert.that(aValue).isUndefined()` o `assert.isUndefined(aValue)` + * `assert.that(aValue).isNotUndefined()` o `assert.isNotUndefined(aValue)` +* Validar si un objeto es o no `null`: + * `assert.that(aValue).isNull()` o `assert.isNull(aValue)` + * `assert.that(aValue).isNotNull()` o `assert.isNotNull(aValue)` +* Testeo de errores: + * `assert.that(() => { ... }).raises(error)` o con una expresión regular `.raises(/part of message/)` + * `assert.that(() => { ... }).doesNotRaise(error)` + * `assert.that(() => { ... }).doesNotRaiseAnyErrors()` +* Aserciones numéricas: + * Comparación: + * `assert.that(aNumber).isGreaterThan(anotherNumber)` + * `assert.that(aNumber).isLessThan(anotherNumber)` + * `assert.that(aNumber).isGreaterThanOrEqualTo(anotherNumber)` + * `assert.that(aNumber).isLessThanOrEqualTo(anotherNumber)` + * Redondeo + * `assert.that(aNumber).isNearTo(anotherNumber)`. Se puede pasar un segundo parámetro adicional que indica el número de dígitos de precisión que se van a considerar. Por defecto, son `4`. +* Aserciones sobre strings: + * `assert.that(string).matches(regexOrString)` o `assert.isMatching(string, regexOrString)` +* Inclusión de objetos en colecciones (`Array` y `Set`): + * `assert.that(collection).includes(object)` + * `assert.that(collection).doesNotInclude(object)` + * `assert.that(collection).includesExactly(...objects)` +* Verificar si una colección es o no vacía: + * `assert.that(collection).isEmpty()` or `assert.isEmpty(collection)` + * `assert.that(collection).isNotEmpty()` or `assert.isNotEmpty(collection)` + * la colección a verificar puede ser un `Array`, un `String` o un `Set` En la carpeta `tests` podrás encontrar más ejemplos y todas las posibles aserciones que puedes escribir. Testy está testeado en sí mismo. ### Otras funcionalidades -- **Ejecutar código antes y después de cada test**: al igual que muchas herramientas de testing, existe una forma de - ejecutar código antes y después de cada test haciendo uso de `before()` y `after()` como parte de la definición de una - _suite_. `before()` y `after()` reciben una función como parámetro y pueden utilizarse una sola vez por _suite_. Ejemplo: - - ```javascript - import { suite, test, assert, before, after } from '@pmoo/testy'; - - suite('usando las funciones before() y after()', () => { - let answer; - - before(() => { - answer = 42; - }); - - test('la respuesta es 42', () => { - assert.that(answer).isEqualTo(42); - }); - - after(() => { - answer = undefined; - }); +* **Ejecutar código antes y después de cada test**: al igual que muchas herramientas de testing, existe una forma de +ejecutar código antes y después de cada test haciendo uso de `before()` y `after()` como parte de la definición de una +_suite_. `before()` y `after()` reciben una función como parámetro y pueden utilizarse una sola vez por _suite_. Ejemplo: + + ```javascript + import { suite, test, assert, before, after } from '@pmoo/testy'; + + suite('usando las funciones before() y after()', () => { + let answer; + + before(() => { + answer = 42; }); - ``` - -- **Soporte para tests pendientes**: un test que no tenga cuerpo, será reportado como pendiente (`[PENDIENTE]`) y no se considerará una falla. -- **Soporte para tests excluidos**: un test se puede excluir añadiendo `.skip()` al final de su definición, esto lo reportará como `[NO EJECUTADO]`. + + test('la respuesta es 42', () => { + assert.that(answer).isEqualTo(42); + }); + + after(() => { + answer = undefined; + }); + }); + ``` +* **Soporte para tests pendientes**: un test que no tenga cuerpo, será reportado como pendiente (`[PENDIENTE]`) y no se considerará una falla. +* **Soporte para tests excluidos**: un test se puede excluir añadiendo `.skip()` al final de su definición, esto lo reportará como `[NO EJECUTADO]`. ```javascript import { suite, test, assert } from '@pmoo/testy'; @@ -211,63 +200,62 @@ En la carpeta `tests` podrás encontrar más ejemplos y todas las posibles aserc }); ``` -- **Soporte para tests asíncronos**: si el código que estás testeando requiere de `async`, es posible hacer `await` - dentro de la definicion del test y luego escribir las aserciones. También es posible hacer llamados asincrónicos en - `before()` y `after()`. Ejemplo: - - ```javascript - import { suite, test, assert, before } from '@pmoo/testy'; - - const promesaUno = async () => Promise.resolve(42); - const promesaDos = async () => Promise.resolve(21); - - suite('usando async y await', () => { - let respuestaUno; - - before(async () => { - respuestaUno = await promesaUno(); - }); - - test('comparando resultados de promesas', async () => { - const respuestaDos = await promesaDos(); - assert.that(respuestaUno).isEqualTo(42); - assert.that(respuestaDos).isEqualTo(21); - }); +* **Soporte para tests asíncronos**: si el código que estás testeando requiere de `async`, es posible hacer `await` +dentro de la definicion del test y luego escribir las aserciones. También es posible hacer llamados asincrónicos en +`before()` y `after()`. Ejemplo: + + ```javascript + import { suite, test, assert, before } from '@pmoo/testy'; + + const promesaUno = async () => Promise.resolve(42); + const promesaDos = async () => Promise.resolve(21); + + suite('usando async y await', () => { + let respuestaUno; + + before(async () => { + respuestaUno = await promesaUno(); }); - ``` - -- **Modo "fail-fast"**: cuando está habilitado, se detiene apenas encuentra un test que falle o lance un error. Los tests restantes serán marcados como no ejecutados (_skipped_). -- **Ejecutar tests en orden aleatorio**: una buena suite de tests no depende de un orden particular de tests para ejecutarse correctamentee. Activando esta configuración es una buena forma de asegurar eso. -- **Chequeo estricto de presencia de aserciones**: si un test no evalúa ninguna aserción durante su ejecución, el resultado se considera un error. Básicamente, un test que no tiene aserciones es un "mal" test. -- **Explícitamente, marcar un test como fallido o pendiente**: Ejemplos: - - ```javascript - import { suite, test, fail, pending } from "@pmoo/testy"; - - suite("marcando tests explícitamente como fallidos o pendientes", () => { - test("marcando como fallido", () => fail.with("no debería estar aquí")); - - test("marcando como pendiente", () => - pending.dueTo("no hubo tiempo de finalizarlo")); - }); - ``` - - Al ejecutar veremos los siguientes mensajes: - - ``` - [FALLIDO] marcando como fallido - => no debería estar aquí - [PENDIENTE] marcando como pendiente - => no hubo tiempo de finalizarlo - ``` + + test('comparando resultados de promesas', async () => { + const respuestaDos = await promesaDos(); + assert.that(respuestaUno).isEqualTo(42); + assert.that(respuestaDos).isEqualTo(21); + }); + }); + ``` +* **Modo "fail-fast"**: cuando está habilitado, se detiene apenas encuentra un test que falle o lance un error. Los tests restantes serán marcados como no ejecutados (_skipped_). +* **Ejecutar tests en orden aleatorio**: una buena suite de tests no depende de un orden particular de tests para ejecutarse correctamentee. Activando esta configuración es una buena forma de asegurar eso. +* **Chequeo estricto de presencia de aserciones**: si un test no evalúa ninguna aserción durante su ejecución, el resultado se considera un error. Básicamente, un test que no tiene aserciones es un "mal" test. +* **Explícitamente, marcar un test como fallido o pendiente**: Ejemplos: + + ```javascript + import { suite, test, fail, pending } from '@pmoo/testy'; + + suite('marcando tests explícitamente como fallidos o pendientes', () => { + test('marcando como fallido', () => + fail.with('no debería estar aquí')); + + test('marcando como pendiente', () => + pending.dueTo('no hubo tiempo de finalizarlo')); + }); + ``` + + Al ejecutar veremos los siguientes mensajes: + ``` + [FALLIDO] marcando como fallido + => no debería estar aquí + [PENDIENTE] marcando como pendiente + => no hubo tiempo de finalizarlo + ``` ## ¿Por qué? ¿Por qué tener una herramienta de tests cuando ya existen otras? La razón principal es que deseamos mantener la simplicidad, algo que no se puede encontrar en las principales herramientas de testing conocidas. -- **Cero dependencias:** Este proyecto no depende de ningún otro paquete de npm para funcionar, lo que facilita su instalación, y lo hace más rápido: esencial para obtener feedback inmediato desarrollando con TDD. Esto es algo bueno también para instalar en lugares donde la conexión a internet no es buena y no queremos perder tiempo descargando múltiples dependencias. -- **Código orientado a objetos entendible:** Esta herramienta es utilizada para enseñar, así que es muy común durante las clases mirar el código para entender cómo se ejecutan los tests, para entender lo que sucede. El objetivo es que los alumnos puedan comprender la herramienta e incluso realizar contribuciones a ella. Intentamos seguir buenas prácticas de diseño con objetos y de _clean code_ en general. -- **Conjunto único de funcionalidad:** Esta herramienta no sigue ninguna especificación ni trata de copiar la funcionalidad de enfoques conocidos de testing (como la forma "xUnit" la forma "xSpec"). La funcionalidad que existe, es la que tiene sentido que esté. +* **Cero dependencias:** Este proyecto no depende de ningún otro paquete de npm para funcionar, lo que facilita su instalación, y lo hace más rápido: esencial para obtener feedback inmediato desarrollando con TDD. Esto es algo bueno también para instalar en lugares donde la conexión a internet no es buena y no queremos perder tiempo descargando múltiples dependencias. +* **Código orientado a objetos entendible:** Esta herramienta es utilizada para enseñar, así que es muy común durante las clases mirar el código para entender cómo se ejecutan los tests, para entender lo que sucede. El objetivo es que los alumnos puedan comprender la herramienta e incluso realizar contribuciones a ella. Intentamos seguir buenas prácticas de diseño con objetos y de _clean code_ en general. +* **Conjunto único de funcionalidad:** Esta herramienta no sigue ninguna especificación ni trata de copiar la funcionalidad de enfoques conocidos de testing (como la forma "xUnit" la forma "xSpec"). La funcionalidad que existe, es la que tiene sentido que esté. ["Design Principles Behind Smalltalk"](https://www.cs.virginia.edu/~evans/cs655/readings/smalltalk.html) es una gran fuente de inspiración para este trabajo. Intentamos seguir los mismos principios aquí. From 991fce95ed73fcc2e9bf3263c6b360e7cf05027d Mon Sep 17 00:00:00 2001 From: mariabelenamat Date: Sun, 29 Dec 2024 13:59:19 -0300 Subject: [PATCH 17/18] Updating readme files --- README.md | 7 +++++++ README_es.md | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/README.md b/README.md index 36598fb6..e39b930a 100644 --- a/README.md +++ b/README.md @@ -108,9 +108,16 @@ Testy will look for a `.testyrc.json` configuration file in the project root dir "failFast": false, // enable/disable fail fast mode (stop as soon as a failed test appears) "randomOrder": false // enable/disable execution of tests in random order "timeoutMs": 1000 // sets the per-test timeout in milliseconds + "language": "en", // language of the output messages. "es", "it" and "en" supported for now } ``` +You can also pass a configuration through the console when running tests by adding these available options after your test file path: +- `-f` or `--fail-fast` to enable fail fast mode. +- `-r` or `--randomize` to enable the execution of tests in random order. +- `-l xx` or `--language xx` where `xx` must be either `es` for Spanish, `en` for English or `it` for Italian. +These console parameters can be sent in any order and combined as you want. + These are all the configuration parameters you can set. Feel free to change it according to your needs. When declaring this configuration, every test suite under the `tests` directory (matching files ending with `*test.js`) will be executed. diff --git a/README_es.md b/README_es.md index 25da5511..d2615ad9 100644 --- a/README_es.md +++ b/README_es.md @@ -107,8 +107,14 @@ Testy se puede configurar a través de un archivo llamado `.testyrc.json` que de "failFast": false, // habilita/deshabilita el modo "fail fast" (detener la ejecución en el primer fallo) "randomOrder": false // habilita/deshabilita la ejecución de tests en orden aleatorio. "timeoutMs": 1000 // asigna el tiempo límite de ejecución por cada test (en milisegundos) + "language": "en", // lenguaje que usara la consola. "es", "it" y "en" disponibles por el momento. } ``` +Puedes pasar parametros de configuracion a traves de la consola agregando estas opciones despues de las rutas de tests que quieras ejecutar: +- `-f` o `--fail-fast` para habiltiar el modo fail fast. +- `-r` o `--randomize` para habilitar la ejecución de tests en orden aleatorio. +- `-l xx` o `--language xx` done `xx` debe ser `es` para Español, `en` para Ingles o `it` para Italiano. +Estos parametros por consola pueden ser enviados en el orden que desees y puedes combinarlos como quieras Estos son todos los parámetros de configuración que existen, ajústalos de acuerdo a tus necesidades. Siguiendo este ejemplo de configuración, lo que se va a ejecutar es cada suite de test dentro del directorio `tests`, cuyos nombres de archivos finalicen con `*test.js`. From 9d2f56dfd49d44bb745cf03e58e4266c01f6ea99 Mon Sep 17 00:00:00 2001 From: Nahuel Garbezza Date: Sun, 29 Dec 2024 21:04:07 -0300 Subject: [PATCH 18/18] docs: correct minor formatting/markdown issues --- README_es.md | 21 ++++++++++------- .../0002-place-utilities-in-utils-module.md | 10 +++++--- .../0013-support-for-es-modules-only.md | 6 ++--- lib/core/equality_assertion_strategy.js | 4 ++-- lib/i18n/i18n_messages.js | 2 +- lib/script_action.js | 23 +++++++++++-------- 6 files changed, 40 insertions(+), 26 deletions(-) diff --git a/README_es.md b/README_es.md index d2615ad9..f57bca3e 100644 --- a/README_es.md +++ b/README_es.md @@ -61,7 +61,7 @@ suite('una suite de tests aburrida', () => { }); ``` -Una suite representa un agrupamiento de tests, y se define llamando a la función `suite(name, body)`, que toma como parámetro el nombre de este agrupamiendo y una función sin argumentos, que representa el contenido de la suite. +Una suite representa un agrupamiento de tests, y se define llamando a la función `suite(name, body)`, que toma como parámetro el nombre de este agrupamiento y una función sin argumentos, que representa el contenido de la suite. Un test se escribe llamando a la función `test(name, body)`, que toma como parámetro el nombre del caso de test y una función sin parámetros que representa el cuerpo del test. @@ -110,14 +110,19 @@ Testy se puede configurar a través de un archivo llamado `.testyrc.json` que de "language": "en", // lenguaje que usara la consola. "es", "it" y "en" disponibles por el momento. } ``` -Puedes pasar parametros de configuracion a traves de la consola agregando estas opciones despues de las rutas de tests que quieras ejecutar: -- `-f` o `--fail-fast` para habiltiar el modo fail fast. + +Puedes pasar parámetros de configuración a través de la consola agregando estas opciones después de las rutas de tests +que quieras ejecutar: +- `-f` o `--fail-fast` para habilitar el modo _fail fast_. - `-r` o `--randomize` para habilitar la ejecución de tests en orden aleatorio. -- `-l xx` o `--language xx` done `xx` debe ser `es` para Español, `en` para Ingles o `it` para Italiano. -Estos parametros por consola pueden ser enviados en el orden que desees y puedes combinarlos como quieras +- `-l xx` o `--language xx` done `xx` debe ser `es` para español, `en` para inglés o `it` para italiano. + +Estos parámetros por consola pueden ser enviados en el orden que desees y puedes combinarlos como quieras. Toman +precedencia respecto a los que estén configurados en `.testyrc.json`. Estos son todos los parámetros de configuración que existen, ajústalos de acuerdo a tus necesidades. -Siguiendo este ejemplo de configuración, lo que se va a ejecutar es cada suite de test dentro del directorio `tests`, cuyos nombres de archivos finalicen con `*test.js`. +Siguiendo este ejemplo de configuración, lo que se va a ejecutar es cada suite de test dentro del directorio `tests`, +cuyos nombres de archivos finalicen con `*test.js`. ### Ejemplos y aserciones disponibles @@ -207,7 +212,7 @@ _suite_. `before()` y `after()` reciben una función como parámetro y pueden ut ``` * **Soporte para tests asíncronos**: si el código que estás testeando requiere de `async`, es posible hacer `await` -dentro de la definicion del test y luego escribir las aserciones. También es posible hacer llamados asincrónicos en +dentro de la definición del test y luego escribir las aserciones. También es posible hacer llamados asincrónicos en `before()` y `after()`. Ejemplo: ```javascript @@ -231,7 +236,7 @@ dentro de la definicion del test y luego escribir las aserciones. También es po }); ``` * **Modo "fail-fast"**: cuando está habilitado, se detiene apenas encuentra un test que falle o lance un error. Los tests restantes serán marcados como no ejecutados (_skipped_). -* **Ejecutar tests en orden aleatorio**: una buena suite de tests no depende de un orden particular de tests para ejecutarse correctamentee. Activando esta configuración es una buena forma de asegurar eso. +* **Ejecutar tests en orden aleatorio**: una buena suite de tests no depende de un orden particular de tests para ejecutarse correctamente. Activando esta configuración es una buena forma de asegurar eso. * **Chequeo estricto de presencia de aserciones**: si un test no evalúa ninguna aserción durante su ejecución, el resultado se considera un error. Básicamente, un test que no tiene aserciones es un "mal" test. * **Explícitamente, marcar un test como fallido o pendiente**: Ejemplos: diff --git a/doc/decisions/0002-place-utilities-in-utils-module.md b/doc/decisions/0002-place-utilities-in-utils-module.md index ddc7d101..71d215f3 100644 --- a/doc/decisions/0002-place-utilities-in-utils-module.md +++ b/doc/decisions/0002-place-utilities-in-utils-module.md @@ -8,14 +8,18 @@ Accepted ## Context -Having control of all the utilitary functions the tool might need. +Having control of all the utility functions the tool might need. ## Decision -Use the `Utils` module for any responsibility whose domain does not seem to be part of other objects' essence. Every time you feel you need a "helper" function, it is a good candidate for `Utils`. If you need to rely on `typeof`, it is also a good sign for needing `Utils`. We want to maximize reuse of these functions by having in a single, "static" place. We understand this might be a temporary solution. +Use the `Utils` module for any responsibility whose domain does not seem to be part of other objects' essence. Every +time you feel you need a "helper" function, it is a good candidate for `Utils`. If you need to rely on `typeof`, it is +also a good sign for needing `Utils`. We want to maximize reuse of these functions by having in a single, "static" +place. We understand this might be a temporary solution. ## Consequences 1. We will have a centralized place of all the logic that needs to be placed somewhere. -2. `Utils` module can potentially become a hotspot in the code, or a file that grows at a high pace. A subfolder with particular Utils might be needed at some point in the future. +2. `Utils` module can potentially become a hotspot in the code, or a file that grows at a high pace. A subfolder with + particular utils might be needed at some point in the future. 3. `Utils` is also a good place for interaction with external dependencies, although we want to keep zero dependencies. diff --git a/doc/decisions/0013-support-for-es-modules-only.md b/doc/decisions/0013-support-for-es-modules-only.md index d9bce6c1..85ab4526 100644 --- a/doc/decisions/0013-support-for-es-modules-only.md +++ b/doc/decisions/0013-support-for-es-modules-only.md @@ -13,8 +13,8 @@ that is only supported in Node, and not in other environments like Deno or the b This article contains a detailed comparison of CommonJS and ES Modules: https://www.knowledgehut.com/blog/web-development/commonjs-vs-es-modules -This tool uses modules a lot, as it dynamically requires files written by the users of Testy, and the asyncronous -features of ES makes things easier and brings more reliability than synchronous CommonJS modules. +This tool uses modules a lot, as it dynamically requires files written by the users of Testy, and the asynchronous +features of ES makes things easier and brings more reliability than synchronous CommonJS modules. ## Decision @@ -25,5 +25,5 @@ which is against the spirit of this project. ## Consequences * This is a disruptive change for users. Projects that uses CommonJS will need to migrate to ES, at least to load the -tests. + tests. * This will represent a breaking change, to be released in a new major version. diff --git a/lib/core/equality_assertion_strategy.js b/lib/core/equality_assertion_strategy.js index 62ae7d46..03a8873d 100644 --- a/lib/core/equality_assertion_strategy.js +++ b/lib/core/equality_assertion_strategy.js @@ -31,7 +31,7 @@ export class EqualityAssertionStrategy { return false; } - evaluate(_actual, _expected, _criterie) { + evaluate(_actual, _expected, _criteria) { return subclassResponsibility(); } } @@ -41,7 +41,7 @@ class BothPartsUndefined extends EqualityAssertionStrategy { return isUndefined(actual) && isUndefined(expected); } - evaluate(_actual, _expected, _criterie) { + evaluate(_actual, _expected, _criteria) { return { comparisonResult: undefined, overrideFailureMessage: () => I18nMessage.of('equality_assertion_failed_due_to_undetermination'), diff --git a/lib/i18n/i18n_messages.js b/lib/i18n/i18n_messages.js index 41287188..0ad76043 100644 --- a/lib/i18n/i18n_messages.js +++ b/lib/i18n/i18n_messages.js @@ -118,7 +118,7 @@ class SingleI18nMessage extends I18nMessage { } toJson() { - return { key: this.#key, oarams: this.#params }; + return { key: this.#key, params: this.#params }; } } diff --git a/lib/script_action.js b/lib/script_action.js index 991488aa..bffe3ef8 100644 --- a/lib/script_action.js +++ b/lib/script_action.js @@ -59,15 +59,20 @@ const ShowHelp = { async execute(_params) { const { description } = this._packageData(); - console.log(`Testy: ${description}\n`); - console.log('Usage: \n'); - console.log(' testy [-h --help] [-v --version] ...test files or folders...\n'); - console.log('Options: \n'); - console.log(' -h, --help Displays this text'); - console.log(' -v, --version Displays the current version'); - console.log(' -f, --fail-fast Enables fail fast option for running tests'); - console.log(' -r, --randomize Enables random order option for running tests'); - console.log(' -l, --language xx Sets a language for running tests. Available options are \'es\' for Spanish, \'en\' for English and \'it\' for Italian'); + console.log(` +Testy: ${description} + +Usage: + + testy [-h --help] [-v --version] ...test files or folders... + +Options: + -h, --help Displays this text + -v, --version Displays the current version + -f, --fail-fast Enables fail fast option for running tests + -r, --randomize Enables random order option for running tests + -l, --language xx Sets a language for running tests. Available options are 'es' for Spanish, 'en' for English and 'it' for Italian + `); this._exitSuccessfully(); }, };