Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@pmoo/testy

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@pmoo/testy - npm Package Compare versions

Comparing version 5.0.2 to 5.1.0

lib/assertion.js

37

CHANGELOG.md

@@ -11,2 +11,36 @@ # Changelog

## [5.1.0] - 2021-01-13
This release includes a lot of contributions (4 new contributors!), and several refactorings to continue improving the quality of the tool.
### Added
* [[feature] added after() hook to run code after each test](https://github.com/ngarbezza/testy/issues/135), thank you @adico1!
* [[feature] isIncludedIn() and isNotIncludedIn() assertions](https://github.com/ngarbezza/testy/issues/75), thank you @ask-imran for your first contribution!
* [[feature] warning message when no tests found](https://github.com/ngarbezza/testy/issues/157), thank you @niyonx for your first contribution!
* [[feature] show error when a requested file does not exist](https://github.com/ngarbezza/testy/issues/158), thank you @chelsieng for your first contribution!
* [[feature] global error handler](https://github.com/ngarbezza/testy/issues/177)
### Fixed
* [[bug] suite and test names cannot be empty](https://github.com/ngarbezza/testy/issues/136), thank you @ask-imran!
* [[bug] includes() and doesNotInclude() matchers only work on Arrays](https://github.com/ngarbezza/testy/issues/130), thank you @trochepablo for your first contribution!
* [[bug] color for pending summary was not painted](https://github.com/ngarbezza/testy/issues/173)
* [[bug] it was possible to mark tests as pending without specifying reason](https://github.com/ngarbezza/testy/issues/172)
### Refactored
* [rename "master" branch to "main"](https://github.com/ngarbezza/testy/issues/133); also, an ADR was added to track the decision that we want a better vocabulary
* [parametrizable i18n messages](https://github.com/ngarbezza/testy/issues/71)
* [write more tests for the i18n module](https://github.com/ngarbezza/testy/issues/179)
* [throw error objects instead of strings](https://github.com/ngarbezza/testy/issues/176)
* [speed up tests by not creating error messages on successful assertions](https://github.com/ngarbezza/testy/commit/531d1d6360c93a3aae2f11bd0c957c45e93cd35c)
* [added some npm scripts for test coverage and dependencies graph](https://github.com/ngarbezza/testy/commit/d4ca1fa7804b2353458eb214d1f302fefc9fed9d)
* [changes in modularization: extract assertion and test result reporter](https://github.com/ngarbezza/testy/commit/4913b5a187bc0700b3de4b5b1a9adc0e2a8dc57e)
* add more tests and increased the current coverage ([example 1](https://github.com/ngarbezza/testy/commit/be41db9872ea4490b5dae238d6c553b214667326), [example 2](https://github.com/ngarbezza/testy/commit/28b2ee51078300382c7398cb40203d6e40ca26d1))
* formatter object decoupled from console ui (ADR 0004 added [here](https://github.com/ngarbezza/testy/commit/9ab5c55fd4738054effef1e1aab15824a62c6750))
* avoid test doubles at all (ADR 0005 added [here](https://github.com/ngarbezza/testy/commit/5a65fbc6e6e58b1f03f996c381240d4a1b8c3875)), removed test runner double
... and more minor cleanups.
## [5.0.2] - 2020-10-13

@@ -209,3 +243,4 @@

[Unreleased]: https://github.com/ngarbezza/testy/compare/v5.0.2...HEAD
[Unreleased]: https://github.com/ngarbezza/testy/compare/v5.1.0...HEAD
[5.1.0]: https://github.com/ngarbezza/testy/compare/v5.0.2...v5.1.0
[5.0.2]: https://github.com/ngarbezza/testy/compare/v5.0.1...v5.0.2

@@ -212,0 +247,0 @@ [5.0.1]: https://github.com/ngarbezza/testy/compare/v5.0.0...v5.0.1

254

lib/asserter.js
'use strict';
const Utils = require('./utils');
const EqualityAssertionStrategy = require('./equality_assertion_strategy');
const TestResult = require('./test_result');
const TestResultReporter = require('./test_result_reporter');
const Assertion = require('./assertion');
const { I18nMessage } = require('./i18n');
class TestResultReporter {
constructor(runner) {
this._runner = runner;
}
const { isStringWithContent } = require('./utils');
report(result) {
this._runner.setResultForCurrentTest(result);
}
translated(key) {
return this._runner._i18n.translate(key);
}
}
class FailureGenerator extends TestResultReporter {
with(description) {
this.report(TestResult.failure(description || this.translated('explicitly_failed')));
this.report(TestResult.failure(description || I18nMessage.of('explicitly_failed')));
}

@@ -29,4 +18,12 @@ }

dueTo(reason) {
this.report(TestResult.explicitlyMarkedAsPending(reason));
if (isStringWithContent(reason)) {
this.report(TestResult.explicitlyMarkedAsPending(reason));
} else {
this.report(TestResult.error(this.invalidReasonErrorMessage()));
}
}
invalidReasonErrorMessage() {
return I18nMessage.of('invalid_pending_reason');
}
}

@@ -84,225 +81,2 @@

class Assertion extends TestResultReporter {
constructor(runner, actual) {
super(runner);
this._actual = actual;
}
// Boolean assertions
isTrue() {
this._booleanAssertion(true, this.translated('be_true'));
}
isFalse() {
this._booleanAssertion(false, this.translated('be_false'));
}
// Undefined value assertions
isUndefined() {
this._undefinedAssertion(this.translated('be_undefined'));
}
isNotUndefined() {
this._notUndefinedAssertion(this.translated('be_defined'));
}
// Null value assertions
isNull() {
this._nullAssertion(this.translated('be_null'));
}
isNotNull() {
this._notNullAssertion(this.translated('be_not_null'));
}
// Equality assertions
isEqualTo(expected, criteria) {
this._equalityAssertion(expected, criteria, true);
}
isNotEqualTo(expected, criteria) {
this._equalityAssertion(expected, criteria, false);
}
// Collection assertions
includes(expectedObject, equalityCriteria) {
const resultIsSuccessful = this._actual.find(element =>
this._areConsideredEqual(element, expectedObject, equalityCriteria));
const failureMessage = `${this.translated('include')} ${Utils.prettyPrint(expectedObject)}`;
this._reportAssertionResult(resultIsSuccessful, failureMessage);
}
doesNotInclude(expectedObject, equalityCriteria) {
const resultIsSuccessful = !this._actual.find(element =>
this._areConsideredEqual(element, expectedObject, equalityCriteria));
const failureMessage = `${this.translated('not_include')} ${Utils.prettyPrint(expectedObject)}`;
this._reportAssertionResult(resultIsSuccessful, failureMessage);
}
includesExactly(...objects) {
const resultIsSuccessful = this._haveElementsConsideredEqual(this._actual, objects);
const failureMessage = `${this.translated('include_exactly')} ${Utils.prettyPrint(objects)}`;
this._reportAssertionResult(resultIsSuccessful, failureMessage);
}
isEmpty() {
const resultIsSuccessful = Utils.numberOfElements(this._actual || {}) === 0
&& Utils.notNullOrUndefined(this._actual);
const failureMessage = this.translated('be_empty');
this._reportAssertionResult(resultIsSuccessful, failureMessage);
}
isNotEmpty() {
const setValueWhenUndefined = this._actual || {};
const resultIsSuccessful = Utils.numberOfElements(setValueWhenUndefined) > 0;
const failureMessage = this.translated('be_not_empty');
this._reportAssertionResult(resultIsSuccessful, failureMessage);
}
// Exception assertions
raises(errorExpectation) {
this._exceptionAssertion(errorExpectation, true);
}
doesNotRaise(notExpectedError) {
this._exceptionAssertion(notExpectedError, false);
}
doesNotRaiseAnyErrors() {
let noErrorsOccurred = false;
let failureMessage = '';
try {
this._actual.call();
noErrorsOccurred = true;
} catch (error) {
noErrorsOccurred = false;
failureMessage = `${this.translated('expected_no_errors')}, ${this.translated('but')} ${Utils.prettyPrint(error)} ${this.translated('was_raised')}`;
} finally {
this._reportAssertionResult(noErrorsOccurred, failureMessage, true);
}
}
// Numeric assertions
isNearTo(number, precisionDigits = 4) {
const result = Number.parseFloat((this._actual).toFixed(precisionDigits)) === number;
const failureMessage = `be near to ${number} (using ${precisionDigits} precision digits)`;
this._reportAssertionResult(result, failureMessage, false);
}
// String assertions
matches(regex) {
const result = this._actual.match(regex);
const failureMessage = `${this.translated('match')} ${regex}`;
this._reportAssertionResult(result, failureMessage, false);
}
// Private
_equalityAssertion(expected, criteria, shouldBeEqual) {
const { comparisonResult, additionalFailureMessage, overrideFailureMessage } =
EqualityAssertionStrategy.evaluate(this._actual, expected, criteria);
const resultIsSuccessful = shouldBeEqual ? comparisonResult : !comparisonResult;
if (overrideFailureMessage) {
this._reportAssertionResult(resultIsSuccessful, overrideFailureMessage, true);
} else {
const expectationMessage = shouldBeEqual ? this.translated('be_equal_to') : this.translated('be_not_equal_to');
const failureMessage = `${expectationMessage} ${Utils.prettyPrint(expected)}${additionalFailureMessage}`;
this._reportAssertionResult(resultIsSuccessful, failureMessage, false);
}
}
_areConsideredEqual(objectOne, objectTwo, equalityCriteria) {
return EqualityAssertionStrategy.evaluate(objectOne, objectTwo, equalityCriteria).comparisonResult;
}
_booleanAssertion(expectedBoolean, failureMessage) {
const resultIsSuccessful = this._actual === expectedBoolean;
this._reportAssertionResult(resultIsSuccessful, failureMessage);
}
_undefinedAssertion(failureMessage) {
const resultIsSuccessful = this._actual === undefined;
this._reportAssertionResult(resultIsSuccessful, failureMessage);
}
_notUndefinedAssertion(failureMessage) {
const resultIsSuccessful = this._actual !== undefined;
this._reportAssertionResult(resultIsSuccessful, failureMessage);
}
_nullAssertion(failureMessage) {
const resultIsSuccessful = this._actual === null;
this._reportAssertionResult(resultIsSuccessful, failureMessage);
}
_notNullAssertion(failureMessage) {
const resultIsSuccessful = this._actual !== null;
this._reportAssertionResult(resultIsSuccessful, failureMessage);
}
_exceptionAssertion(errorExpectation, shouldFail) {
let hasFailed = false;
let actualError = undefined;
try {
this._actual();
hasFailed = !shouldFail;
} catch (error) {
actualError = error;
const errorCheck = this._checkIfErrorMatchesExpectation(errorExpectation, actualError);
hasFailed = shouldFail ? errorCheck : !errorCheck;
} finally {
const toHappenOrNot = shouldFail ? this.translated('to_happen') : this.translated('not_to_happen');
const expectedErrorIntroduction = `${this.translated('expected')} ${this.translated('expecting_error')} ${Utils.prettyPrint(errorExpectation)} ${toHappenOrNot}`;
const failureMessage = typeof actualError !== 'undefined' ?
`${expectedErrorIntroduction}, ${this.translated('but_got')} ${Utils.prettyPrint(actualError)} ${this.translated('instead')}` : expectedErrorIntroduction;
this._reportAssertionResult(hasFailed, failureMessage, true);
}
}
_checkIfErrorMatchesExpectation(errorExpectation, actualError) {
if (Utils.isRegex(errorExpectation)) {
return errorExpectation.test(actualError);
} else {
return this._areConsideredEqual(actualError, errorExpectation);
}
}
_reportAssertionResult(wasSuccess, matcherFailureMessage, overrideFailureMessage) {
if (wasSuccess) {
this.report(TestResult.success());
} else {
const defaultFailureMessage = `${this.translated('expected')} ${this._actualResultAsString()} ${this.translated('to')}${matcherFailureMessage}`;
this.report(TestResult.failure(overrideFailureMessage ? matcherFailureMessage : defaultFailureMessage));
}
}
_actualResultAsString() {
return Utils.prettyPrint(this._actual);
}
_haveElementsConsideredEqual(collectionOne, collectionTwo) {
const collectionOneArray = Array.from(collectionOne);
const collectionTwoArray = Array.from(collectionTwo);
if (collectionOneArray.length !== collectionTwoArray.length) return false;
for (let i = 0; i < collectionOne.length; i++) {
const includedInOne = collectionOne.find(element =>
this._areConsideredEqual(element, collectionTwoArray[i]));
const includedInTwo = collectionTwo.find(element =>
this._areConsideredEqual(element, collectionOneArray[i]));
if (!includedInOne || !includedInTwo) return false;
}
return true;
}
}
module.exports = { Asserter, FailureGenerator, PendingMarker };

@@ -15,3 +15,3 @@ 'use strict';

userConfiguration = require(resolvePathFor(CONFIGURATION_FILE_NAME));
} catch(error) {
} catch (error) {
userConfiguration = {};

@@ -36,4 +36,8 @@ }

filter() {
return new RegExp(this._configurationOptions.filter);
return new RegExp(this.filterRaw());
}
filterRaw() {
return this._configurationOptions.filter;
}

@@ -40,0 +44,0 @@ language() {

'use strict';
const I18n = require('./i18n');
const { I18n } = require('./i18n');
const Formatter = require('./formatter');
// Colors and emphasis
const off = '\x1b[0m';
const bold = '\x1b[1m';
const grey = '\x1b[30m';
const red = '\x1b[31m';
const green = '\x1b[32m';
const yellow = '\x1b[33m';
class ConsoleUI {
constructor() {
this.useLanguage(I18n.defaultLanguage());
static successfulExitCode() {
return 0;
}
static failedExitCode() {
return 1;
}
// Callbacks for runner/suite/test

@@ -22,21 +19,12 @@

return {
whenPending: test => {
this._displayResult(this.translated('wip'), test, yellow);
if (test.isExplicitlyMarkedPending())
this._displayResultDetail(test.result().reason());
},
whenSkipped: test => {
this._displayResult(this.translated('skip'), test, grey);
},
whenSuccess: test => {
this._displayResult(this.translated('ok'), test, green);
},
whenFailed: test => {
this._displayResult(this.translated('fail'), test, red);
this._displayResultDetail(test.result().failureMessage());
},
whenErrored: test => {
this._displayResult(this.translated('error'), test, red);
this._displayResultDetail(test.result().failureMessage());
}
whenPending: test =>
this._formatter.displayPendingResult(test),
whenSkipped: test =>
this._formatter.displaySkippedResult(test),
whenSuccess: test =>
this._formatter.displaySuccessResult(test),
whenFailed: test =>
this._formatter.displayFailureResult(test),
whenErrored: test =>
this._formatter.displayErrorResult(test),
};

@@ -47,12 +35,6 @@ }

return {
onStart: suite => {
console.log(`\n${suite.name()}:`);
this._displaySeparator('-');
},
onFinish: suite => {
this._displaySeparator('-');
console.log(`${this.translated('summary_of')} ${suite.name()}:`);
this._displayCountFor(suite);
this._displaySeparator();
}
onStart: suite =>
this._formatter.displaySuiteStart(suite),
onFinish: suite =>
this._formatter.displaySuiteEnd(suite),
};

@@ -63,101 +45,33 @@ }

return {
onFinish: runner => {
this.displayErrorsAndFailuresSummary(runner);
this._displaySummary(runner);
}
onFinish: runner =>
this._formatter.displayRunnerEnd(runner),
onSuccess: _runner =>
this._exitWithCode(ConsoleUI.successfulExitCode()),
onFailure: _runner =>
this._exitWithCode(ConsoleUI.failedExitCode()),
};
}
displayInitialSummary(configuration, paths) {
this._displaySeparator();
console.log(this._inBold(this.translated('starting_testy')));
this._displayRunConfiguration(paths, configuration);
this._displaySeparator();
start(configuration, paths, runnerBlock) {
this._formatter.start();
this._formatter.displayInitialInformation(configuration, paths);
runnerBlock.call();
this._formatter.end();
}
measuringTotalTime(code) {
const name = this.translated('total_time');
console.time(name);
code();
console.timeEnd(name);
}
useLanguage(language) {
this._i18n = new I18n(language);
const i18n = new I18n(language);
this._formatter = new Formatter(console, i18n);
}
translated(key) {
return this._i18n.translate(key);
exitWithError(errorMessage) {
this._formatter.displayError(errorMessage);
this._exitWithCode(ConsoleUI.failedExitCode());
}
_displayRunConfiguration(paths, configuration) {
const testPaths = this.translated('running_tests_in');
const failFast = this.translated('fail_fast');
const randomOrder = this.translated('random_order');
const padding = Math.max(testPaths.length, failFast.length, randomOrder.length);
console.log(`${testPaths.padEnd(padding)} : ${paths}`);
console.log(`${failFast.padEnd(padding)} : ${this._humanBoolean(configuration.failFastMode().enabled())}`);
console.log(`${randomOrder.padEnd(padding)} : ${this._humanBoolean(configuration.randomOrder())}`);
_exitWithCode(exitCode) {
process.exit(exitCode);
}
_displayIfNonZero(quantity, word, color = off) {
return quantity > 0 ? `, ${this._withColor(`${quantity} ${word}`, color)}` : '';
}
_displayResult(result, test, color) {
console.log(`[${color}${this._inBold(result)}] ${this._withColor(test.name(), color)}`);
}
_displayResultDetail(detail) {
console.log(` => ${detail}`);
}
_displaySeparator(character = '=') {
console.log(character.repeat(80));
}
_displayCountFor(runner) {
const passedCount = this._displayIfNonZero(runner.successCount(), this.translated('passed'), green);
const failureCount = this._displayIfNonZero(runner.failuresCount(), this.translated('failed'), red);
const errorCount = this._displayIfNonZero(runner.errorsCount(), this.translated('errors'), red);
const pendingCount = this._displayIfNonZero(runner.pendingCount(), this.translated('pending'));
const skippedCount = this._displayIfNonZero(runner.skippedCount(), this.translated('skipped'), yellow);
console.log(`${runner.totalCount()} test(s)${passedCount}${failureCount}${errorCount}${pendingCount}${skippedCount}`);
}
displayErrorsAndFailuresSummary(runner) {
if (runner.hasErrorsOrFailures()) {
console.log(`\n${this.translated('failures_summary')}`);
runner.allFailuresAndErrors().forEach(test => {
if (test.isFailure()) {
this._displayResult(this.translated('fail'), test, red);
} else {
this._displayResult(this.translated('error'), test, red);
}
this._displayResultDetail(test.result().failureMessage());
});
this._displaySeparator();
}
}
_displaySummary(runner) {
console.log(`\n${this.translated('total')}`);
this._displayCountFor(runner);
this._displaySeparator();
}
_inBold(text) {
return `${bold}${text}${off}`;
}
_withColor(text, color) {
return `${color}${text}${off}`;
}
_humanBoolean(boolean) {
return boolean === true ? this.translated('yes') : this.translated('no');
}
}
module.exports = ConsoleUI;
'use strict';
const Utils = require('./utils');
const { I18nMessage } = require('./i18n');
const { isString, isFunction, isUndefined, respondsTo, isCyclic, deepStrictEqual } = require('./utils');

@@ -28,3 +29,3 @@ const EqualityAssertionStrategy = {

appliesTo(actual, expected) {
return actual === undefined && expected === undefined;
return isUndefined(actual) && isUndefined(expected);
},

@@ -35,3 +36,3 @@

comparisonResult: false,
overrideFailureMessage: 'Equality cannot be determined. Both parts are undefined',
overrideFailureMessage: () => I18nMessage.of('equality_assertion_failed_due_to_undetermination'),
};

@@ -45,3 +46,3 @@ },

appliesTo(actual, expected, criteria) {
return Utils.isFunction(criteria);
return isFunction(criteria);
},

@@ -52,3 +53,3 @@

comparisonResult: criteria(actual, expected),
additionalFailureMessage: ''
additionalFailureMessage: () => I18nMessage.empty(),
};

@@ -62,3 +63,3 @@ },

appliesTo(actual, expected, criteria) {
return Utils.isString(criteria);
return isString(criteria);
},

@@ -75,3 +76,3 @@

_comparisonCanBeMade(actual, expected, criteria) {
return Utils.respondsTo(actual, criteria) && Utils.respondsTo(expected, criteria);
return respondsTo(actual, criteria) && respondsTo(expected, criteria);
},

@@ -82,3 +83,3 @@

comparisonResult: actual[criteria](expected),
additionalFailureMessage: ''
additionalFailureMessage: () => I18nMessage.empty(),
};

@@ -90,3 +91,3 @@ },

comparisonResult: false,
additionalFailureMessage: ` Equality check failed. Objects do not have '${criteria}' property`
additionalFailureMessage: () => I18nMessage.of('equality_assertion_failed_due_to_missing_property', criteria),
};

@@ -100,3 +101,3 @@ },

appliesTo(actual, _expected) {
return Utils.respondsTo(actual, 'equals');
return respondsTo(actual, 'equals');
},

@@ -107,3 +108,3 @@

comparisonResult: actual.equals(expected),
additionalFailureMessage: ''
additionalFailureMessage: () => I18nMessage.empty(),
};

@@ -117,3 +118,3 @@ },

appliesTo(actual, expected) {
return Utils.isCyclic(actual) || Utils.isCyclic(expected);
return isCyclic(actual) || isCyclic(expected);
},

@@ -124,3 +125,3 @@

comparisonResult: false,
additionalFailureMessage: ' (circular references found, equality check cannot be done. Please compare objects\' properties individually)'
additionalFailureMessage: () => I18nMessage.of('equality_assertion_failed_due_to_circular_references'),
};

@@ -139,4 +140,4 @@ },

return {
comparisonResult: Utils.deepStrictEqual(actual, expected),
additionalFailureMessage: ''
comparisonResult: deepStrictEqual(actual, expected),
additionalFailureMessage: () => I18nMessage.empty(),
};

@@ -143,0 +144,0 @@ },

'use strict';
const TRANSLATIONS = require('./translations');
const { subclassResponsibility, isUndefined } = require('./utils');
class I18nMessage {
static of(key, ...params) {
return new InternationalizedMessage(key, ...params);
}
static empty() {
return new EmptyMessage();
}
static joined(messages, joinedBy) {
const messagesWithContent = messages.filter(message => message.hasContent());
if (messagesWithContent.length === 0) {
throw new Error('No messages with content have been found to be composed');
} else if (messagesWithContent.length === 1) {
return messagesWithContent[0];
} else {
return new ComposedInternationalizedMessage(messagesWithContent, joinedBy);
}
}
expressedIn(_locale) {
subclassResponsibility();
}
hasContent() {
subclassResponsibility();
}
}
class EmptyMessage extends I18nMessage {
expressedIn(_locale) {
return '';
}
hasContent() {
return false;
}
}
class ComposedInternationalizedMessage extends I18nMessage {
constructor(messages, joinString) {
super();
this._messages = messages;
this._joinString = joinString;
Object.freeze(this);
}
expressedIn(locale) {
return this._messages
.map(message => message.expressedIn(locale))
.join(this._joinString);
}
hasContent() {
return true;
}
}
class InternationalizedMessage extends I18nMessage {
constructor(key, ...params) {
super();
this._key = key;
this._params = params;
Object.freeze(this);
}
expressedIn(locale) {
return locale.translate(this._key, ...this._params);
}
hasContent() {
return true;
}
}
class I18n {
static default(translations = TRANSLATIONS) {
return new this(this.defaultLanguage(), translations);
}
static defaultLanguage() {

@@ -10,3 +91,4 @@ return 'en';

constructor(languageCode = I18n.defaultLanguage(), translations = TRANSLATIONS) {
constructor(languageCode, translations = TRANSLATIONS) {
this._assertLanguageIsSupported(languageCode, translations);
this._languageCode = languageCode;

@@ -16,23 +98,62 @@ this._translations = translations;

translate(key) {
const languageTranslations = this.translationsForCurrentLanguage();
const translatedText = languageTranslations[key] || this.defaultTranslationFor(key);
if (translatedText === undefined)
throw this.keyNotFoundMessage(key);
return translatedText;
translate(key, ...params) {
const languageTranslations = this._translationsForCurrentLanguage();
const translatedText = languageTranslations[key] || this._defaultTranslationFor(key);
this._validateResultingTextExists(translatedText, key);
return this._evaluateWithPotentialArguments(translatedText, params);
}
translationsForCurrentLanguage() {
return this._translations[this._languageCode] || {};
// assertions
_assertLanguageIsSupported(languageCode, translations) {
const supportedLanguages = Object.keys(translations);
if (!supportedLanguages.includes(languageCode)) {
throw new Error(`Language '${languageCode}' is not supported. Allowed values: ${supportedLanguages.join(', ')}`);
}
}
defaultTranslationFor(key) {
_validateResultingTextExists(text, key) {
if (isUndefined(text)) {
throw new Error(this._keyNotFoundMessage(key));
}
}
_validateNumberOfArgumentsMatch(expectedParams, givenParams) {
if (expectedParams.length !== givenParams.length) {
throw new Error(this._wrongNumberOfArgumentsErrorMessage(expectedParams, givenParams));
}
}
// private
_evaluateWithPotentialArguments(translatedText, params) {
const translatedTextArguments = translatedText.match(/%s/g) || [];
if (translatedTextArguments.length > 0) {
this._validateNumberOfArgumentsMatch(translatedTextArguments, params);
// Node 15 will include the replaceAll() method
return translatedText.replace(/%s/g, () => params.shift());
} else {
return translatedText;
}
}
_translationsForCurrentLanguage() {
return this._translations[this._languageCode];
}
_defaultTranslationFor(key) {
return this._translations[I18n.defaultLanguage()][key];
}
keyNotFoundMessage(key) {
// error messages
_keyNotFoundMessage(key) {
return `${key} not found in translations (language: ${this._languageCode})!`;
}
_wrongNumberOfArgumentsErrorMessage(expectedParams, givenParams) {
return `Expected ${expectedParams.length} argument(s) on the translation string, got ${givenParams.length} instead`;
}
}
module.exports = I18n;
module.exports = { I18n, I18nMessage };

@@ -18,2 +18,14 @@ 'use strict';

},
_packageData() {
return require('../package.json');
},
_exitSuccessfully() {
process.exit(0);
},
_exitWithFailure() {
process.exit(1);
},
};

@@ -29,5 +41,5 @@

execute(_params) {
const { version, description, homepage } = require('../package.json');
const { version, description, homepage } = this._packageData();
console.log(`Testy version: ${version}\n${description}\n${homepage}`);
process.exit(0);
this._exitSuccessfully();
},

@@ -44,3 +56,3 @@ };

execute(_params) {
const { description } = require('../package.json');
const { description } = this._packageData();
console.log(`Testy: ${description}\n`);

@@ -52,3 +64,3 @@ console.log('Usage: \n');

console.log(' -v, --version Displays the current version');
process.exit(0);
this._exitSuccessfully();
},

@@ -65,4 +77,13 @@ };

execute(params) {
const testyInstance = Testy.configuredWith(Configuration.current());
testyInstance.run(params);
try {
const testyInstance = Testy.configuredWith(Configuration.current());
testyInstance.run(params);
this._exitSuccessfully();
} catch (error) {
const { bugs } = this._packageData();
console.log('Sorry, an unexpected error happened while loading Testy, you did nothing wrong. Details below:');
console.log(error.stack);
console.log(`Please report this issue including the full error message and stacktrace at ${bugs.url}.`);
this._exitWithFailure();
}
},

@@ -69,0 +90,0 @@ };

@@ -24,6 +24,6 @@ 'use strict';

static evaluate(test, failFastMode) {
static evaluate(test, context) {
return [SkippedTest, TestWithoutDefinition, TestWithDefinition]
.find(result => result.canHandle(test, failFastMode))
.handle(test, failFastMode);
.find(result => result.canHandle(test, context))
.handle(test, context);
}

@@ -59,4 +59,4 @@

class SkippedTest extends TestResult {
static canHandle(test, failFastMode) {
return failFastMode.hasFailed();
static canHandle(test, context) {
return context.failFastMode.hasFailed();
}

@@ -92,3 +92,3 @@

static handle(test, failFastMode) {
static handle(test, context) {
test.evaluate();

@@ -98,3 +98,3 @@ const possibleResults = [TestWithoutAssertion, TestErrored, TestExplicitlyMarkedPending, TestSucceeded, TestFailed];

.find(result => result.canHandle(test))
.handle(test, failFastMode);
.handle(test, context);
}

@@ -135,4 +135,4 @@ }

static handle(test, failFastMode) {
failFastMode.registerFailure();
static handle(test, context) {
context.failFastMode.registerFailure();
test.finishWithError();

@@ -160,5 +160,5 @@ }

static handle(test, failFastMode) {
static handle(test, context) {
test.setResult(new this());
super.handle(test, failFastMode);
super.handle(test, context);
}

@@ -190,4 +190,4 @@

static handle(test, failFastMode) {
failFastMode.registerFailure();
static handle(test, context) {
context.failFastMode.registerFailure();
test.finishWithFailure();

@@ -194,0 +194,0 @@ }

@@ -5,4 +5,4 @@ 'use strict';

const TestSuite = require('./test_suite');
const FailFast = require("./fail_fast");
const I18n = require('./i18n');
const FailFast = require('./fail_fast');
const { I18n } = require('./i18n');
const { shuffle } = require('./utils');

@@ -20,3 +20,3 @@

registerSuite(name, suiteBody = () => {}, callbacks = {}) {
registerSuite(name, suiteBody, callbacks) {
const suiteToAdd = new TestSuite(name, suiteBody, callbacks);

@@ -28,11 +28,15 @@ return this.addSuite(suiteToAdd);

const testToAdd = new Test(name, testBody, callbacks);
this.currentSuite().addTest(testToAdd);
this._currentSuite.addTest(testToAdd);
}
registerBefore(beforeBlock) {
this.currentSuite().before(beforeBlock);
this._currentSuite.before(beforeBlock);
}
registerAfter(afterBlock) {
this._currentSuite.after(afterBlock);
}
addSuite(suiteToAdd) {
this.suites().push(suiteToAdd);
this._suites.push(suiteToAdd);
this._setCurrentSuite(suiteToAdd);

@@ -58,5 +62,5 @@ return suiteToAdd;

this._randomizeSuites();
this.suites().forEach(suite => {
this._suites.forEach(suite => {
this._setCurrentSuite(suite);
suite.run(this._failFastMode, this._randomOrder);
suite.run(this._executionContext());
});

@@ -66,10 +70,19 @@ this._callbacks.onFinish(this);

_executionContext() {
return {
failFastMode: this._failFastMode,
randomOrderMode: this._randomOrder,
};
}
setResultForCurrentTest(result) {
this.currentSuite().currentTest().setResult(result);
this._currentSuite.currentTest().setResult(result);
}
finish(callbacks) {
return this._considerResultAsSucceeded()
? callbacks.success()
: callbacks.failure();
finish() {
if (this.hasErrorsOrFailures()) {
return this._callbacks.onFailure(this);
} else {
return this._callbacks.onSuccess(this);
}
}

@@ -103,15 +116,5 @@

// Accessing
currentSuite() {
return this._currentSuite;
}
suites() {
return this._suites;
}
allFailuresAndErrors() {
return this.suites().reduce(
(failures, suite) => failures.concat(suite.allFailuresAndErrors()), []
return this._suites.reduce((failures, suite) =>
failures.concat(suite.allFailuresAndErrors()), [],
);

@@ -130,8 +133,6 @@ }

_considerResultAsSucceeded() {
return this.errorsCount() + this.failuresCount() === 0;
}
_countEach(property) {
return this.suites().reduce((count, suite) => count + suite[property](), 0);
return this._suites.reduce((count, suite) =>
count + suite[property](), 0,
);
}

@@ -141,3 +142,3 @@

if (this._randomOrder) {
shuffle(this.suites());
shuffle(this._suites);
}

@@ -144,0 +145,0 @@ }

'use strict';
const FailFast = require('./fail_fast');
const { shuffle, isString, isFunction } = require('./utils');
const { shuffle, isUndefined, isStringWithContent, isFunction } = require('./utils');

@@ -13,2 +12,3 @@ class TestSuite {

this._before = undefined;
this._after = undefined;
}

@@ -22,15 +22,24 @@

before(initialization) {
if (this._before === undefined)
this._before = initialization;
else
throw 'There is already a before() block. Please leave just one before() block and run again the tests.';
before(initializationBlock) {
if (isUndefined(this._before)) {
this._before = initializationBlock;
} else {
throw new Error('There is already a before() block. Please leave just one before() block and run again the tests.');
}
}
after(releasingBlock) {
if (isUndefined(this._after)) {
this._after = releasingBlock;
} else {
throw new Error('There is already an after() block. Please leave just one after() block and run again the tests.');
}
}
// Executing
run(failFastMode = FailFast.default(), randomOrderMode = false) {
run(context) {
this._callbacks.onStart(this);
this._evaluateSuiteDefinition();
this._runTests(failFastMode, randomOrderMode);
this._runTests(context);
this._callbacks.onFinish(this);

@@ -96,4 +105,4 @@ }

_ensureNameIsValid(name) {
if (!isString(name)) {
throw 'Suite does not have a valid name';
if (!isStringWithContent(name)) {
throw new Error('Suite does not have a valid name');
}

@@ -104,3 +113,3 @@ }

if (!isFunction(body)) {
throw 'Suite does not have a valid body';
throw new Error('Suite does not have a valid body');
}

@@ -123,5 +132,8 @@ }

// TODO: reify configuration instead of many boolean flags
_runTests(failFastMode, randomOrderMode) {
if (randomOrderMode) {
_evaluateAfterBlock() {
this._after && this._after.call();
}
_runTests(context) {
if (context.randomOrderMode) {
this._randomizeTests();

@@ -132,3 +144,4 @@ }

this._evaluateBeforeBlock();
test.run(failFastMode);
test.run(context);
this._evaluateAfterBlock();
});

@@ -135,0 +148,0 @@ }

'use strict';
const TestResult = require('./test_result');
const FailFast = require('./fail_fast');
const { isString, isFunction, isUndefined } = require('./utils');
const { isStringWithContent, isFunction, isUndefined } = require('./utils');

@@ -17,4 +16,4 @@ class Test {

run(failFastMode = FailFast.default()) {
TestResult.evaluate(this, failFastMode);
run(context) {
TestResult.evaluate(this, context);
}

@@ -41,4 +40,5 @@

setResult(result) {
if(this.hasNoResult() || this.isSuccess())
if (this.hasNoResult() || this.isSuccess()) {
this._result = result;
}
}

@@ -65,7 +65,7 @@

hasDefinition() {
return this.body() !== undefined;
return !isUndefined(this.body());
}
hasNoResult() {
return this.result() === undefined;
return isUndefined(this.result());
}

@@ -124,4 +124,4 @@

_ensureNameIsValid(name) {
if (!isString(name)) {
throw 'Test does not have a valid name';
if (!isStringWithContent(name)) {
throw new Error('Test does not have a valid name');
}

@@ -132,3 +132,3 @@ }

if (!isUndefined(body) && !isFunction(body)) {
throw 'Test does not have a valid body';
throw new Error('Test does not have a valid body');
}

@@ -135,0 +135,0 @@ }

@@ -19,26 +19,26 @@ {

"failures_summary": "Failures summary:",
"expected": "Expected",
"to": "to ",
"be_equal_to": "be equal to",
"be_not_equal_to": "be not equal to",
"to_happen": "to happen",
"not_to_happen": "not to happen",
"but_got": "but got",
"instead": "instead",
"expecting_error": "error",
"be_true": "be true",
"be_false": "be false",
"be_undefined": "be undefined",
"be_defined": "be defined",
"be_null": "be null",
"be_not_null": "be not null",
"include": "include",
"not_include": "not include",
"include_exactly": "include exactly",
"be_empty": "be empty",
"be_not_empty": "be not empty",
"match": "match",
"expected_no_errors": "Expected no errors to happen",
"but": "but",
"was_raised": "was raised",
"expectation_be_true": "Expected %s to be true",
"expectation_be_false": "Expected %s to be false",
"expectation_be_undefined": "Expected %s to be undefined",
"expectation_be_defined": "Expected %s to be defined",
"expectation_be_null": "Expected %s to be null",
"expectation_be_not_null": "Expected %s to be not null",
"expectation_be_near_to": "Expected %s to be near to %s (using %s precision digits)",
"expectation_match_regex": "Expected %s to match %s",
"expectation_include": "Expected %s to include %s",
"expectation_not_include": "Expected %s to not include %s",
"expectation_be_included_in": "Expected %s to be included in %s",
"expectation_be_not_included_in": "Expected %s to be not included in %s",
"expectation_include_exactly": "Expected %s to include exactly %s",
"expectation_be_empty": "Expected %s to be empty",
"expectation_be_not_empty": "Expected %s to be not empty",
"expectation_error": "Expected error %s to happen",
"expectation_no_error": "Expected error %s not to happen",
"expectation_no_errors": "Expected no errors to happen, but %s was raised",
"expectation_different_error": "Expected error %s to happen, but got %s instead",
"equality_assertion_be_equal_to": "Expected %s to be equal to %s",
"equality_assertion_be_not_equal_to": "Expected %s to be not equal to %s",
"equality_assertion_failed_due_to_undetermination": "Equality cannot be determined. Both parts are undefined",
"equality_assertion_failed_due_to_missing_property": "Equality check failed. Objects do not have %s property",
"equality_assertion_failed_due_to_circular_references": "(circular references found, equality check cannot be done. Please compare objects' properties individually)",
"explicitly_failed": "Explicitly failed",

@@ -48,3 +48,4 @@ "running_tests_in": "Running tests in",

"random_order": "Random order",
"starting_testy": "Starting Testy!"
"starting_testy": "Starting Testy!",
"invalid_pending_reason": "In order to mark a test as pending, you need to specify a reason."
},

@@ -68,26 +69,26 @@ "es": {

"failures_summary": "Resumen de errores/fallidos:",
"expected": "Se esperaba que",
"to": "",
"be_equal_to": "sea igual a",
"be_not_equal_to": "no sea igual a",
"to_happen": "ocurra",
"not_to_happen": "no ocurra",
"but_got": "pero se obtuvo",
"instead": "en su lugar",
"expecting_error": "el error",
"be_true": "sea true",
"be_false": "sea false",
"be_undefined": "sea undefined",
"be_defined": "esté definido",
"be_null": "sea null",
"be_not_null": "no sea null",
"include": "incluya a",
"not_include": "no incluya a",
"include_exactly": "incluya exactamente a",
"be_empty": "sea vacío",
"be_not_empty": "no sea vacío",
"match": "sea cubierto por la expresión regular",
"expected_no_errors": "No se esperaban errores",
"but": "pero",
"was_raised": "fue lanzado",
"expectation_be_true": "Se esperaba que %s sea true",
"expectation_be_false": "Se esperaba que %s sea false",
"expectation_be_undefined": "Se esperaba que %s sea undefined",
"expectation_be_defined": "Se esperaba que %s esté definido",
"expectation_be_null": "Se esperaba que %s sea null",
"expectation_be_not_null": "Se esperaba que %s no sea null",
"expectation_be_near_to": "Se esperaba que %s esté cercano a %s (usando %s dígitos de precisión)",
"expectation_match_regex": "Se esperaba que %s sea cubierto por la expresión regular %s",
"expectation_include": "Se esperaba que %s incluya a %s",
"expectation_not_include": "Se esperaba que %s incluya a %s",
"expectation_be_included_in": "Se esperaba que %s esté incluido en %s",
"expectation_be_not_included_in": "Se esperaba que %s no esté incluido en %s",
"expectation_include_exactly": "Se esperaba que %s incluya exactamente a %s",
"expectation_be_empty": "Se esperaba que %s sea vacío",
"expectation_be_not_empty": "Se esperaba que %s no sea vacío",
"expectation_error": "Se esperaba que ocurra el error %s",
"expectation_no_error": "No se esperaba que ocurra el error %s",
"expectation_no_errors": "No se esperaban errores, pero %s fue lanzado",
"expectation_different_error": "Se esperaba que ocurra el error %s, pero en su lugar ocurrió el error %s",
"equality_assertion_be_equal_to": "Se esperaba que %s sea igual a %s",
"equality_assertion_be_not_equal_to": "Se esperaba que %s no sea igual a %s",
"equality_undetermined": "La igualdad no puede ser determinada. Ambas partes son undefined",
"equality_assertion_failed_due_to_missing_property": "Igualdad entre objetos fallida. Los objetos no tienen la propiedad %s",
"equality_assertion_failed_due_to_circular_references": "(se encontraron referencias circulares, no es posible verificar la igualdad. Por favor, comparar propiedades de los objetos de manera individual)",
"explicitly_failed": "Explícitamente marcado como fallido",

@@ -97,4 +98,5 @@ "running_tests_in": "Ejecutando tests en",

"random_order": "Orden aleatorio",
"starting_testy": "Comenzando a ejecutar Testy!"
"starting_testy": "Comenzando a ejecutar Testy!",
"invalid_pending_reason": "Para marcar un test como pendiente, es necesario especificar un motivo."
}
}

@@ -9,3 +9,5 @@ 'use strict';

const isCyclic = object => {
if (object === null) { return false; }
if (object === null) {
return false;
}
const seenObjects = [];

@@ -15,3 +17,5 @@

if (typeof obj === 'object') {
if (seenObjects.includes(obj)) return true;
if (seenObjects.includes(obj)) {
return true;
}
seenObjects.push(obj);

@@ -42,5 +46,4 @@ return !!Object.keys(obj).find(key => detect(obj[key]));

}
fs.readdirSync(dir).forEach(entry =>
results.push(...allFilesMatching(path.join(dir, entry), regex, results))
results.push(...allFilesMatching(path.join(dir, entry), regex, results)),
);

@@ -78,2 +81,5 @@ return results;

const isStringWithContent = string =>
isString(string) && string.replace(/\s/g, '').length > 0;
const respondsTo = (object, methodName) =>

@@ -94,2 +100,22 @@ notNullOrUndefined(object) && isFunction(object[methodName]);

const stringToArray = object => Array.from(object);
const arrayToArray = object => object;
const setToArray = object => Array.from(object);
const mapToArray = object => Array.from(object.values());
const convertToArray = object => {
const conversionFunctions = {
String: stringToArray,
Array: arrayToArray,
Set: setToArray,
Map: mapToArray,
};
const conversionFunction = conversionFunctions[object.constructor.name];
return conversionFunction(object);
};
const subclassResponsibility = () => {
throw new Error('subclass responsibility');
};
module.exports = {

@@ -103,2 +129,3 @@ // comparison on objects

isString,
isStringWithContent,
isFunction,

@@ -112,5 +139,8 @@ isUndefined,

numberOfElements,
convertToArray,
// files
resolvePathFor,
allFilesMatching,
// object orientation
subclassResponsibility,
};
{
"name": "@pmoo/testy",
"version": "5.0.2",
"version": "5.1.0",
"description": "A minimal testing framework, for educational purposes.",

@@ -10,2 +10,5 @@ "homepage": "https://ngarbezza.github.io/testy/",

},
"bugs": {
"url": "https://github.com/ngarbezza/testy/issues"
},
"engines": {

@@ -17,3 +20,6 @@ "node": ">= 8.*"

"coverage": "npx nyc@latest --reporter=lcov --reporter=text-summary npm test",
"open-coverage-report": "xdg-open coverage/lcov-report/index.html",
"generate-dependencies-graph": "npx madge -i testy-dependencies.png lib/ bin/",
"lint": "npx eslint@6.8.0 .",
"lint-fix": "npx eslint@6.8.0 . --fix",
"test": "bin/testy_cli.js"

@@ -20,0 +26,0 @@ },

@@ -18,10 +18,9 @@ # Testy

![package-size](https://img.shields.io/bundlephobia/min/@pmoo/testy.svg?logo=npm)
![activity](https://img.shields.io/github/commit-activity/w/ngarbezza/testy.svg?logo=npm)
![activity](https://img.shields.io/github/commit-activity/m/ngarbezza/testy?logo=npm)
![release-date](https://img.shields.io/github/release-date/ngarbezza/testy.svg?logo=npm)
\
[![all-contributors](https://img.shields.io/badge/all_contributors-2-orange.svg?logo=open-source-initiative)](#contributors)
[![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).
:arrow_right: [v4 (legacy version) documentation here](README_v4.md) \
:arrow_right: [Documentación en español aquí](README_es.md)

@@ -168,2 +167,19 @@

```
* **Running code after every test**: just like many testing frameworks have, there is a way to execute some code after (cleanp) every test in a suite using the `after()` function. Example:
```javascript
const { suite, test, before, after, assert } = require('@pmoo/testy');
suite('using the after() helper', () => {
let answer;
before(() => {
answer = 42;
});
after(() => {
answer = undefined;
});
});
```
* **Support for pending tests**: if a test has no body, it will be reported as `[WIP]` and it won't be considered a failure.

@@ -221,4 +237,10 @@ * **Fail-Fast mode**: if enabled, it stops execution in the first test that fails (or has an error). Remaining tests will be marked as skipped.

<td align="center"><a href="https://github.com/abraaoduarte"><img src="https://avatars2.githubusercontent.com/u/6676804?v=4" width="100px;" alt=""/><br /><sub><b>Abraão Duarte</b></sub></a><br /><a href="https://github.com/ngarbezza/testy/commits?author=abraaoduarte" title="Code">💻</a></td>
<td align="center"><a href="http://adico.tech"><img src="https://avatars0.githubusercontent.com/u/5412270?v=4" width="100px;" alt=""/><br /><sub><b>adico</b></sub></a><br /><a href="https://github.com/ngarbezza/testy/commits?author=adico1" title="Code">💻</a></td>
<td align="center"><a href="http://adico.tech"><img src="https://avatars0.githubusercontent.com/u/5412270?v=4" width="100px;" alt=""/><br /><sub><b>adico</b></sub></a><br /><a href="https://github.com/ngarbezza/testy/commits?author=adico1" title="Code">💻</a> <a href="https://github.com/ngarbezza/testy/commits?author=adico1" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/ask-imran"><img src="https://avatars0.githubusercontent.com/u/20487103?v=4" width="100px;" alt=""/><br /><sub><b>Askar Imran</b></sub></a><br /><a href="https://github.com/ngarbezza/testy/commits?author=ask-imran" title="Code">💻</a> <a href="https://github.com/ngarbezza/testy/commits?author=ask-imran" title="Tests">⚠️</a></td>
<td align="center"><a href="http://www.nigelyong.com/"><img src="https://avatars2.githubusercontent.com/u/23243585?v=4" width="100px;" alt=""/><br /><sub><b>Nigel Yong</b></sub></a><br /><a href="https://github.com/ngarbezza/testy/commits?author=niyonx" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/chelsieng"><img src="https://avatars1.githubusercontent.com/u/60008262?v=4" width="100px;" alt=""/><br /><sub><b>Chelsie Ng</b></sub></a><br /><a href="https://github.com/ngarbezza/testy/commits?author=chelsieng" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/trochepablo"><img src="https://avatars2.githubusercontent.com/u/18213369?v=4" width="100px;" alt=""/><br /><sub><b>Pablo T</b></sub></a><br /><a href="https://github.com/ngarbezza/testy/commits?author=trochepablo" title="Tests">⚠️</a> <a href="https://github.com/ngarbezza/testy/commits?author=trochepablo" title="Code">💻</a></td>
</tr>
</table>

@@ -225,0 +247,0 @@

@@ -7,3 +7,3 @@ 'use strict';

const ConsoleUI = require(`${libDir}/console_ui`);
const Utils = require(`${libDir}/utils`);
const { allFilesMatching, resolvePathFor } = require(`${libDir}/utils`);

@@ -21,3 +21,3 @@ const ui = new ConsoleUI();

function suite(name, suiteBody) {
return testRunner.registerSuite(name, suiteBody, ui.suiteCallbacks());
testRunner.registerSuite(name, suiteBody, ui.suiteCallbacks());
}

@@ -29,2 +29,6 @@

function after(initialization) {
testRunner.registerAfter(initialization);
}
class Testy {

@@ -46,10 +50,6 @@ // instance creation

this._loadAllRequestedFiles();
ui.displayInitialSummary(this._configuration, this._testFilesPathsToRun());
ui.measuringTotalTime(() =>
testRunner.run()
ui.start(this._configuration, this._testFilesPathsToRun(), () =>
testRunner.run(),
);
testRunner.finish({
success: () => process.exit(0),
failure: () => process.exit(1),
});
testRunner.finish();
}

@@ -72,7 +72,11 @@

_loadAllRequestedFiles() {
this._resolvedTestFilesPathsToRun().forEach(path =>
Utils.allFilesMatching(path, this._testFilesFilter()).forEach(file =>
require(file)
)
);
try {
this._resolvedTestFilesPathsToRun().forEach(path =>
allFilesMatching(path, this._testFilesFilter()).forEach(file =>
require(file),
),
);
} catch (err) {
ui.exitWithError(`Error: ${err.path} does not exist.`);
}
}

@@ -85,4 +89,4 @@

_resolvedTestFilesPathsToRun() {
return this._testFilesPathsToRun().map(path => Utils.resolvePathFor(path));
_resolvedTestFilesPathsToRun(){
return this._testFilesPathsToRun().map(path => resolvePathFor(path));
}

@@ -99,2 +103,2 @@

module.exports = { Testy, suite, test, before, assert, fail, pending };
module.exports = { Testy, suite, test, before, after, assert, fail, pending };

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc