2 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
8 import util from 'util';
10 const chalk = require('chalk');
11 const React = require('react');
12 const ReactTestRenderer = require('react-test-renderer');
13 const leftPad = require('left-pad');
14 const prettyFormat = require('../build');
15 const ReactTestComponent = require('../build/plugins/react_test_component');
16 const worldGeoJson = require('./world.geo.json');
18 const NANOSECONDS = 1000000000;
19 let TIMES_TO_RUN = 100000;
21 function testCase(name, fn) {
22 let result, error, time, total;
31 const start = process.hrtime();
33 for (let i = 0; i < TIMES_TO_RUN; i++) {
37 const diff = process.hrtime(start);
39 total = diff[0] * 1e9 + diff[1];
40 time = Math.round(total / TIMES_TO_RUN);
52 function test(name, value, ignoreResult, prettyFormatOpts) {
53 const formatted = testCase('prettyFormat() ', () =>
54 prettyFormat(value, prettyFormatOpts),
57 const inspected = testCase('util.inspect() ', () =>
64 const stringified = testCase('JSON.stringify()', () =>
65 JSON.stringify(value, null, ' '),
68 const results = [formatted, inspected, stringified].sort(
69 (a, b) => a.time - b.time,
72 const winner = results[0];
74 results.forEach((item, index) => {
75 item.isWinner = index === 0;
76 item.isLoser = index === results.length - 1;
79 function log(current) {
80 let message = current.name;
83 message += ' - ' + leftPad(current.time, 6) + 'ns';
88 current.total / NANOSECONDS +
94 message += ' - Error: ' + current.error.message;
97 if (!ignoreResult && current.result) {
98 message += ' - ' + JSON.stringify(current.result);
101 message = ' ' + message + ' ';
104 message = chalk.dim(message);
107 const diff = current.time - winner.time;
109 if (diff > winner.time * 0.85) {
110 message = chalk.bgRed.black(message);
111 } else if (diff > winner.time * 0.65) {
112 message = chalk.bgYellow.black(message);
113 } else if (!current.error) {
114 message = chalk.bgGreen.black(message);
116 message = chalk.dim(message);
119 console.log(' ' + message);
122 console.log(name + ': ');
123 results.forEach(log);
127 function returnArguments() {
131 test('empty arguments', returnArguments());
132 test('arguments', returnArguments(1, 2, 3));
133 test('an empty array', []);
134 test('an array with items', [1, 2, 3]);
135 test('a typed array', new Uint32Array(3));
136 test('an array buffer', new ArrayBuffer(3));
137 test('a nested array', [[1, 2, 3]]);
139 test('false', false);
140 test('an error', new Error());
141 test('a typed error with a message', new TypeError('message'));
142 /* eslint-disable no-new-func */
143 test('a function constructor', new Function());
144 /* eslint-enable no-new-func */
145 test('an anonymous function', () => {});
147 test('a named function', named);
148 test('Infinity', Infinity);
149 test('-Infinity', -Infinity);
150 test('an empty map', new Map());
151 const mapWithValues = new Map();
152 const mapWithNonStringKeys = new Map();
153 mapWithValues.set('prop1', 'value1');
154 mapWithValues.set('prop2', 'value2');
155 mapWithNonStringKeys.set({prop: 'value'}, {prop: 'value'});
156 test('a map with values', mapWithValues);
157 test('a map with non-string keys', mapWithNonStringKeys);
160 test('a number', 123);
161 test('a date', new Date(10e11));
162 test('an empty object', {});
163 test('an object with properties', {prop1: 'value1', prop2: 'value2'});
164 const objectWithPropsAndSymbols = {prop: 'value1'};
165 objectWithPropsAndSymbols[Symbol('symbol1')] = 'value2';
166 objectWithPropsAndSymbols[Symbol('symbol2')] = 'value3';
167 test('an object with properties and symbols', objectWithPropsAndSymbols);
168 test('an object with sorted properties', {a: 2, b: 1});
169 test('regular expressions from constructors', new RegExp('regexp'));
170 test('regular expressions from literals', /regexp/gi);
171 test('an empty set', new Set());
172 const setWithValues = new Set();
173 setWithValues.add('value1');
174 setWithValues.add('value2');
175 test('a set with values', setWithValues);
176 test('a string', 'string');
177 test('a symbol', Symbol('symbol'));
178 test('undefined', undefined);
179 test('a WeakMap', new WeakMap());
180 test('a WeakSet', new WeakSet());
181 test('deeply nested objects', {prop: {prop: {prop: 'value'}}});
182 const circularReferences = {};
183 circularReferences.prop = circularReferences;
184 test('circular references', circularReferences);
185 const parallelReferencesInner = {};
186 const parallelReferences = {
187 prop1: parallelReferencesInner,
188 prop2: parallelReferencesInner,
190 test('parallel references', parallelReferences);
191 test('able to customize indent', {prop: 'value'});
193 for (let i = 0; i < 50; i++) {
196 test('big object', bigObj);
198 const element = React.createElement(
200 {onClick: () => {}, prop: {a: 1, b: 2}},
201 React.createElement('div', {prop: {a: 1, b: 2}}),
202 React.createElement('div'),
205 {prop: {a: 1, b: 2}},
206 React.createElement('div', null, React.createElement('div')),
210 test('react', ReactTestRenderer.create(element).toJSON(), false, {
211 plugins: [ReactTestComponent],
215 test('massive', worldGeoJson, true);