diff --git a/package.json b/package.json
index 28c15d9ba023..c52ff646e01b 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"flow-bin": "^0.39.0",
"glob": "^7.1.1",
"graceful-fs": "^4.1.11",
+ "immutable": "^3.8.1",
"istanbul-api": "^1.1.0",
"istanbul-lib-coverage": "^1.0.0",
"jasmine-reporters": "^2.2.0",
diff --git a/packages/jest-diff/src/index.js b/packages/jest-diff/src/index.js
index 8beb375bcc94..80385a664305 100644
--- a/packages/jest-diff/src/index.js
+++ b/packages/jest-diff/src/index.js
@@ -15,6 +15,7 @@ import type {DiffOptions} from './diffStrings';
const ReactElementPlugin = require('pretty-format/build/plugins/ReactElement');
const ReactTestComponentPlugin = require('pretty-format/build/plugins/ReactTestComponent');
const AsymmetricMatcherPlugin = require('pretty-format/build/plugins/AsymmetricMatcher');
+const ImmutablePlugins = require('pretty-format/build/plugins/ImmutablePlugins');
const chalk = require('chalk');
const diffStrings = require('./diffStrings');
@@ -30,7 +31,7 @@ const PLUGINS = [
ReactTestComponentPlugin,
ReactElementPlugin,
AsymmetricMatcherPlugin,
-];
+].concat(ImmutablePlugins);
const FORMAT_OPTIONS = {
plugins: PLUGINS,
};
diff --git a/packages/jest-matcher-utils/src/index.js b/packages/jest-matcher-utils/src/index.js
index 7c9ee30cf2b7..2845993d5bd5 100644
--- a/packages/jest-matcher-utils/src/index.js
+++ b/packages/jest-matcher-utils/src/index.js
@@ -13,8 +13,13 @@
const chalk = require('chalk');
const prettyFormat = require('pretty-format');
const AsymmetricMatcherPlugin = require('pretty-format/build/plugins/AsymmetricMatcher');
+const ReactElementPlugin = require('pretty-format/build/plugins/ReactElement');
+const ImmutablePlugins = require('pretty-format/build/plugins/ImmutablePlugins');
-const PLUGINS = [AsymmetricMatcherPlugin];
+const PLUGINS = [
+ AsymmetricMatcherPlugin,
+ ReactElementPlugin,
+].concat(ImmutablePlugins);
export type ValueType =
| 'array'
diff --git a/packages/jest-snapshot/src/__tests__/plugins-test.js b/packages/jest-snapshot/src/__tests__/plugins-test.js
index 26bd654c6665..e887b602f329 100644
--- a/packages/jest-snapshot/src/__tests__/plugins-test.js
+++ b/packages/jest-snapshot/src/__tests__/plugins-test.js
@@ -31,7 +31,7 @@ const testPath = names => {
it('gets plugins', () => {
const {getSerializers} = require('../plugins');
const plugins = getSerializers();
- expect(plugins.length).toBe(2);
+ expect(plugins.length).toBe(8);
});
it('adds plugins from an empty array', () => testPath([]));
diff --git a/packages/jest-snapshot/src/plugins.js b/packages/jest-snapshot/src/plugins.js
index 481155b9cd93..e6f30bfaad70 100644
--- a/packages/jest-snapshot/src/plugins.js
+++ b/packages/jest-snapshot/src/plugins.js
@@ -11,8 +11,12 @@
const ReactElementPlugin = require('pretty-format/build/plugins/ReactElement');
const ReactTestComponentPlugin = require('pretty-format/build/plugins/ReactTestComponent');
+const ImmutablePlugins = require('pretty-format/build/plugins/ImmutablePlugins');
-let PLUGINS = [ReactElementPlugin, ReactTestComponentPlugin];
+let PLUGINS = [
+ ReactElementPlugin,
+ ReactTestComponentPlugin,
+].concat(ImmutablePlugins);
// Prepend to list so the last added is the first tested.
exports.addSerializer = (plugin: any) => {
diff --git a/packages/pretty-format/src/__tests__/ImmutablePlugins-test.js b/packages/pretty-format/src/__tests__/ImmutablePlugins-test.js
new file mode 100644
index 000000000000..84a933b9a63d
--- /dev/null
+++ b/packages/pretty-format/src/__tests__/ImmutablePlugins-test.js
@@ -0,0 +1,376 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+ /* eslint-disable max-len */
+
+'use strict';
+
+const React = require('react');
+const diff = require('jest-diff');
+const prettyFormat = require('../');
+const Immutable = require('immutable');
+const ReactElementPlugin = require('../plugins/ReactElement');
+const ReactTestComponentPlugin = require('../plugins/ReactTestComponent');
+const ImmutablePlugins = require('../plugins/ImmutablePlugins');
+
+expect.extend({
+ toPrettyPrintTo(received, expected, opts) {
+ const prettyPrintImmutable = prettyFormat(received,
+ Object.assign({
+ plugins: [
+ ReactElementPlugin,
+ ReactTestComponentPlugin,
+ ].concat(ImmutablePlugins),
+ }, opts)
+ );
+ const pass = prettyPrintImmutable === expected;
+
+ const message = pass
+ ? () => this.utils.matcherHint('.not.toBe') + '\n\n' +
+ `Expected value to not be:\n` +
+ ` ${this.utils.printExpected(expected)}\n` +
+ `Received:\n` +
+ ` ${this.utils.printReceived(prettyPrintImmutable)}`
+ : () => {
+ const diffString = diff(expected, prettyPrintImmutable, {
+ expand: this.expand,
+ });
+ return this.utils.matcherHint('.toBe') + '\n\n' +
+ `Expected value to be:\n` +
+ ` ${this.utils.printExpected(expected)}\n` +
+ `Received:\n` +
+ ` ${this.utils.printReceived(prettyPrintImmutable)}` +
+ (diffString ? `\n\nDifference:\n\n${diffString}` : '');
+ };
+
+ return {actual: prettyPrintImmutable, message, pass};
+ },
+});
+
+describe('Immutable.OrderedSet plugin', () => {
+ it('supports an empty set', () => {
+ expect(Immutable.OrderedSet([]))
+ .toPrettyPrintTo('Immutable.OrderedSet []', {min: true});
+ });
+
+ it('supports a single string element', () => {
+ expect(Immutable.OrderedSet(['foo']))
+ .toPrettyPrintTo('Immutable.OrderedSet ["foo"]', {min: true});
+ });
+
+ it('supports a single integer element', () => {
+ expect(Immutable.OrderedSet([1]))
+ .toPrettyPrintTo('Immutable.OrderedSet [1]', {min: true});
+ });
+
+ it('supports multiple string elements {min: true}', () => {
+ expect(Immutable.OrderedSet(['jhon', 'mike', 'cristian']))
+ .toPrettyPrintTo('Immutable.OrderedSet ["jhon", "mike", "cristian"]', {min: true});
+ });
+
+ it('supports multiple string elements {min: false}', () => {
+ expect(Immutable.OrderedSet(['jhon', 'mike', 'cristian']))
+ .toPrettyPrintTo('Immutable.OrderedSet [\n "jhon",\n "mike",\n "cristian",\n]', {min: false});
+ });
+
+ it('supports multiple integer elements {min: true}', () => {
+ expect(Immutable.OrderedSet([1, 2, 3]))
+ .toPrettyPrintTo('Immutable.OrderedSet [1, 2, 3]', {min: true});
+ });
+
+ it('supports multiple integer elements {min: false}', () => {
+ expect(Immutable.OrderedSet([1, 2, 3]))
+ .toPrettyPrintTo('Immutable.OrderedSet [\n 1,\n 2,\n 3,\n]', {min: false});
+ });
+
+ it('supports object elements {min: true}', () => {
+ expect(Immutable.OrderedSet([{a: 1, b: 2, c: 3}]))
+ .toPrettyPrintTo('Immutable.OrderedSet [{\"a\": 1, \"b\": 2, \"c\": 3}]', {min: true});
+ });
+
+ it('supports object elements {min: false}', () => {
+ expect(Immutable.OrderedSet([{a: 1, b: 2, c: 3}]))
+ .toPrettyPrintTo('Immutable.OrderedSet [\n Object {\n \"a\": 1,\n \"b\": 2,\n \"c\": 3,\n },\n]', {min: false});
+ });
+
+ it('supports React components {min: true}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.OrderedSet([reactComponent, reactComponent]))
+ .toPrettyPrintTo('Immutable.OrderedSet [Hello World]', {min: true});
+ });
+
+ it('supports React components {min: false}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.OrderedSet([reactComponent, reactComponent]))
+ .toPrettyPrintTo('Immutable.OrderedSet [\n \n Hello World\n ,\n]', {min: false});
+ });
+});
+
+describe('Immutable.List plugin', () => {
+ it('supports an empty set', () => {
+ expect(Immutable.List([]))
+ .toPrettyPrintTo('Immutable.List []', {min: true});
+ });
+
+ it('supports a single string element', () => {
+ expect(Immutable.List(['foo']))
+ .toPrettyPrintTo('Immutable.List ["foo"]', {min: true});
+ });
+
+ it('supports a single integer element', () => {
+ expect(Immutable.List([1]))
+ .toPrettyPrintTo('Immutable.List [1]', {min: true});
+ });
+
+ it('supports multiple string elements {min: true}', () => {
+ expect(Immutable.List(['jhon', 'mike', 'cristian']))
+ .toPrettyPrintTo('Immutable.List ["jhon", "mike", "cristian"]', {min: true});
+ });
+
+ it('supports multiple string elements {min: false}', () => {
+ expect(Immutable.List(['jhon', 'mike', 'cristian']))
+ .toPrettyPrintTo('Immutable.List [\n "jhon",\n "mike",\n "cristian",\n]');
+ });
+
+ it('supports multiple integer elements {min: true}', () => {
+ expect(Immutable.List([1, 2, 3]))
+ .toPrettyPrintTo('Immutable.List [1, 2, 3]', {min: true});
+ });
+
+ it('supports multiple integer elements {min: false}', () => {
+ expect(Immutable.List([1, 2, 3]))
+ .toPrettyPrintTo('Immutable.List [\n 1,\n 2,\n 3,\n]');
+ });
+
+ it('supports object elements {min: true}', () => {
+ expect(Immutable.List([{a: 1, b: 2, c: 3}]))
+ .toPrettyPrintTo('Immutable.List [{\"a\": 1, \"b\": 2, \"c\": 3}]', {min: true});
+ });
+
+ it('supports object elements {min: false}', () => {
+ expect(Immutable.List([{a: 1, b: 2, c: 3}]))
+ .toPrettyPrintTo('Immutable.List [\n Object {\n \"a\": 1,\n \"b\": 2,\n \"c\": 3,\n },\n]');
+ });
+
+ it('supports React components {min: true}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.List([reactComponent, reactComponent]))
+ .toPrettyPrintTo('Immutable.List [Hello World, Hello World]', {min: true});
+ });
+
+ it('supports React components {min: false}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.List([reactComponent, reactComponent]))
+ .toPrettyPrintTo('Immutable.List [\n \n Hello World\n ,\n \n Hello World\n ,\n]');
+ });
+});
+
+describe('Immutable.Stack plugin', () => {
+ it('supports an empty set', () => {
+ expect(Immutable.Stack([]))
+ .toPrettyPrintTo('Immutable.Stack []', {min: true});
+ });
+
+ it('supports a single string element', () => {
+ expect(Immutable.Stack(['foo']))
+ .toPrettyPrintTo('Immutable.Stack ["foo"]', {min: true});
+ });
+
+ it('supports a single integer element', () => {
+ expect(Immutable.Stack([1]))
+ .toPrettyPrintTo('Immutable.Stack [1]', {min: true});
+ });
+
+ it('supports multiple string elements {min: true}', () => {
+ expect(Immutable.Stack(['jhon', 'mike', 'cristian']))
+ .toPrettyPrintTo('Immutable.Stack ["jhon", "mike", "cristian"]', {min: true});
+ });
+
+ it('supports multiple string elements {min: false}', () => {
+ expect(Immutable.Stack(['jhon', 'mike', 'cristian']))
+ .toPrettyPrintTo('Immutable.Stack [\n "jhon",\n "mike",\n "cristian",\n]');
+ });
+
+ it('supports multiple integer elements {min: true}', () => {
+ expect(Immutable.Stack([1, 2, 3]))
+ .toPrettyPrintTo('Immutable.Stack [1, 2, 3]', {min: true});
+ });
+
+ it('supports multiple integer elements {min: false}', () => {
+ expect(Immutable.Stack([1, 2, 3]))
+ .toPrettyPrintTo('Immutable.Stack [\n 1,\n 2,\n 3,\n]');
+ });
+
+ it('supports object elements {min: true}', () => {
+ expect(Immutable.Stack([{a: 1, b: 2, c: 3}]))
+ .toPrettyPrintTo('Immutable.Stack [{\"a\": 1, \"b\": 2, \"c\": 3}]', {min: true});
+ });
+
+ it('supports object elements {min: false}', () => {
+ expect(Immutable.Stack([{a: 1, b: 2, c: 3}]))
+ .toPrettyPrintTo('Immutable.Stack [\n Object {\n \"a\": 1,\n \"b\": 2,\n \"c\": 3,\n },\n]');
+ });
+
+ it('supports React components {min: true}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.Stack([reactComponent, reactComponent]))
+ .toPrettyPrintTo('Immutable.Stack [Hello World, Hello World]', {min: true});
+ });
+
+ it('supports React components {min: false}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.Stack([reactComponent, reactComponent]))
+ .toPrettyPrintTo('Immutable.Stack [\n \n Hello World\n ,\n \n Hello World\n ,\n]');
+ });
+});
+
+describe('Immutable.Set plugin', () => {
+ it('supports an empty set', () => {
+ expect(Immutable.Set([]))
+ .toPrettyPrintTo('Immutable.Set []', {min: true});
+ });
+
+ it('supports a single string element', () => {
+ expect(Immutable.Set(['foo']))
+ .toPrettyPrintTo('Immutable.Set ["foo"]', {min: true});
+ });
+
+ it('supports a single integer element', () => {
+ expect(Immutable.Set([1]))
+ .toPrettyPrintTo('Immutable.Set [1]', {min: true});
+ });
+
+ it('supports multiple string elements {min: true}', () => {
+ expect(Immutable.Set(['jhon', 'mike', 'cristian']))
+ .toPrettyPrintTo('Immutable.Set ["jhon", "mike", "cristian"]', {min: true});
+ });
+
+ it('supports multiple string elements {min: false}', () => {
+ expect(Immutable.Set(['jhon', 'mike', 'cristian']))
+ .toPrettyPrintTo('Immutable.Set [\n "jhon",\n "mike",\n "cristian",\n]');
+ });
+
+ it('supports multiple integer elements {min: true}', () => {
+ expect(Immutable.Set([1, 2, 3]))
+ .toPrettyPrintTo('Immutable.Set [1, 2, 3]', {min: true});
+ });
+
+ it('supports multiple integer elements {min: false}', () => {
+ expect(Immutable.Set([1, 2, 3]))
+ .toPrettyPrintTo('Immutable.Set [\n 1,\n 2,\n 3,\n]');
+ });
+
+ it('supports object elements {min: true}', () => {
+ expect(Immutable.Set([{a: 1, b: 2, c: 3}]))
+ .toPrettyPrintTo('Immutable.Set [{\"a\": 1, \"b\": 2, \"c\": 3}]', {min: true});
+ });
+
+ it('supports object elements {min: false}', () => {
+ expect(Immutable.Set([{a: 1, b: 2, c: 3}]))
+ .toPrettyPrintTo('Immutable.Set [\n Object {\n \"a\": 1,\n \"b\": 2,\n \"c\": 3,\n },\n]');
+ });
+
+ it('supports React components {min: true}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.Set([reactComponent, reactComponent]))
+ .toPrettyPrintTo('Immutable.Set [Hello World]', {min: true});
+ });
+
+ it('supports React components {min: false}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.Set([reactComponent, reactComponent]))
+ .toPrettyPrintTo('Immutable.Set [\n \n Hello World\n ,\n]');
+ });
+});
+
+describe('Immutable.Map plugin', () => {
+ it('supports an empty set', () => {
+ expect(Immutable.Map({}))
+ .toPrettyPrintTo('Immutable.Map {}', {min: true});
+ });
+
+ it('supports an object with single key', () => {
+ expect(Immutable.Map({a: 1}))
+ .toPrettyPrintTo('Immutable.Map {a: 1}', {min: true});
+ });
+
+ it('supports an object with multiple keys {min: true}', () => {
+ expect(Immutable.Map({a: 1, b: 2, c: 3}))
+ .toPrettyPrintTo('Immutable.Map {a: 1, b: 2, c: 3}', {min: true});
+ });
+
+ it('supports an object with multiple keys {min: false}', () => {
+ expect(Immutable.Map({a: 1, b: 2, c: 3}))
+ .toPrettyPrintTo('Immutable.Map {\n a: 1,\n b: 2,\n c: 3,\n}');
+ });
+
+ it('supports object elements {min: true}', () => {
+ expect(Immutable.Map({key: {a: 1, b: 2, c: 3}}))
+ .toPrettyPrintTo('Immutable.Map {key: {\"a\": 1, \"b\": 2, \"c\": 3}}', {min: true});
+ });
+
+ it('supports object elements {min: false}', () => {
+ expect(Immutable.Map({key: {a: 1, b: 2, c: 3}}))
+ .toPrettyPrintTo('Immutable.Map {\n key: Object {\n \"a\": 1,\n \"b\": 2,\n \"c\": 3,\n },\n}');
+ });
+
+ it('supports React components {min: true}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.Map({a: reactComponent, b: reactComponent}))
+ .toPrettyPrintTo('Immutable.Map {a: Hello World, b: Hello World}', {min: true});
+ });
+
+ it('supports React components {min: false}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.Map({a: reactComponent, b: reactComponent}))
+ .toPrettyPrintTo('Immutable.Map {\n a: \n Hello World\n ,\n b: \n Hello World\n ,\n}');
+ });
+});
+
+describe('Immutable.OrderedMap plugin', () => {
+ it('supports an empty set', () => {
+ expect(Immutable.OrderedMap({}))
+ .toPrettyPrintTo('Immutable.OrderedMap {}', {min: true});
+ });
+
+ it('supports an object with single key', () => {
+ expect(Immutable.OrderedMap({a: 1}))
+ .toPrettyPrintTo('Immutable.OrderedMap {a: 1}', {min: true});
+ });
+
+ it('supports an object with multiple keys {min: true}', () => {
+ expect(Immutable.OrderedMap({a: 1, b: 2, c: 3}))
+ .toPrettyPrintTo('Immutable.OrderedMap {a: 1, b: 2, c: 3}', {min: true});
+ });
+
+ it('supports an object with multiple keys {min: false}', () => {
+ expect(Immutable.OrderedMap({a: 1, b: 2, c: 3}))
+ .toPrettyPrintTo('Immutable.OrderedMap {\n a: 1,\n b: 2,\n c: 3,\n}');
+ });
+
+ it('supports object elements {min: true}', () => {
+ expect(Immutable.OrderedMap({key: {a: 1, b: 2, c: 3}}))
+ .toPrettyPrintTo('Immutable.OrderedMap {key: {\"a\": 1, \"b\": 2, \"c\": 3}}', {min: true});
+ });
+
+ it('supports object elements {min: false}', () => {
+ expect(Immutable.OrderedMap({key: {a: 1, b: 2, c: 3}}))
+ .toPrettyPrintTo('Immutable.OrderedMap {\n key: Object {\n \"a\": 1,\n \"b\": 2,\n \"c\": 3,\n },\n}');
+ });
+
+ it('supports React components {min: true}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.OrderedMap({a: reactComponent, b: reactComponent}))
+ .toPrettyPrintTo('Immutable.OrderedMap {a: Hello World, b: Hello World}', {min: true});
+ });
+
+ it('supports React components {min: false}', () => {
+ const reactComponent = React.createElement('Mouse', null, 'Hello World');
+ expect(Immutable.OrderedMap({a: reactComponent, b: reactComponent}))
+ .toPrettyPrintTo('Immutable.OrderedMap {\n a: \n Hello World\n ,\n b: \n Hello World\n ,\n}');
+ });
+});
diff --git a/packages/pretty-format/src/plugins/ImmutableList.js b/packages/pretty-format/src/plugins/ImmutableList.js
new file mode 100644
index 000000000000..69854ceb4a6a
--- /dev/null
+++ b/packages/pretty-format/src/plugins/ImmutableList.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ * @flow
+ */
+
+'use strict';
+
+const printImmutable = require('./printImmutable');
+const IS_LIST_SENTINEL = '@@__IMMUTABLE_LIST__@@';
+
+const isList = (maybeList: Object) => {
+ return !!(maybeList && maybeList[IS_LIST_SENTINEL]);
+};
+
+const test = (object: Object) => object && isList(object);
+
+const print = (
+ val: Object,
+ print: Function,
+ indent: Function,
+ opts: Object,
+ colors: Object
+) => {
+ return printImmutable(val, print, indent, opts, colors, 'List', false);
+};
+
+module.exports = {print, test};
diff --git a/packages/pretty-format/src/plugins/ImmutableMap.js b/packages/pretty-format/src/plugins/ImmutableMap.js
new file mode 100644
index 000000000000..092b0b630b75
--- /dev/null
+++ b/packages/pretty-format/src/plugins/ImmutableMap.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ * @flow
+ */
+
+'use strict';
+
+const printImmutable = require('./printImmutable');
+const IS_MAP_SENTINEL = '@@__IMMUTABLE_MAP__@@';
+
+const isMap = (maybeMap: Object) => {
+ return !!(maybeMap && maybeMap[IS_MAP_SENTINEL]);
+};
+
+const test = (object: Object) => object && isMap(object);
+
+const print = (
+ val: Object,
+ print: Function,
+ indent: Function,
+ opts: Object,
+ colors: Object
+) => {
+ return printImmutable(val, print, indent, opts, colors, 'Map', true);
+};
+
+module.exports = {print, test};
diff --git a/packages/pretty-format/src/plugins/ImmutableOrderedMap.js b/packages/pretty-format/src/plugins/ImmutableOrderedMap.js
new file mode 100644
index 000000000000..6f01ee9cc23f
--- /dev/null
+++ b/packages/pretty-format/src/plugins/ImmutableOrderedMap.js
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ * @flow
+ */
+
+'use strict';
+
+const printImmutable = require('./printImmutable');
+const IS_MAP_SENTINEL = '@@__IMMUTABLE_MAP__@@';
+const IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@';
+
+const isMap = (maybeMap: Object) => {
+ return !!(maybeMap && maybeMap[IS_MAP_SENTINEL]);
+};
+
+const isOrdered = (maybeOrdered: Object) => {
+ return !!(maybeOrdered && maybeOrdered[IS_ORDERED_SENTINEL]);
+};
+
+const isOrderedMap = (maybeOrderedMap: Object) => {
+ return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap);
+};
+
+const test = (object: Object) => object && isOrderedMap(object);
+
+const print = (
+ val: Object,
+ print: Function,
+ indent: Function,
+ opts: Object,
+ colors: Object
+) => {
+ return printImmutable(val, print, indent, opts, colors, 'OrderedMap', true);
+};
+
+module.exports = {print, test};
diff --git a/packages/pretty-format/src/plugins/ImmutableOrderedSet.js b/packages/pretty-format/src/plugins/ImmutableOrderedSet.js
new file mode 100644
index 000000000000..3b158bc85ef7
--- /dev/null
+++ b/packages/pretty-format/src/plugins/ImmutableOrderedSet.js
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ * @flow
+ */
+
+'use strict';
+
+const printImmutable = require('./printImmutable');
+const IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@';
+const IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@';
+
+const isSet = (maybeSet: Object) => {
+ return !!(maybeSet && maybeSet[IS_SET_SENTINEL]);
+};
+
+const isOrdered = (maybeOrdered: Object) => {
+ return !!(maybeOrdered && maybeOrdered[IS_ORDERED_SENTINEL]);
+};
+
+const isOrderedSet = (maybeOrderedSet: Object) => {
+ return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet);
+};
+
+const test = (object: Object) => object && isOrderedSet(object);
+
+const print = (
+ val: Object,
+ print: Function,
+ indent: Function,
+ opts: Object,
+ colors: Object
+) => {
+ return printImmutable(val, print, indent, opts, colors, 'OrderedSet', false);
+};
+
+module.exports = {print, test};
diff --git a/packages/pretty-format/src/plugins/ImmutablePlugins.js b/packages/pretty-format/src/plugins/ImmutablePlugins.js
new file mode 100644
index 000000000000..4d6d73bcc28d
--- /dev/null
+++ b/packages/pretty-format/src/plugins/ImmutablePlugins.js
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ * @flow
+ */
+
+'use strict';
+
+const ImmutableOrderedSetPlugin = require('./ImmutableOrderedSet');
+const ImmutableListPlugin = require('./ImmutableList');
+const ImmutableMapPlugin = require('./ImmutableMap');
+const ImmutableOrderedMapPlugin = require('./ImmutableOrderedMap');
+const ImmutableSetPlugin = require('./ImmutableSet');
+const ImmutableStackPlugin = require('./ImmutableStack');
+
+module.exports = [
+ ImmutableOrderedSetPlugin,
+ ImmutableListPlugin,
+ ImmutableOrderedMapPlugin,
+ ImmutableMapPlugin,
+ ImmutableSetPlugin,
+ ImmutableStackPlugin,
+];
diff --git a/packages/pretty-format/src/plugins/ImmutableSet.js b/packages/pretty-format/src/plugins/ImmutableSet.js
new file mode 100644
index 000000000000..f9222c83ae63
--- /dev/null
+++ b/packages/pretty-format/src/plugins/ImmutableSet.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ * @flow
+ */
+
+'use strict';
+
+const printImmutable = require('./printImmutable');
+const IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@';
+
+const isSet = (maybeSet: Object) => {
+ return !!(maybeSet && maybeSet[IS_SET_SENTINEL]);
+};
+
+const test = (object: Object) => object && isSet(object);
+
+const print = (
+ val: Object,
+ print: Function,
+ indent: Function,
+ opts: Object,
+ colors: Object
+) => {
+ return printImmutable(val, print, indent, opts, colors, 'Set', false);
+};
+
+module.exports = {print, test};
diff --git a/packages/pretty-format/src/plugins/ImmutableStack.js b/packages/pretty-format/src/plugins/ImmutableStack.js
new file mode 100644
index 000000000000..be13c944fc2e
--- /dev/null
+++ b/packages/pretty-format/src/plugins/ImmutableStack.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ * @flow
+ */
+
+'use strict';
+
+const printImmutable = require('./printImmutable');
+const IS_STACK_SENTINEL = '@@__IMMUTABLE_STACK__@@';
+
+const isStack = (maybeStack: Object) => {
+ return !!(maybeStack && maybeStack[IS_STACK_SENTINEL]);
+};
+
+const test = (object: Object) => object && isStack(object);
+
+const print = (
+ val: Object,
+ print: Function,
+ indent: Function,
+ opts: Object,
+ colors: Object
+) => {
+ return printImmutable(val, print, indent, opts, colors, 'Stack', false);
+};
+
+module.exports = {print, test};
diff --git a/packages/pretty-format/src/plugins/printImmutable.js b/packages/pretty-format/src/plugins/printImmutable.js
new file mode 100644
index 000000000000..e34725ecfff9
--- /dev/null
+++ b/packages/pretty-format/src/plugins/printImmutable.js
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ * @flow
+ */
+
+'use strict';
+
+const IMMUTABLE_NAMESPACE = 'Immutable.';
+const SPACE = ' ';
+
+const addKey = (isMap: boolean, key: any) => {
+ return isMap ? (key + ': ') : '';
+};
+
+const addFinalEdgeSpacing = (length: number, edgeSpacing: string) => {
+ return length > 0 ? edgeSpacing : '';
+};
+
+const printImmutable = (
+ val: Object,
+ print: Function,
+ indent: Function,
+ opts: Object,
+ colors: Object,
+ immutableDataStructureName: string,
+ isMap: boolean,
+) : string => {
+ const openTag = isMap ? '{' : '[';
+ const closeTag = isMap ? '}' : ']';
+ let result = IMMUTABLE_NAMESPACE + immutableDataStructureName +
+ SPACE + openTag + opts.edgeSpacing;
+
+ const immutableArray = [];
+ val.forEach((item: any, key: any) => {
+ immutableArray.push(
+ indent(addKey(isMap, key) + print(item, print, indent, opts, colors))
+ );
+ });
+
+ if (!opts.min && immutableArray.length > 0) {
+ result += immutableArray.join(',' + opts.spacing) + ',';
+ } else {
+ result += immutableArray.join(',' + opts.spacing);
+ }
+
+ return result +
+ addFinalEdgeSpacing(immutableArray.length, opts.edgeSpacing) +
+ closeTag;
+};
+
+module.exports = printImmutable;
diff --git a/yarn.lock b/yarn.lock
index 303583c3a628..b68ea71f82cc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1171,6 +1171,10 @@ ignore@^3.2.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.2.tgz#1c51e1ef53bab6ddc15db4d9ac4ec139eceb3410"
+immutable@^3.8.1:
+ version "3.8.1"
+ resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.1.tgz#200807f11ab0f72710ea485542de088075f68cd2"
+
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"