Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow fail to work in try/catch #664

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@
"watchPlugins": [
"jest-watch-typeahead/filename",
"jest-watch-typeahead/testname"
],
"reporters": [
"<rootDir>/test/reporters/ExceptionlessExpectedFailureReporter.js",
"default"
]
},
"babel": {
Expand Down
1 change: 1 addition & 0 deletions src/matchers/fail.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export function fail(_, message) {
this.dontThrow();
return {
pass: false,
message: () => (message ? message : 'fails by .fail() assertion'),
Expand Down
5 changes: 0 additions & 5 deletions test/matchers/__snapshots__/fail.test.js.snap

This file was deleted.

14 changes: 10 additions & 4 deletions test/matchers/fail.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import * as matcher from 'src/matchers/fail';

expect.extend(matcher);

describe('.fail', () => {
test('fails without message', () => {
expect(() => expect().fail()).toThrowErrorMatchingSnapshot();
expect().fail(); // This should fail!
});
test('fails with message', () => {
expect(() => expect().fail("This shouldn't fail!")).toThrowErrorMatchingSnapshot();
expect().fail('This should fail!');
});
test('fails when invoked in a try/catch', () => {
try {
expect().fail();
} catch (error) {
expect('this assertion').toBe('not checked');
}
});
});

Expand All @@ -16,6 +22,6 @@ describe('.not.fail', () => {
expect().not.fail();
});
test('does not fail with message', () => {
expect().not.fail('this should fail!');
expect().not.fail('this should not fail!');
});
});
83 changes: 83 additions & 0 deletions test/reporters/ExceptionlessExpectedFailureReporter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* Flips the test results for fail.test.js > .fail > <test cases>
*/
class ExceptionlessExpectedFailureReporter {
constructor(globalConfig, reporterOptions, reporterContext) {
this._globalConfig = globalConfig;
this._options = reporterOptions;
this._context = reporterContext;
}
onTestCaseResult(test, testCaseResult) {
this._processTestCaseResult(testCaseResult);
}
onTestFileResult(test, testResult, results) {
if (testResult.testFilePath.endsWith('fail.test.js')) {
this._processTestResults(results);
}
}
_processTestResults(results) {
for (let testSuiteResult of results.testResults) {
if (testSuiteResult.testFilePath.endsWith('fail.test.js')) {
let switchedToFailing = 0;
let switchedToPassing = 0;
for (let testCaseResult of testSuiteResult.testResults) {
const processResult = this._processTestCaseResult(testCaseResult);
if (processResult === 'switch-to-failing') switchedToFailing++;
if (processResult === 'switch-to-passing') switchedToPassing++;
}
const originalFailureCount = testSuiteResult.numFailingTests;
testSuiteResult.numFailingTests += switchedToFailing - switchedToPassing;
results.numFailedTests += switchedToFailing - switchedToPassing;
testSuiteResult.numPassingTests += switchedToPassing - switchedToFailing;
results.numPassedTests += switchedToPassing - switchedToFailing;
if (originalFailureCount === switchedToPassing) {
testSuiteResult.failureMessage = '';
results.numFailedTestSuites -= 1;
results.numPassedTestSuites += 1;
if (results.numFailedTestSuites === 0) results.success = true;
console.log('marking failing test suite as passing', testSuiteResult.testFilePath);
}
}
}
}

_processTestCaseResult(testCaseResult) {
if (this._hasDotFailAncestor(testCaseResult)) {
if (testCaseResult.status === 'failed') {
this._markPassing(testCaseResult);
return 'switch-to-passing';
} else if (testCaseResult.status === 'passed') {
this._markFailing(testCaseResult);
return 'switch-to-failing';
}
}
return 'unchanged';
}
_hasDotFailAncestor(result) {
return result.ancestorTitles.length > 0 && result.ancestorTitles[0] === '.fail';
}
_markPassing(result) {
result.status = 'passed';
result.failureDetails = [];
result.failureMessages = [];
result.numPassingAsserts = 1;
}
_markFailing(result) {
const message = `${result.fullName} was expected to fail, but did not.`;
result.status = 'failed';
result.failureDetails = [
{
matcherResult: {
pass: false,
message: message,
},
message: message,
stack: `${message}\n\tNo stack trace.\n\tThis is a placeholder message generated inside ExceptionlessExpectedFailureReporter`,
},
];
result.failureMessages = [message];
result.numPassingAsserts = 0;
}
}

module.exports = ExceptionlessExpectedFailureReporter;