216 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
 | |
|  *
 | |
|  * This source code is licensed under the MIT license found in the
 | |
|  * LICENSE file in the root directory of this source tree.
 | |
|  */
 | |
| 
 | |
| import util from 'util';
 | |
| 
 | |
| const chalk = require('chalk');
 | |
| const React = require('react');
 | |
| const ReactTestRenderer = require('react-test-renderer');
 | |
| const leftPad = require('left-pad');
 | |
| const prettyFormat = require('../build');
 | |
| const ReactTestComponent = require('../build/plugins/ReactTestComponent');
 | |
| const worldGeoJson = require('./world.geo.json');
 | |
| 
 | |
| const NANOSECONDS = 1000000000;
 | |
| let TIMES_TO_RUN = 100000;
 | |
| 
 | |
| function testCase(name, fn) {
 | |
|   let result, error, time, total;
 | |
| 
 | |
|   try {
 | |
|     result = fn();
 | |
|   } catch (err) {
 | |
|     error = err;
 | |
|   }
 | |
| 
 | |
|   if (!error) {
 | |
|     const start = process.hrtime();
 | |
| 
 | |
|     for (let i = 0; i < TIMES_TO_RUN; i++) {
 | |
|       fn();
 | |
|     }
 | |
| 
 | |
|     const diff = process.hrtime(start);
 | |
| 
 | |
|     total = diff[0] * 1e9 + diff[1];
 | |
|     time = Math.round(total / TIMES_TO_RUN);
 | |
|   }
 | |
| 
 | |
|   return {
 | |
|     error,
 | |
|     name,
 | |
|     result,
 | |
|     time,
 | |
|     total,
 | |
|   };
 | |
| }
 | |
| 
 | |
| function test(name, value, ignoreResult, prettyFormatOpts) {
 | |
|   const formatted = testCase('prettyFormat()  ', () =>
 | |
|     prettyFormat(value, prettyFormatOpts),
 | |
|   );
 | |
| 
 | |
|   const inspected = testCase('util.inspect()  ', () =>
 | |
|     util.inspect(value, {
 | |
|       depth: null,
 | |
|       showHidden: true,
 | |
|     }),
 | |
|   );
 | |
| 
 | |
|   const stringified = testCase('JSON.stringify()', () =>
 | |
|     JSON.stringify(value, null, '  '),
 | |
|   );
 | |
| 
 | |
|   const results = [formatted, inspected, stringified].sort(
 | |
|     (a, b) => a.time - b.time,
 | |
|   );
 | |
| 
 | |
|   const winner = results[0];
 | |
| 
 | |
|   results.forEach((item, index) => {
 | |
|     item.isWinner = index === 0;
 | |
|     item.isLoser = index === results.length - 1;
 | |
|   });
 | |
| 
 | |
|   function log(current) {
 | |
|     let message = current.name;
 | |
| 
 | |
|     if (current.time) {
 | |
|       message += ' - ' + leftPad(current.time, 6) + 'ns';
 | |
|     }
 | |
|     if (current.total) {
 | |
|       message +=
 | |
|         ' - ' +
 | |
|         current.total / NANOSECONDS +
 | |
|         's total (' +
 | |
|         TIMES_TO_RUN +
 | |
|         ' runs)';
 | |
|     }
 | |
|     if (current.error) {
 | |
|       message += ' - Error: ' + current.error.message;
 | |
|     }
 | |
| 
 | |
|     if (!ignoreResult && current.result) {
 | |
|       message += ' - ' + JSON.stringify(current.result);
 | |
|     }
 | |
| 
 | |
|     message = ' ' + message + ' ';
 | |
| 
 | |
|     if (current.error) {
 | |
|       message = chalk.dim(message);
 | |
|     }
 | |
| 
 | |
|     const diff = current.time - winner.time;
 | |
| 
 | |
|     if (diff > winner.time * 0.85) {
 | |
|       message = chalk.bgRed.black(message);
 | |
|     } else if (diff > winner.time * 0.65) {
 | |
|       message = chalk.bgYellow.black(message);
 | |
|     } else if (!current.error) {
 | |
|       message = chalk.bgGreen.black(message);
 | |
|     } else {
 | |
|       message = chalk.dim(message);
 | |
|     }
 | |
| 
 | |
|     console.log('  ' + message);
 | |
|   }
 | |
| 
 | |
|   console.log(name + ': ');
 | |
|   results.forEach(log);
 | |
|   console.log();
 | |
| }
 | |
