Skip to content

Commit

Permalink
Fix pretty print for closeTo matcher (#12626)
Browse files Browse the repository at this point in the history
  • Loading branch information
L4vlet committed Apr 14, 2022
1 parent fb18e9a commit 045367a
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -59,6 +59,7 @@
- `[expect]` Move typings of `.not`, `.rejects` and `.resolves` modifiers outside of `Matchers` interface ([#12346](https://github.com/facebook/jest/pull/12346))
- `[expect]` Throw useful error if `expect.extend` is called with invalid matchers ([#12488](https://github.com/facebook/jest/pull/12488))
- `[expect]` Fix `iterableEquality` ignores other properties ([#8359](https://github.com/facebook/jest/pull/8359))
- `[expect]` Fix print for the `closeTo` matcher ([#12626](https://github.com/facebook/jest/pull/12626))
- `[jest-circus, @jest/types]` Disallow undefined value in `TestContext` type ([#12507](https://github.com/facebook/jest/pull/12507))
- `[jest-config]` Correctly detect CI environment and update snapshots accordingly ([#12378](https://github.com/facebook/jest/pull/12378))
- `[jest-config]` Pass `moduleTypes` to `ts-node` to enforce CJS when transpiling ([#12397](https://github.com/facebook/jest/pull/12397))
Expand Down
9 changes: 9 additions & 0 deletions packages/expect/src/asymmetricMatchers.ts
Expand Up @@ -13,6 +13,7 @@ import {
subsetEquality,
} from '@jest/expect-utils';
import * as matcherUtils from 'jest-matcher-utils';
import {pluralize} from 'jest-util';
import {getState} from './jestMatchersObject';
import type {
AsymmetricMatcher as AsymmetricMatcherInterface,
Expand Down Expand Up @@ -329,6 +330,14 @@ class CloseTo extends AsymmetricMatcher<number> {
override getExpectedType() {
return 'number';
}

override toAsymmetricMatcher(): string {
return [
this.toString(),
this.sample,
`(${pluralize('digit', this.precision)})`,
].join(' ');
}
}

export const any = (expectedObject: unknown): Any => new Any(expectedObject);
Expand Down
1 change: 1 addition & 0 deletions packages/expect/src/index.ts
Expand Up @@ -49,6 +49,7 @@ import type {
ThrowingMatcherFn,
} from './types';

export {AsymmetricMatcher} from './asymmetricMatchers';
export type {
AsymmetricMatchers,
BaseExpect,
Expand Down
1 change: 1 addition & 0 deletions packages/pretty-format/package.json
Expand Up @@ -29,6 +29,7 @@
"@types/react": "*",
"@types/react-is": "^17.0.0",
"@types/react-test-renderer": "*",
"expect": "^28.0.0-alpha.8",
"immutable": "^4.0.0",
"jest-util": "^28.0.0-alpha.8",
"react": "*",
Expand Down
55 changes: 55 additions & 0 deletions packages/pretty-format/src/__tests__/AsymmetricMatcher.test.ts
Expand Up @@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

import {AsymmetricMatcher as AbstractAsymmetricMatcher} from 'expect';
import prettyFormat, {plugins} from '../';
import type {OptionsReceived} from '../types';

Expand Down Expand Up @@ -131,6 +132,42 @@ test('stringNotMatching(string)', () => {
expect(result).toEqual('StringNotMatching /jest/');
});

test('closeTo(number, precision)', () => {
const result = prettyFormat(expect.closeTo(1.2345, 4), options);
expect(result).toEqual('NumberCloseTo 1.2345 (4 digits)');
});

test('notCloseTo(number, precision)', () => {
const result = prettyFormat(expect.not.closeTo(1.2345, 1), options);
expect(result).toEqual('NumberNotCloseTo 1.2345 (1 digit)');
});

test('closeTo(number)', () => {
const result = prettyFormat(expect.closeTo(1.2345), options);
expect(result).toEqual('NumberCloseTo 1.2345 (2 digits)');
});

test('closeTo(Infinity)', () => {
const result = prettyFormat(expect.closeTo(-Infinity), options);
expect(result).toEqual('NumberCloseTo -Infinity (2 digits)');
});

test('closeTo(scientific number)', () => {
const result = prettyFormat(expect.closeTo(1.56e-3, 4), options);
expect(result).toEqual('NumberCloseTo 0.00156 (4 digits)');
});

test('closeTo(very small scientific number)', () => {
const result = prettyFormat(expect.closeTo(1.56e-10, 4), options);
expect(result).toEqual('NumberCloseTo 1.56e-10 (4 digits)');
});

test('correctly handles inability to pretty-print matcher', () => {
expect(() => prettyFormat(new DummyMatcher(1), options)).toThrow(
'Asymmetric matcher DummyMatcher does not implement toAsymmetricMatcher()',
);
});

test('supports multiple nested asymmetric matchers', () => {
const result = prettyFormat(
{
Expand Down Expand Up @@ -311,3 +348,21 @@ test('min option', () => {
'{"test": {"nested": ObjectContaining {"a": ArrayContaining [1], "b": Anything, "c": Any<String>, "d": StringContaining "jest", "e": StringMatching /jest/, "f": ObjectContaining {"test": "case"}}}}',
);
});

class DummyMatcher extends AbstractAsymmetricMatcher<number> {
constructor(sample: number) {
super(sample);
}

asymmetricMatch(other: number) {
return this.sample === other;
}

toString() {
return 'DummyMatcher';
}

override getExpectedType() {
return 'number';
}
}
6 changes: 6 additions & 0 deletions packages/pretty-format/src/plugins/AsymmetricMatcher.ts
Expand Up @@ -80,6 +80,12 @@ export const serialize: NewPlugin['serialize'] = (
);
}

if (typeof val.toAsymmetricMatcher !== 'function') {
throw new Error(
`Asymmetric matcher ${val.constructor.name} does not implement toAsymmetricMatcher()`,
);
}

return val.toAsymmetricMatcher();
};

Expand Down
1 change: 1 addition & 0 deletions packages/pretty-format/tsconfig.json
Expand Up @@ -6,5 +6,6 @@
},
"include": ["./src/**/*"],
"exclude": ["./**/__tests__/**/*"],
// no `expect`, only used in tests
"references": [{"path": "../jest-schemas"}, {"path": "../jest-util"}]
}
9 changes: 8 additions & 1 deletion scripts/buildTs.mjs
Expand Up @@ -62,6 +62,13 @@ import {getPackages} from './buildUtils.mjs';
}
}

// dev dep
if (pkg.name === 'pretty-format') {
if (dep === 'expect') {
return false;
}
}

return true;
})
.map(dep =>
Expand All @@ -84,7 +91,7 @@ import {getPackages} from './buildUtils.mjs';
assert.deepStrictEqual(
references,
jestDependenciesOfPackage,
`Expected declared references to match dependencies in packages ${
`Expected declared references to match dependencies in package ${
pkg.name
}. Got:\n\n${references.join(
'\n',
Expand Down
1 change: 1 addition & 0 deletions yarn.lock
Expand Up @@ -17974,6 +17974,7 @@ __metadata:
"@types/react-test-renderer": "*"
ansi-regex: ^5.0.1
ansi-styles: ^5.0.0
expect: ^28.0.0-alpha.8
immutable: ^4.0.0
jest-util: ^28.0.0-alpha.8
react: "*"
Expand Down

0 comments on commit 045367a

Please sign in to comment.