test.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. import util from 'util';
  8. const chalk = require('chalk');
  9. const React = require('react');
  10. const ReactTestRenderer = require('react-test-renderer');
  11. const leftPad = require('left-pad');
  12. const prettyFormat = require('../build');
  13. const ReactTestComponent = require('../build/plugins/ReactTestComponent');
  14. const worldGeoJson = require('./world.geo.json');
  15. const NANOSECONDS = 1000000000;
  16. let TIMES_TO_RUN = 100000;
  17. function testCase(name, fn) {
  18. let result, error, time, total;
  19. try {
  20. result = fn();
  21. } catch (err) {
  22. error = err;
  23. }
  24. if (!error) {
  25. const start = process.hrtime();
  26. for (let i = 0; i < TIMES_TO_RUN; i++) {
  27. fn();
  28. }
  29. const diff = process.hrtime(start);
  30. total = diff[0] * 1e9 + diff[1];
  31. time = Math.round(total / TIMES_TO_RUN);
  32. }
  33. return {
  34. error,
  35. name,
  36. result,
  37. time,
  38. total,
  39. };
  40. }
  41. function test(name, value, ignoreResult, prettyFormatOpts) {
  42. const formatted = testCase('prettyFormat() ', () =>
  43. prettyFormat(value, prettyFormatOpts),
  44. );
  45. const inspected = testCase('util.inspect() ', () =>
  46. util.inspect(value, {
  47. depth: null,
  48. showHidden: true,
  49. }),
  50. );
  51. const stringified = testCase('JSON.stringify()', () =>
  52. JSON.stringify(value, null, ' '),
  53. );
  54. const results = [formatted, inspected, stringified].sort(
  55. (a, b) => a.time - b.time,
  56. );
  57. const winner = results[0];
  58. results.forEach((item, index) => {
  59. item.isWinner = index === 0;
  60. item.isLoser = index === results.length - 1;
  61. });
  62. function log(current) {
  63. let message = current.name;
  64. if (current.time) {
  65. message += ' - ' + leftPad(current.time, 6) + 'ns';
  66. }
  67. if (current.total) {
  68. message +=
  69. ' - ' +
  70. current.total / NANOSECONDS +
  71. 's total (' +
  72. TIMES_TO_RUN +
  73. ' runs)';
  74. }
  75. if (current.error) {
  76. message += ' - Error: ' + current.error.message;
  77. }
  78. if (!ignoreResult && current.result) {
  79. message += ' - ' + JSON.stringify(current.result);
  80. }
  81. message = ' ' + message + ' ';
  82. if (current.error) {
  83. message = chalk.dim(message);
  84. }
  85. const diff = current.time - winner.time;
  86. if (diff > winner.time * 0.85) {
  87. message = chalk.bgRed.black(message);
  88. } else if (diff > winner.time * 0.65) {
  89. message = chalk.bgYellow.black(message);
  90. } else if (!current.error) {
  91. message = chalk.bgGreen.black(message);
  92. } else {
  93. message = chalk.dim(message);
  94. }
  95. console.log(' ' + message);
  96. }
  97. console.log(name + ': ');
  98. results.forEach(log);
  99. console.log();
  100. }
  101. function returnArguments() {
  102. return arguments;
  103. }
  104. test('empty arguments', returnArguments());
  105. test('arguments', returnArguments(1, 2, 3));
  106. test('an empty array', []);
  107. test('an array with items', [1, 2, 3]);
  108. test('a typed array', new Uint32Array(3));
  109. test('an array buffer', new ArrayBuffer(3));
  110. test('a nested array', [[1, 2, 3]]);
  111. test('true', true);
  112. test('false', false);
  113. test('an error', new Error());
  114. test('a typed error with a message', new TypeError('message'));
  115. /* eslint-disable no-new-func */
  116. test('a function constructor', new Function());
  117. /* eslint-enable no-new-func */
  118. test('an anonymous function', () => {});
  119. function named() {}
  120. test('a named function', named);
  121. test('Infinity', Infinity);
  122. test('-Infinity', -Infinity);
  123. test('an empty map', new Map());
  124. const mapWithValues = new Map();
  125. const mapWithNonStringKeys = new Map();
  126. mapWithValues.set('prop1', 'value1');
  127. mapWithValues.set('prop2', 'value2');
  128. mapWithNonStringKeys.set({prop: 'value'}, {prop: 'value'});
  129. test('a map with values', mapWithValues);
  130. test('a map with non-string keys', mapWithNonStringKeys);
  131. test('NaN', NaN);
  132. test('null', null);
  133. test('a number', 123);
  134. test('a date', new Date(10e11));
  135. test('an empty object', {});
  136. test('an object with properties', {prop1: 'value1', prop2: 'value2'});
  137. const objectWithPropsAndSymbols = {prop: 'value1'};
  138. objectWithPropsAndSymbols[Symbol('symbol1')] = 'value2';
  139. objectWithPropsAndSymbols[Symbol('symbol2')] = 'value3';
  140. test('an object with properties and symbols', objectWithPropsAndSymbols);
  141. test('an object with sorted properties', {a: 2, b: 1});
  142. test('regular expressions from constructors', new RegExp('regexp'));
  143. test('regular expressions from literals', /regexp/gi);
  144. test('an empty set', new Set());
  145. const setWithValues = new Set();
  146. setWithValues.add('value1');
  147. setWithValues.add('value2');
  148. test('a set with values', setWithValues);
  149. test('a string', 'string');
  150. test('a symbol', Symbol('symbol'));
  151. test('undefined', undefined);
  152. test('a WeakMap', new WeakMap());
  153. test('a WeakSet', new WeakSet());
  154. test('deeply nested objects', {prop: {prop: {prop: 'value'}}});
  155. const circularReferences = {};
  156. circularReferences.prop = circularReferences;
  157. test('circular references', circularReferences);
  158. const parallelReferencesInner = {};
  159. const parallelReferences = {
  160. prop1: parallelReferencesInner,
  161. prop2: parallelReferencesInner,
  162. };
  163. test('parallel references', parallelReferences);
  164. test('able to customize indent', {prop: 'value'});
  165. const bigObj = {};
  166. for (let i = 0; i < 50; i++) {
  167. bigObj[i] = i;
  168. }
  169. test('big object', bigObj);
  170. const element = React.createElement(
  171. 'div',
  172. {onClick: () => {}, prop: {a: 1, b: 2}},
  173. React.createElement('div', {prop: {a: 1, b: 2}}),
  174. React.createElement('div'),
  175. React.createElement(
  176. 'div',
  177. {prop: {a: 1, b: 2}},
  178. React.createElement('div', null, React.createElement('div')),
  179. ),
  180. );
  181. test('react', ReactTestRenderer.create(element).toJSON(), false, {
  182. plugins: [ReactTestComponent],
  183. });
  184. TIMES_TO_RUN = 100;
  185. test('massive', worldGeoJson, true);