| 
 | |
| function returnArguments() {
 | |
|   return arguments;
 | |
| }
 | |
| 
 | |
| test('empty arguments', returnArguments());
 | |
| test('arguments', returnArguments(1, 2, 3));
 | |
| test('an empty array', []);
 | |
| test('an array with items', [1, 2, 3]);
 | |
| test('a typed array', new Uint32Array(3));
 | |
| test('an array buffer', new ArrayBuffer(3));
 | |
| test('a nested array', [[1, 2, 3]]);
 | |
| test('true', true);
 | |
| test('false', false);
 | |
| test('an error', new Error());
 | |
| test('a typed error with a message', new TypeError('message'));
 | |
| /* eslint-disable no-new-func */
 | |
| test('a function constructor', new Function());
 | |
| /* eslint-enable no-new-func */
 | |
| test('an anonymous function', () => {});
 | |
| function named() {}
 | |
| test('a named function', named);
 | |
| test('Infinity', Infinity);
 | |
| test('-Infinity', -Infinity);
 | |
| test('an empty map', new Map());
 | |
| const mapWithValues = new Map();
 | |
| const mapWithNonStringKeys = new Map();
 | |
| mapWithValues.set('prop1', 'value1');
 | |
| mapWithValues.set('prop2', 'value2');
 | |
| mapWithNonStringKeys.set({prop: 'value'}, {prop: 'value'});
 | |
| test('a map with values', mapWithValues);
 | |
| test('a map with non-string keys', mapWithNonStringKeys);
 | |
| test('NaN', NaN);
 | |
| test('null', null);
 | |
| test('a number', 123);
 | |
| test('a date', new Date(10e11));
 | |
| test('an empty object', {});
 | |
| test('an object with properties', {prop1: 'value1', prop2: 'value2'});
 | |
| const objectWithPropsAndSymbols = {prop: 'value1'};
 | |
| objectWithPropsAndSymbols[Symbol('symbol1')] = 'value2';
 | |
| objectWithPropsAndSymbols[Symbol('symbol2')] = 'value3';
 | |
| test('an object with properties and symbols', objectWithPropsAndSymbols);
 | |
| test('an object with sorted properties', {a: 2, b: 1});
 | |
| test('regular expressions from constructors', new RegExp('regexp'));
 | |
| test('regular expressions from literals', /regexp/gi);
 | |
| test('an empty set', new Set());
 | |
| const setWithValues = new Set();
 | |
| setWithValues.add('value1');
 | |
| setWithValues.add('value2');
 | |
| test('a set with values', setWithValues);
 | |
| test('a string', 'string');
 | |
| test('a symbol', Symbol('symbol'));
 | |
| test('undefined', undefined);
 | |
| test('a WeakMap', new WeakMap());
 | |
| test('a WeakSet', new WeakSet());
 | |
| test('deeply nested objects', {prop: {prop: {prop: 'value'}}});
 | |
| const circularReferences = {};
 | |
| circularReferences.prop = circularReferences;
 | |
| test('circular references', circularReferences);
 | |
| const parallelReferencesInner = {};
 | |
| const parallelReferences = {
 | |
|   prop1: parallelReferencesInner,
 | |
|   prop2: parallelReferencesInner,
 | |
| };
 | |
| test('parallel references', parallelReferences);
 | |
| test('able to customize indent', {prop: 'value'});
 | |
| const bigObj = {};
 | |
| for (let i = 0; i < 50; i++) {
 | |
|   bigObj[i] = i;
 | |
| }
 | |
| test('big object', bigObj);
 | |
| 
 | |
| const element = React.createElement(
 | |
|   'div',
 | |
|   {onClick: () => {}, prop: {a: 1, b: 2}},
 | |
|   React.createElement('div', {prop: {a: 1, b: 2}}),
 | |
|   React.createElement('div'),
 | |
|   React.createElement(
 | |
|     'div',
 | |
|     {prop: {a: 1, b: 2}},
 | |
|     React.createElement('div', null, React.createElement('div')),
 | |
|   ),
 | |
| );
 | |
| 
 | |
| test('react', ReactTestRenderer.create(element).toJSON(), false, {
 | |
|   plugins: [ReactTestComponent],
 | |
| });
 | |
| 
 | |
| TIMES_TO_RUN = 100;
 | |
| test('massive', worldGeoJson, true);
 |