You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					317 lines
				
				8.4 KiB
			
		
		
			
		
	
	
					317 lines
				
				8.4 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Object.defineProperty(exports, '__esModule', {
							 | 
						||
| 
								 | 
							
								  value: true
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								exports.default = void 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _fs = _interopRequireDefault(require('fs'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _jestMessageUtil = require('jest-message-util');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _utils = require('./utils');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _inline_snapshots = require('./inline_snapshots');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _interopRequireDefault(obj) {
							 | 
						||
| 
								 | 
							
								  return obj && obj.__esModule ? obj : {default: obj};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
							 | 
						||
| 
								 | 
							
								var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var jestExistsFile =
							 | 
						||
| 
								 | 
							
								  global[Symbol.for('jest-native-exists-file')] || _fs.default.existsSync;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _defineProperty(obj, key, value) {
							 | 
						||
| 
								 | 
							
								  if (key in obj) {
							 | 
						||
| 
								 | 
							
								    Object.defineProperty(obj, key, {
							 | 
						||
| 
								 | 
							
								      value: value,
							 | 
						||
| 
								 | 
							
								      enumerable: true,
							 | 
						||
| 
								 | 
							
								      configurable: true,
							 | 
						||
| 
								 | 
							
								      writable: true
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    obj[key] = value;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return obj;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class SnapshotState {
							 | 
						||
| 
								 | 
							
								  // @ts-ignore
							 | 
						||
| 
								 | 
							
								  constructor(snapshotPath, options) {
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_counters', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_dirty', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_index', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_updateSnapshot', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_snapshotData', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_initialData', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_snapshotPath', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_inlineSnapshots', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_uncheckedKeys', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_getBabelTraverse', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_getPrettier', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, 'added', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, 'expand', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, 'matched', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, 'unmatched', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, 'updated', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this._snapshotPath = snapshotPath;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const _getSnapshotData = (0, _utils.getSnapshotData)(
							 | 
						||
| 
								 | 
							
								        this._snapshotPath,
							 | 
						||
| 
								 | 
							
								        options.updateSnapshot
							 | 
						||
| 
								 | 
							
								      ),
							 | 
						||
| 
								 | 
							
								      data = _getSnapshotData.data,
							 | 
						||
| 
								 | 
							
								      dirty = _getSnapshotData.dirty;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this._initialData = data;
							 | 
						||
| 
								 | 
							
								    this._snapshotData = data;
							 | 
						||
| 
								 | 
							
								    this._dirty = dirty;
							 | 
						||
| 
								 | 
							
								    this._getBabelTraverse = options.getBabelTraverse;
							 | 
						||
| 
								 | 
							
								    this._getPrettier = options.getPrettier;
							 | 
						||
| 
								 | 
							
								    this._inlineSnapshots = [];
							 | 
						||
| 
								 | 
							
								    this._uncheckedKeys = new Set(Object.keys(this._snapshotData));
							 | 
						||
| 
								 | 
							
								    this._counters = new Map();
							 | 
						||
| 
								 | 
							
								    this._index = 0;
							 | 
						||
| 
								 | 
							
								    this.expand = options.expand || false;
							 | 
						||
| 
								 | 
							
								    this.added = 0;
							 | 
						||
| 
								 | 
							
								    this.matched = 0;
							 | 
						||
| 
								 | 
							
								    this.unmatched = 0;
							 | 
						||
| 
								 | 
							
								    this._updateSnapshot = options.updateSnapshot;
							 | 
						||
| 
								 | 
							
								    this.updated = 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  markSnapshotsAsCheckedForTest(testName) {
							 | 
						||
| 
								 | 
							
								    this._uncheckedKeys.forEach(uncheckedKey => {
							 | 
						||
| 
								 | 
							
								      if ((0, _utils.keyToTestName)(uncheckedKey) === testName) {
							 | 
						||
| 
								 | 
							
								        this._uncheckedKeys.delete(uncheckedKey);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _addSnapshot(key, receivedSerialized, options) {
							 | 
						||
| 
								 | 
							
								    this._dirty = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (options.isInline) {
							 | 
						||
| 
								 | 
							
								      const error = options.error || new Error();
							 | 
						||
| 
								 | 
							
								      const lines = (0, _jestMessageUtil.getStackTraceLines)(error.stack || '');
							 | 
						||
| 
								 | 
							
								      const frame = (0, _jestMessageUtil.getTopFrame)(lines);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!frame) {
							 | 
						||
| 
								 | 
							
								        throw new Error(
							 | 
						||
| 
								 | 
							
								          "Jest: Couldn't infer stack frame for inline snapshot."
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      this._inlineSnapshots.push({
							 | 
						||
| 
								 | 
							
								        frame,
							 | 
						||
| 
								 | 
							
								        snapshot: receivedSerialized
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      this._snapshotData[key] = receivedSerialized;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  clear() {
							 | 
						||
| 
								 | 
							
								    this._snapshotData = this._initialData;
							 | 
						||
| 
								 | 
							
								    this._inlineSnapshots = [];
							 | 
						||
| 
								 | 
							
								    this._counters = new Map();
							 | 
						||
| 
								 | 
							
								    this._index = 0;
							 | 
						||
| 
								 | 
							
								    this.added = 0;
							 | 
						||
| 
								 | 
							
								    this.matched = 0;
							 | 
						||
| 
								 | 
							
								    this.unmatched = 0;
							 | 
						||
| 
								 | 
							
								    this.updated = 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  save() {
							 | 
						||
| 
								 | 
							
								    const hasExternalSnapshots = Object.keys(this._snapshotData).length;
							 | 
						||
| 
								 | 
							
								    const hasInlineSnapshots = this._inlineSnapshots.length;
							 | 
						||
| 
								 | 
							
								    const isEmpty = !hasExternalSnapshots && !hasInlineSnapshots;
							 | 
						||
| 
								 | 
							
								    const status = {
							 | 
						||
| 
								 | 
							
								      deleted: false,
							 | 
						||
| 
								 | 
							
								      saved: false
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) {
							 | 
						||
| 
								 | 
							
								      if (hasExternalSnapshots) {
							 | 
						||
| 
								 | 
							
								        (0, _utils.saveSnapshotFile)(this._snapshotData, this._snapshotPath);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (hasInlineSnapshots) {
							 | 
						||
| 
								 | 
							
								        const prettier = this._getPrettier(); // Load lazily
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const babelTraverse = this._getBabelTraverse(); // Load lazily
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        (0, _inline_snapshots.saveInlineSnapshots)(
							 | 
						||
| 
								 | 
							
								          this._inlineSnapshots,
							 | 
						||
| 
								 | 
							
								          prettier,
							 | 
						||
| 
								 | 
							
								          babelTraverse
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      status.saved = true;
							 | 
						||
| 
								 | 
							
								    } else if (!hasExternalSnapshots && jestExistsFile(this._snapshotPath)) {
							 | 
						||
| 
								 | 
							
								      if (this._updateSnapshot === 'all') {
							 | 
						||
| 
								 | 
							
								        _fs.default.unlinkSync(this._snapshotPath);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      status.deleted = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return status;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  getUncheckedCount() {
							 | 
						||
| 
								 | 
							
								    return this._uncheckedKeys.size || 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  getUncheckedKeys() {
							 | 
						||
| 
								 | 
							
								    return Array.from(this._uncheckedKeys);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  removeUncheckedKeys() {
							 | 
						||
| 
								 | 
							
								    if (this._updateSnapshot === 'all' && this._uncheckedKeys.size) {
							 | 
						||
| 
								 | 
							
								      this._dirty = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      this._uncheckedKeys.forEach(key => delete this._snapshotData[key]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      this._uncheckedKeys.clear();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  match({testName, received, key, inlineSnapshot, error}) {
							 | 
						||
| 
								 | 
							
								    this._counters.set(testName, (this._counters.get(testName) || 0) + 1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const count = Number(this._counters.get(testName));
							 | 
						||
| 
								 | 
							
								    const isInline = inlineSnapshot !== undefined;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!key) {
							 | 
						||
| 
								 | 
							
								      key = (0, _utils.testNameToKey)(testName, count);
							 | 
						||
| 
								 | 
							
								    } // Do not mark the snapshot as "checked" if the snapshot is inline and
							 | 
						||
| 
								 | 
							
								    // there's an external snapshot. This way the external snapshot can be
							 | 
						||
| 
								 | 
							
								    // removed with `--updateSnapshot`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!(isInline && this._snapshotData[key])) {
							 | 
						||
| 
								 | 
							
								      this._uncheckedKeys.delete(key);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const receivedSerialized = (0, _utils.serialize)(received);
							 | 
						||
| 
								 | 
							
								    const expected = isInline ? inlineSnapshot : this._snapshotData[key];
							 | 
						||
| 
								 | 
							
								    const pass = expected === receivedSerialized;
							 | 
						||
| 
								 | 
							
								    const hasSnapshot = isInline
							 | 
						||
| 
								 | 
							
								      ? inlineSnapshot !== ''
							 | 
						||
| 
								 | 
							
								      : this._snapshotData[key] !== undefined;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const snapshotIsPersisted =
							 | 
						||
| 
								 | 
							
								      isInline || _fs.default.existsSync(this._snapshotPath);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (pass && !isInline) {
							 | 
						||
| 
								 | 
							
								      // Executing a snapshot file as JavaScript and writing the strings back
							 | 
						||
| 
								 | 
							
								      // when other snapshots have changed loses the proper escaping for some
							 | 
						||
| 
								 | 
							
								      // characters. Since we check every snapshot in every test, use the newly
							 | 
						||
| 
								 | 
							
								      // generated formatted string.
							 | 
						||
| 
								 | 
							
								      // Note that this is only relevant when a snapshot is added and the dirty
							 | 
						||
| 
								 | 
							
								      // flag is set.
							 | 
						||
| 
								 | 
							
								      this._snapshotData[key] = receivedSerialized;
							 | 
						||
| 
								 | 
							
								    } // These are the conditions on when to write snapshots:
							 | 
						||
| 
								 | 
							
								    //  * There's no snapshot file in a non-CI environment.
							 | 
						||
| 
								 | 
							
								    //  * There is a snapshot file and we decided to update the snapshot.
							 | 
						||
| 
								 | 
							
								    //  * There is a snapshot file, but it doesn't have this snaphsot.
							 | 
						||
| 
								 | 
							
								    // These are the conditions on when not to write snapshots:
							 | 
						||
| 
								 | 
							
								    //  * The update flag is set to 'none'.
							 | 
						||
| 
								 | 
							
								    //  * There's no snapshot file or a file without this snapshot on a CI environment.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (
							 | 
						||
| 
								 | 
							
								      (hasSnapshot && this._updateSnapshot === 'all') ||
							 | 
						||
| 
								 | 
							
								      ((!hasSnapshot || !snapshotIsPersisted) &&
							 | 
						||
| 
								 | 
							
								        (this._updateSnapshot === 'new' || this._updateSnapshot === 'all'))
							 | 
						||
| 
								 | 
							
								    ) {
							 | 
						||
| 
								 | 
							
								      if (this._updateSnapshot === 'all') {
							 | 
						||
| 
								 | 
							
								        if (!pass) {
							 | 
						||
| 
								 | 
							
								          if (hasSnapshot) {
							 | 
						||
| 
								 | 
							
								            this.updated++;
							 | 
						||
| 
								 | 
							
								          } else {
							 | 
						||
| 
								 | 
							
								            this.added++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          this._addSnapshot(key, receivedSerialized, {
							 | 
						||
| 
								 | 
							
								            error,
							 | 
						||
| 
								 | 
							
								            isInline
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          this.matched++;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        this._addSnapshot(key, receivedSerialized, {
							 | 
						||
| 
								 | 
							
								          error,
							 | 
						||
| 
								 | 
							
								          isInline
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        this.added++;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return {
							 | 
						||
| 
								 | 
							
								        actual: '',
							 | 
						||
| 
								 | 
							
								        count,
							 | 
						||
| 
								 | 
							
								        expected: '',
							 | 
						||
| 
								 | 
							
								        key,
							 | 
						||
| 
								 | 
							
								        pass: true
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      if (!pass) {
							 | 
						||
| 
								 | 
							
								        this.unmatched++;
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          actual: (0, _utils.unescape)(receivedSerialized),
							 | 
						||
| 
								 | 
							
								          count,
							 | 
						||
| 
								 | 
							
								          expected: expected ? (0, _utils.unescape)(expected) : null,
							 | 
						||
| 
								 | 
							
								          key,
							 | 
						||
| 
								 | 
							
								          pass: false
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        this.matched++;
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          actual: '',
							 | 
						||
| 
								 | 
							
								          count,
							 | 
						||
| 
								 | 
							
								          expected: '',
							 | 
						||
| 
								 | 
							
								          key,
							 | 
						||
| 
								 | 
							
								          pass: true
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fail(testName, _received, key) {
							 | 
						||
| 
								 | 
							
								    this._counters.set(testName, (this._counters.get(testName) || 0) + 1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const count = Number(this._counters.get(testName));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!key) {
							 | 
						||
| 
								 | 
							
								      key = (0, _utils.testNameToKey)(testName, count);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this._uncheckedKeys.delete(key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this.unmatched++;
							 | 
						||
| 
								 | 
							
								    return key;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								exports.default = SnapshotState;
							 |