Skip to content
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);