Skip to content

Commit

Permalink
add to throw error matching named snapshot with e2e
Browse files Browse the repository at this point in the history
  • Loading branch information
bakamitai456 committed Jun 15, 2023
1 parent 6841acf commit 7dfe361
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 7 deletions.
109 changes: 109 additions & 0 deletions e2e/__tests__/toThrowErrorMatchingNamedSnapshot.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import * as path from 'path';
import * as fs from 'graceful-fs';
import {cleanup, makeTemplate, writeFiles} from '../Utils';
import runJest from '../runJest';

const DIR = path.resolve(
__dirname,
'../to-throw-error-matching-named-snapshot',
);
const TESTS_DIR = path.resolve(DIR, '__tests__');

beforeEach(() => cleanup(TESTS_DIR));
afterAll(() => cleanup(TESTS_DIR));

test('works fine when function throws error', () => {
const filename = 'works-fine-when-function-throws-error.test.js';
const template =
makeTemplate(`test('works fine when function throws error', () => {
expect(() => { throw new Error('apple'); })
.toThrowErrorMatchingNamedSnapshot('works-fine');
});
`);

{
writeFiles(TESTS_DIR, {[filename]: template()});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
}
});

test("throws the error if tested function didn't throw error", () => {
const filename = 'throws-if-tested-function-did-not-throw.test.js';
const template =
makeTemplate(`test('throws the error if tested function did not throw error', () => {
expect(() => {}).toThrowErrorMatchingNamedSnapshot('error if did not throw error');
});
`);

{
writeFiles(TESTS_DIR, {[filename]: template()});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
expect(stderr).toMatch('Received function did not throw');
expect(exitCode).toBe(1);
}
});

test('accepts custom snapshot name', () => {
const filename = 'accept-custom-snapshot-name.test.js';
const template = makeTemplate(`test('accepts custom snapshot name', () => {
expect(() => { throw new Error('apple'); })
.toThrowErrorMatchingNamedSnapshot('custom-name');
});
`);

{
writeFiles(TESTS_DIR, {[filename]: template()});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
}
});

test('cannot be used with .not', () => {
const filename = 'cannot-be-used-with-not.test.js';
const template = makeTemplate(`test('cannot be used with .not', () => {
expect(() => { throw new Error('apple'); })
.not
.toThrowErrorMatchingNamedSnapshot('cannot-used-with-not');
});
`);

{
writeFiles(TESTS_DIR, {[filename]: template()});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
expect(stderr).toMatch('Snapshot matchers cannot be used with not');
expect(exitCode).toBe(1);
}
});

test('should support rejecting promises', () => {
const filename = 'should-support-rejecting-promises.test.js';
const template =
makeTemplate(`test('should support rejecting promises', () => {
return expect(Promise.reject(new Error('octopus'))).rejects.toThrowErrorMatchingNamedSnapshot('support-reject');
});
`);

{
writeFiles(TESTS_DIR, {[filename]: template()});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);

const snapshot = fs.readFileSync(
`${TESTS_DIR}/__snapshots__/${filename}.snap`,
'utf8',
);

expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(snapshot).toMatchNamedSnapshot('support-reject');
expect(exitCode).toBe(0);
}
});
5 changes: 3 additions & 2 deletions e2e/__tests__/toThrowErrorMatchingSnapshot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ test("throws the error if tested function didn't throw error", () => {
}
});

