utils.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.saveSnapshotFile = exports.ensureDirectoryExists = exports.unescape = exports.serialize = exports.getSnapshotData = exports.getSnapshotPath = exports.keyToTestName = exports.testNameToKey = exports.SNAPSHOT_VERSION_WARNING = exports.SNAPSHOT_GUIDE_LINK = exports.SNAPSHOT_VERSION = exports.SNAPSHOT_EXTENSION = undefined;
  6. var _plugins = require('./plugins');
  7. var _chalk = require('chalk');
  8. var _chalk2 = _interopRequireDefault(_chalk);
  9. var _fs = require('fs');
  10. var _fs2 = _interopRequireDefault(_fs);
  11. var _mkdirp = require('mkdirp');
  12. var _mkdirp2 = _interopRequireDefault(_mkdirp);
  13. var _naturalCompare = require('natural-compare');
  14. var _naturalCompare2 = _interopRequireDefault(_naturalCompare);
  15. var _path = require('path');
  16. var _path2 = _interopRequireDefault(_path);
  17. var _prettyFormat = require('pretty-format');
  18. var _prettyFormat2 = _interopRequireDefault(_prettyFormat);
  19. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  20. /**
  21. * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
  22. *
  23. * This source code is licensed under the MIT license found in the
  24. * LICENSE file in the root directory of this source tree.
  25. *
  26. *
  27. */
  28. const SNAPSHOT_EXTENSION = exports.SNAPSHOT_EXTENSION = 'snap';
  29. const SNAPSHOT_VERSION = exports.SNAPSHOT_VERSION = '1';
  30. const SNAPSHOT_VERSION_REGEXP = /^\/\/ Jest Snapshot v(.+),/;
  31. const SNAPSHOT_GUIDE_LINK = exports.SNAPSHOT_GUIDE_LINK = 'https://goo.gl/fbAQLP';
  32. const SNAPSHOT_VERSION_WARNING = exports.SNAPSHOT_VERSION_WARNING = _chalk2.default.yellow(`${_chalk2.default.bold('Warning')}: Before you upgrade snapshots, ` + `we recommend that you revert any local changes to tests or other code, ` + `to ensure that you do not store invalid state.`);
  33. const writeSnapshotVersion = () => `// Jest Snapshot v${SNAPSHOT_VERSION}, ${SNAPSHOT_GUIDE_LINK}`;
  34. const validateSnapshotVersion = snapshotContents => {
  35. const versionTest = SNAPSHOT_VERSION_REGEXP.exec(snapshotContents);
  36. const version = versionTest && versionTest[1];
  37. if (!version) {
  38. return new Error(_chalk2.default.red(`${_chalk2.default.bold('Outdated snapshot')}: No snapshot header found. ` + `Jest 19 introduced versioned snapshots to ensure all developers ` + `on a project are using the same version of Jest. ` + `Please update all snapshots during this upgrade of Jest.\n\n`) + SNAPSHOT_VERSION_WARNING);
  39. }
  40. if (version < SNAPSHOT_VERSION) {
  41. return new Error(_chalk2.default.red(`${_chalk2.default.red.bold('Outdated snapshot')}: The version of the snapshot ` + `file associated with this test is outdated. The snapshot file ` + `version ensures that all developers on a project are using ` + `the same version of Jest. ` + `Please update all snapshots during this upgrade of Jest.\n\n`) + `Expected: v${SNAPSHOT_VERSION}\n` + `Received: v${version}\n\n` + SNAPSHOT_VERSION_WARNING);
  42. }
  43. if (version > SNAPSHOT_VERSION) {
  44. return new Error(_chalk2.default.red(`${_chalk2.default.red.bold('Outdated Jest version')}: The version of this ` + `snapshot file indicates that this project is meant to be used ` + `with a newer version of Jest. The snapshot file version ensures ` + `that all developers on a project are using the same version of ` + `Jest. Please update your version of Jest and re-run the tests.\n\n`) + `Expected: v${SNAPSHOT_VERSION}\n` + `Received: v${version}`);
  45. }
  46. return null;
  47. };
  48. const testNameToKey = exports.testNameToKey = (testName, count) => testName + ' ' + count;
  49. const keyToTestName = exports.keyToTestName = key => {
  50. if (!/ \d+$/.test(key)) {
  51. throw new Error('Snapshot keys must end with a number.');
  52. }
  53. return key.replace(/ \d+$/, '');
  54. };
  55. const getSnapshotPath = exports.getSnapshotPath = testPath => _path2.default.join(_path2.default.join(_path2.default.dirname(testPath), '__snapshots__'), _path2.default.basename(testPath) + '.' + SNAPSHOT_EXTENSION);
  56. const getSnapshotData = exports.getSnapshotData = (snapshotPath, update) => {
  57. const data = Object.create(null);
  58. let snapshotContents = '';
  59. let dirty = false;
  60. if (_fs2.default.existsSync(snapshotPath)) {
  61. try {
  62. snapshotContents = _fs2.default.readFileSync(snapshotPath, 'utf8');
  63. // eslint-disable-next-line no-new-func
  64. const populate = new Function('exports', snapshotContents);
  65. // $FlowFixMe
  66. populate(data);
  67. } catch (e) {}
  68. }
  69. const validationResult = validateSnapshotVersion(snapshotContents);
  70. const isInvalid = snapshotContents && validationResult;
  71. if (update === 'none' && isInvalid) {
  72. throw validationResult;
  73. }
  74. if ((update === 'all' || update === 'new') && isInvalid) {
  75. dirty = true;
  76. }
  77. return { data, dirty };
  78. };
  79. // Extra line breaks at the beginning and at the end of the snapshot are useful
  80. // to make the content of the snapshot easier to read
  81. const addExtraLineBreaks = string => string.includes('\n') ? `\n${string}\n` : string;
  82. const serialize = exports.serialize = data => {
  83. return addExtraLineBreaks(normalizeNewlines((0, _prettyFormat2.default)(data, {
  84. escapeRegex: true,
  85. plugins: (0, _plugins.getSerializers)(),
  86. printFunctionName: false
  87. })));
  88. };
  89. // unescape double quotes
  90. const unescape = exports.unescape = data => data.replace(/\\(")/g, '$1');
  91. const printBacktickString = str => {
  92. return '`' + str.replace(/`|\\|\${/g, '\\$&') + '`';
  93. };
  94. const ensureDirectoryExists = exports.ensureDirectoryExists = filePath => {
  95. try {
  96. _mkdirp2.default.sync(_path2.default.join(_path2.default.dirname(filePath)), '777');
  97. } catch (e) {}
  98. };
  99. const normalizeNewlines = string => string.replace(/\r\n|\r/g, '\n');
  100. const saveSnapshotFile = exports.saveSnapshotFile = (snapshotData, snapshotPath) => {
  101. const snapshots = Object.keys(snapshotData).sort(_naturalCompare2.default).map(key => 'exports[' + printBacktickString(key) + '] = ' + printBacktickString(normalizeNewlines(snapshotData[key])) + ';');
  102. ensureDirectoryExists(snapshotPath);
  103. _fs2.default.writeFileSync(snapshotPath, writeSnapshotVersion() + '\n\n' + snapshots.join('\n\n') + '\n');
  104. };