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

Fix errors when identity-obj-proxy mocks CSS Modules #4935

Merged
merged 2 commits into from
Nov 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

### Fixes

* `[pretty-format]` Fix errors when identity-obj-proxy mocks CSS Modules
([#4935](https://github.com/facebook/jest/pull/4935))
* `[babel-jest]` Fix support for namespaced babel version 7
([#4918](https://github.com/facebook/jest/pull/4918))
* `[expect]` fix .toThrow for promises
Expand Down
9 changes: 9 additions & 0 deletions packages/pretty-format/src/__tests__/immutable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ const toPrettyPrintTo = getPrettyPrint([ReactElement, ImmutablePlugin]);
const expect = global.expect;
expect.extend({toPrettyPrintTo});

it('does not incorrectly match identity-obj-proxy as Immutable object', () => {
// SENTINEL constant is from https://github.com/facebook/immutable-js
const IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@';
const val = {};
val[IS_ITERABLE_SENTINEL] = IS_ITERABLE_SENTINEL; // mock the mock object :)
const expected = `{"${IS_ITERABLE_SENTINEL}": "${IS_ITERABLE_SENTINEL}"}`;
expect(val).toPrettyPrintTo(expected, {min: true});
});

describe('Immutable.OrderedSet', () => {
it('supports an empty collection {min: true}', () => {
expect(Immutable.OrderedSet([])).toPrettyPrintTo(
Expand Down
11 changes: 11 additions & 0 deletions packages/pretty-format/src/__tests__/pretty_format.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,17 @@ describe('prettyFormat()', () => {
expect(prettyFormat(Object.create(null))).toEqual('Object {}');
});

it('prints identity-obj-proxy with string constructor', () => {
const val = Object.create(null);
val.constructor = 'constructor'; // mock the mock object :)
const expected = [
'Object {', // Object instead of undefined
' "constructor": "constructor",',
'}',
].join('\n');
expect(prettyFormat(val)).toEqual(expected);
});

it('calls toJSON and prints its return value', () => {
expect(
prettyFormat({
Expand Down
9 changes: 7 additions & 2 deletions packages/pretty-format/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ const errorToString = Error.prototype.toString;
const regExpToString = RegExp.prototype.toString;
const symbolToString = Symbol.prototype.toString;

// Explicitly comparing typeof constructor to function avoids undefined as name
// when mock identity-obj-proxy returns the key as the value for any key.
const getConstructorName = val =>
(typeof val.constructor === 'function' && val.constructor.name) || 'Object';

// Is val is equal to global window object? Works even if it does not exist :)
/* global window */
const isWindow = val => typeof window !== 'undefined' && val === window;
Expand Down Expand Up @@ -239,8 +244,8 @@ function printComplexValue(
// Avoid failure to serialize global window object in jsdom test environment.
// For example, not even relevant if window is prop of React element.
return hitMaxDepth || isWindow(val)
? '[' + (val.constructor ? val.constructor.name : 'Object') + ']'
: (min ? '' : (val.constructor ? val.constructor.name : 'Object') + ' ') +
? '[' + getConstructorName(val) + ']'
: (min ? '' : getConstructorName(val) + ' ') +
'{' +
printObjectProperties(val, config, indentation, depth, refs, printer) +
'}';
Expand Down
5 changes: 4 additions & 1 deletion packages/pretty-format/src/plugins/immutable.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,10 @@ export const serialize = (
return printImmutableRecord(val, config, indentation, depth, refs, printer);
};

// Explicitly comparing sentinel properties to true avoids false positive
// when mock identity-obj-proxy returns the key as the value for any key.
export const test = (val: any) =>
val && (val[IS_ITERABLE_SENTINEL] || val[IS_RECORD_SENTINEL]);
val &&
(val[IS_ITERABLE_SENTINEL] === true || val[IS_RECORD_SENTINEL] === true);

export default ({serialize, test}: NewPlugin);