test('accepts custom snapshot name', () => {
test('accepts custom snapshot hint', () => {
const filename = 'accept-custom-snapshot-name.test.js';
const template = makeTemplate(`test('accepts custom snapshot name', () => {
expect(() => { throw new Error('apple'); })
.toThrowErrorMatchingSnapshot('custom-name');
.toThrowErrorMatchingSnapshot('custom-hint');
});
`);

Expand Down Expand Up @@ -93,6 +93,7 @@ test('should support rejecting promises', () => {
{
writeFiles(TESTS_DIR, {[filename]: template()});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
console.log(stderr);

const snapshot = fs.readFileSync(
`${TESTS_DIR}/__snapshots__/${filename}.snap`,
Expand Down
5 changes: 5 additions & 0 deletions e2e/to-match-named-snapshot-with-retries/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"jest": {
"testEnvironment": "node"
}
}
5 changes: 5 additions & 0 deletions e2e/to-throw-error-matching-named-snapshot/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"jest": {
"testEnvironment": "node"
}
}
3 changes: 2 additions & 1 deletion packages/expect/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ const getPromiseMatcher = (name: string, matcher: RawMatcherFn) => {
return createThrowMatcher(name, true);
} else if (
name === 'toThrowErrorMatchingSnapshot' ||
name === 'toThrowErrorMatchingInlineSnapshot'
name === 'toThrowErrorMatchingInlineSnapshot' ||
name === 'toThrowErrorMatchingNamedSnapshot'
) {
return createToThrowErrorMatchingSnapshotMatcher(matcher);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-expect/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
toMatchNamedSnapshot,
toMatchSnapshot,
toThrowErrorMatchingInlineSnapshot,
toThrowErrorMatchingNamedSnapshot,
toThrowErrorMatchingSnapshot,
} from 'jest-snapshot';
import type {JestExpect} from './types';
Expand All @@ -33,6 +34,7 @@ function createJestExpect(): JestExpect {
toMatchNamedSnapshot,
toMatchSnapshot,
toThrowErrorMatchingInlineSnapshot,
toThrowErrorMatchingNamedSnapshot,
toThrowErrorMatchingSnapshot,
});

Expand Down
30 changes: 28 additions & 2 deletions packages/jest-snapshot/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -546,12 +546,37 @@ export const toThrowErrorMatchingInlineSnapshot: MatcherFunctionWithContext<
);
};

export const toThrowErrorMatchingNamedSnapshot: MatcherFunctionWithContext<
Context,
[snapshotName?: string, fromPromise?: boolean]
> = function (received, snapshotName, fromPromise) {
const matcherName = 'toThrowErrorMatchingNamedSnapshot';

return _toThrowErrorMatchingSnapshot(
{
context: this,
isInline: false,
matcherName,
received,
snapshotName,
},
fromPromise,
);
};

const _toThrowErrorMatchingSnapshot = (
config: MatchSnapshotConfig,
fromPromise?: boolean,
) => {
const {context, hint, inlineSnapshot, isInline, matcherName, received} =
config;
const {
context,
hint,
inlineSnapshot,
isInline,
matcherName,
snapshotName,
received,
} = config;

context.dontThrow && context.dontThrow();

Expand Down Expand Up @@ -606,5 +631,6 @@ const _toThrowErrorMatchingSnapshot = (
isInline,
matcherName,
received: error.message,
snapshotName,
});
};
12 changes: 10 additions & 2 deletions packages/jest-snapshot/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,17 @@ export interface SnapshotMatchers<R extends void | Promise<void>, T> {
hint?: string,
): R;
/**
* This ensures that a value matches the most recent snapshot.
* This ensures that a value matches the specific snapshot.
* Instead of use current test name in global state, it will use the specific name to find the snapshot.
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
*/
toMatchNamedSnapshot<U extends Record<keyof T, unknown>>(
propertyMatchers: Partial<U>,
snapshot?: string,
): R;
/**
* This ensures that a value matches the most recent snapshot.
* This ensures that a value matches the specific snapshot.
* Instead of use current test name in global state, it will use the specific name to find the snapshot.
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
*/
toMatchNamedSnapshot(snapshotName?: string): R;
Expand Down Expand Up @@ -91,6 +93,12 @@ export interface SnapshotMatchers<R extends void | Promise<void>, T> {
* Instead of writing the snapshot value to a .snap file, it will be written into the source code automatically.
*/
toThrowErrorMatchingInlineSnapshot(snapshot?: string): R;

/**
* Used to test that a function throws a error matching the specific snapshot.
* Instead of use current test name in global state, it will use the specific name to find the snapshot.
*/
toThrowErrorMatchingNamedSnapshot(name?: string): R;
}

export type SnapshotFormat = Omit<PrettyFormatOptions, 'compareKeys'>;

0 comments on commit 7dfe361

Please sign in to comment.