formatting.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. import React from 'react';
  2. import test from '../..';
  3. import HelloMessage from './hello-message';
  4. // Older AVA versions that do not use Concordance don't handle globals very
  5. // well. Use this so formatting output can be contrasted between versions.
  6. const formatGlobals = Boolean(require(process.env.AVA_PATH + '/package.json').dependencies.concordance);
  7. test('date formatted', t => {
  8. const date = new Date('1969-07-20T20:17:40.000Z');
  9. t.true(date);
  10. });
  11. test('invalid date formatted', t => {
  12. const date = new Date('🙀');
  13. t.true(date);
  14. });
  15. test('date formatted, subclass', t => {
  16. class Foo extends Date {}
  17. const date = new Foo('1969-07-20T20:17:40.000Z');
  18. t.true(date);
  19. });
  20. test('date diff', t => {
  21. t.deepEqual(new Date('1969-07-20T20:17:40.000Z'), new Date());
  22. });
  23. test('date diff, extra properties', t => {
  24. t.deepEqual(new Date('1969-07-20T20:17:40.000Z'), Object.assign(new Date('1969-07-20T20:17:40.000Z'), {
  25. foo: 'bar'
  26. }));
  27. });
  28. test('error formatted', t => {
  29. const err = new Error('Houston, we have a problem');
  30. t.true(err);
  31. });
  32. test('error formatted, constructor does not match name', t => {
  33. const err = Object.assign(new Error('Houston, we have a problem'), {name: 'FamousWords'});
  34. t.true(err);
  35. });
  36. test('error formatted, constructor does not match name, and string tag does not match constructor', t => {
  37. class CustomError extends Error {
  38. constructor(message) {
  39. super(message);
  40. this.name = 'FamousWords'; // eslint-disable-line unicorn/custom-error-definition
  41. }
  42. }
  43. const err = new CustomError('Houston, we have a problem');
  44. t.true(err);
  45. });
  46. test('error formatted, no name or constructor', t => {
  47. class CustomError extends Error {
  48. constructor(message) {
  49. super(message);
  50. this.name = ''; // eslint-disable-line unicorn/custom-error-definition
  51. }
  52. }
  53. const err = new CustomError('Houston, we have a problem');
  54. Object.defineProperty(err, 'constructor', {});
  55. t.true(err);
  56. });
  57. test('error diff, message', t => {
  58. t.deepEqual(new Error('Houston, we have a problem'), new Error('One small step'));
  59. });
  60. test('error diff, constructor', t => {
  61. t.deepEqual(new Error('Houston, we have a problem'), new RangeError('One small step'));
  62. });
  63. test('error diff, extra properties', t => {
  64. t.deepEqual(new Error('Houston, we have a problem'), Object.assign(new Error('Houston, we have a problem'), {
  65. date: new Date('1969-07-20T20:17:40.000Z')
  66. }));
  67. });
  68. test('error thrown in test', () => {
  69. throw Object.assign(new Error('Houston, we have a problem'), {
  70. date: new Date('1969-07-20T20:17:40.000Z')
  71. });
  72. });
  73. test.cb('callback test ended with error', t => {
  74. t.end(Object.assign(new Error('Houston, we have a problem'), {
  75. date: new Date('1969-07-20T20:17:40.000Z')
  76. }));
  77. });
  78. test('error thrown in test due to improper throws', t => {
  79. const improper = () => {
  80. throw Object.assign(new Error('Houston, we have a problem'), {
  81. date: new Date('1969-07-20T20:17:40.000Z')
  82. });
  83. };
  84. t.throws(improper());
  85. });
  86. test('test returned rejected promise', () => {
  87. return Promise.reject(Object.assign(new Error('Houston, we have a problem'), {
  88. date: new Date('1969-07-20T20:17:40.000Z')
  89. }));
  90. });
  91. test('array of strings formatted', t => {
  92. const arr = ['foo'];
  93. t.true(arr);
  94. });
  95. test('array of strings diff', t => {
  96. t.deepEqual(['foo'], ['bar']);
  97. });
  98. test('string formatted', t => {
  99. t.true('foo');
  100. });
  101. test('string diff', t => {
  102. t.is('foo', 'bar');
  103. });
  104. test('string diff, with overlap', t => {
  105. t.is('foobar', 'bar');
  106. });
  107. test('multiline string diff, with overlap at start', t => {
  108. t.is('foo\nbar', 'foo\nbaz');
  109. });
  110. test('multiline string diff, with overlap at end', t => {
  111. t.is('bar\nbaz', 'foo\nbaz');
  112. });
  113. test('map formatted', t => {
  114. const map = new Map([['foo', 'bar']]);
  115. t.true(map);
  116. });
  117. test('map diff', t => {
  118. t.deepEqual(new Map([['foo', 'bar']]), new Map([['baz', 'qux']]));
  119. });
  120. test('map diff, extra properties', t => {
  121. t.deepEqual(new Map([['foo', 'bar']]), Object.assign(new Map([['foo', 'bar']]), {baz: 'qux'}));
  122. });
  123. test('function formatted', t => {
  124. const fn = function foo() {}; // eslint-disable-line func-name-matching, func-names
  125. t.true(fn);
  126. });
  127. test('function diff', t => {
  128. function foo() {}
  129. function bar() {}
  130. t.deepEqual(foo, bar);
  131. });
  132. test('function diff, extra properties', t => {
  133. function foo() {}
  134. function bar() {}
  135. t.deepEqual(foo, Object.assign(bar, {baz: 'qux'}));
  136. });
  137. test('anonymous function', t => {
  138. t.true(() => {});
  139. });
  140. test('generator function', t => {
  141. t.true(function * foo() {}); // eslint-disable-line func-names
  142. });
  143. test('arguments formatted', t => {
  144. const args = (function () {
  145. return arguments;
  146. })('foo');
  147. t.true(args);
  148. });
  149. test('arguments diff', t => {
  150. const foo = (function () {
  151. return arguments;
  152. })('foo');
  153. const bar = (function () {
  154. return arguments;
  155. })('bar');
  156. t.deepEqual(foo, bar);
  157. });
  158. test('arguments diff with normal array', t => {
  159. const foo = (function () {
  160. return arguments;
  161. })('foo');
  162. t.deepEqual(foo, ['bar']);
  163. });
  164. if (formatGlobals) {
  165. test('global formatted', t => {
  166. t.true(global);
  167. });
  168. test('global diff', t => {
  169. t.deepEqual(global, {});
  170. });
  171. }
  172. test('object formatted', t => {
  173. const obj = {
  174. foo: 'bar'
  175. };
  176. t.true(obj);
  177. });
  178. test('object diff', t => {
  179. t.deepEqual({
  180. foo: 'bar'
  181. }, {
  182. baz: 'qux'
  183. });
  184. });
  185. test('object formatted, custom class', t => {
  186. class Foo {}
  187. const obj = new Foo();
  188. t.true(obj);
  189. });
  190. test('object formatted, no constructor', t => {
  191. class Foo {}
  192. const obj = new Foo();
  193. Object.defineProperty(obj, 'constructor', {});
  194. t.true(obj);
  195. });
  196. test('object formatted, non-Object string tag that does not match constructor', t => {
  197. class Foo extends Array {}
  198. const obj = new Foo();
  199. t.true(obj);
  200. });
  201. test('promise formatted', t => {
  202. const promise = Promise.resolve();
  203. t.true(promise);
  204. });
  205. test('promise diff', t => {
  206. t.deepEqual(Promise.resolve(), Promise.resolve());
  207. });
  208. test('promise diff, extra properties', t => {
  209. t.deepEqual(Promise.resolve(), Object.assign(Promise.resolve(), {foo: 'bar'}));
  210. });
  211. test('regexp formatted', t => {
  212. const regexp = /foo/gi;
  213. t.true(regexp);
  214. });
  215. test('regexp diff', t => {
  216. t.deepEqual(/foo/gi, /bar/gi);
  217. });
  218. test('regexp diff, extra properties', t => {
  219. t.deepEqual(/foo/gi, Object.assign(/foo/gi, {baz: 'qux'}));
  220. });
  221. test('set formatted', t => {
  222. const set = new Set([{foo: 'bar'}]);
  223. t.true(set);
  224. });
  225. test('set diff, string values', t => {
  226. t.deepEqual(new Set(['foo']), new Set(['bar']));
  227. });
  228. test('set diff, object values', t => {
  229. t.deepEqual(new Set([{foo: 'bar'}]), new Set([{bar: 'baz'}]));
  230. });
  231. test('set diff, distinct values', t => {
  232. t.deepEqual(new Set([{foo: 'bar'}]), new Set([null]));
  233. });
  234. test('set diff, extra properties', t => {
  235. t.deepEqual(new Set([{foo: 'bar'}]), Object.assign(new Set([{foo: 'bar'}]), {baz: 'qux'}));
  236. });
  237. test('buffer formatted', t => {
  238. const buffer = Buffer.from('decafba'.repeat(12), 'hex');
  239. t.true(buffer);
  240. });
  241. test('buffer diff', t => {
  242. t.deepEqual(Buffer.from('decafba'.repeat(12), 'hex'), Buffer.from('baddecaf', 'hex'));
  243. });
  244. test('buffer diff, extra properties', t => {
  245. t.deepEqual(Buffer.from('decafba'.repeat(12), 'hex'), Object.assign(Buffer.from('decafba'.repeat(12), 'hex'), {foo: 'bar'}));
  246. });
  247. test('primitives', t => {
  248. const primitives = [
  249. true,
  250. false,
  251. null,
  252. 0,
  253. -0,
  254. 42,
  255. Infinity,
  256. -Infinity,
  257. NaN,
  258. 'foo',
  259. 'foo\nbar',
  260. Symbol.iterator,
  261. Symbol.for('foo'),
  262. Symbol('bar'),
  263. undefined
  264. ];
  265. t.true(primitives);
  266. });
  267. test('circular references', t => {
  268. const obj = {};
  269. obj.circular = obj;
  270. t.true(obj);
  271. });
  272. test('react element, formatted', t => {
  273. const element = React.createElement(HelloMessage, {name: 'Sindre'});
  274. t.true(element);
  275. });
  276. test('react element, complex attributes, formatted', t => {
  277. const element = React.createElement('div', {
  278. multiline: 'Hello\nworld',
  279. object: {foo: ['bar']}
  280. });
  281. t.true(element);
  282. });
  283. test('react element, opaque children, formatted', t => {
  284. const element = React.createElement('Foo', null, new Set(['foo']), true);
  285. t.true(element);
  286. });
  287. test('react element, diff', t => {
  288. const element = React.createElement(HelloMessage, {name: 'Sindre'});
  289. const other = React.createElement(HelloMessage, {name: 'Vadim'});
  290. t.deepEqual(element, other);
  291. });
  292. test('deep structure, formatted', t => {
  293. const deep = {
  294. foo: {
  295. bar: {
  296. baz: {
  297. qux: 'quux'
  298. }
  299. }
  300. }
  301. };
  302. t.true(deep);
  303. });
  304. test('deep structure, diff', t => {
  305. const deep = {
  306. foo: {
  307. bar: {
  308. baz: {
  309. qux: 'quux'
  310. }
  311. }
  312. }
  313. };
  314. t.deepEqual(deep, Object.assign({corge: 'grault'}, deep));
  315. });