'use strict'
/**
* @module extensions/snapshot/Snapshot
*/
const prettyFormat = require('pretty-format')
const snapshot = require('./snapshot')
const clean = require('./clean')
const statistics = require('./statistics')
/**
* Snapshot extension.
*
* @class
*/
class Snapshot {
/**
* @param {Object} options - Options
* @param {boolean} [options.updateSnapshots=false] - Should we update the snapshots
* @param {boolean} [options.cleanSnapshots=false] - Should we clean the snapshot to remove unused snapshots
*/
constructor(options) {
this.options = options || {}
this.shouldUpdate = this.options.updateSnapshots
this.cleanSnapshots = this.options.cleanSnapshots
this.featureFile = null
this.scenarioLine = -1
this._snapshotsCount = 0
}
/**
* Compare a content to it's snapshot.
* If no snapshot yet, it create it.
*
* It uses the context to name the snapshot: feature file, scenario name and nth snapshot of scenario
* Snapshot name will be by default stored in FEATURE_FILE_FOLDER_PATH/__snapshots__/FEATURE_FILE_NAME.snap
* And snapshot name will be "SCENARIO_NAME NUMBER_OF_TIME_SCNEARIO_NAME_APPEARD_IN_FEATURE.NUMBER_OF_TIME_WE_SNAPSHOTED_IN_CURRENT_SCENARIO"
* For the first scenario of a scenario called "Scenario 1" that only appears once in feature file,
* snapshot name will be "Scenario 1 1.1"
*
* If option "-u" or "--updateSnapshots" is used, all snapshots will be updated
* If options "--cleanSnapshots" is used, unused stored snapshots will be removed.
* @param {*} expectedContent - Content to compare to snapshot
* @throws {string} If snapshot and expected content doesn't match, it throws diff between both
*/
expectToMatch(expectedContent) {
expectedContent = prettyFormat(expectedContent)
let snapshotsFile = snapshot.snapshotsPath(this.featureFile, this.options)
const scenarios = snapshot.extractScenarios(this.featureFile)
const snapshotsPrefix = snapshot.prefixSnapshots(scenarios)[this.scenarioLine]
if (!snapshotsPrefix)
throw new Error(
`Can not do a snapshot. Scenario not found in file ${this
.featureFile} on line ${this.scenarioLine}`
)
this._snapshotsCount += 1
const snapshotName = `${snapshotsPrefix.prefix}.${this._snapshotsCount}`
if (this.cleanSnapshots) clean.referenceSnapshot(snapshotsFile, snapshotName) // To clean after all unreferenced snapshots
const snapshotsContents = snapshot.readSnapshotFile(snapshotsFile)
let snapshotContent = snapshotsContents[snapshotName]
if (!snapshotContent) {
statistics.created.push({ file: this.featureFile, name: snapshotName })
} else if (this.shouldUpdate) {
statistics.updated.push({ file: this.featureFile, name: snapshotName })
}
if (!snapshotContent || this.shouldUpdate) {
snapshotsContents[snapshotName] = expectedContent
snapshot.writeSnapshotFile(snapshotsFile, snapshotsContents)
snapshotContent = expectedContent
}
const diff = snapshot.diff(snapshotContent, expectedContent)
if (diff) throw new Error(diff)
}
}
/**
* Create a new isolated Snapshot module
* @return {Snapshot}
*/
module.exports = function(...args) {
return new Snapshot(...args)
}
/**
* Snapshot extension.
* @type {Snapshot}
*/
module.exports.Snapshot = Snapshot