Skip to content

Commit

Permalink
Fix errors when identity-obj-proxy mocks CSS Modules (#4935)
Browse files Browse the repository at this point in the history
* Fix errors when identity-obj-proxy mocks CSS Modules

* Add item to CHANGELOG.md
  • Loading branch information
pedrottimark authored and cpojer committed Nov 22, 2017
1 parent 5800f47 commit 8a3ff83
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 3 deletions.
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);

0 comments on commit 8a3ff83

Please sign in to comment.