UNPKG

2.95 kBJavaScriptView Raw
1'use strict'
2
3const fs = require('fs')
4const path = require('path')
5const diff = require('variable-diff')
6const disparity = require('disparity')
7const debug = require('debug')('snap-shot')
8const la = require('lazy-ass')
9const is = require('check-more-types')
10const mkdirp = require('mkdirp')
11const vm = require('vm')
12
13const cwd = process.cwd()
14const fromCurrentFolder = path.relative.bind(null, cwd)
15const snapshotsFolder = fromCurrentFolder('__snapshots__')
16
17function loadSnaps (snapshotPath) {
18 const full = require.resolve(snapshotPath)
19 if (!fs.existsSync(snapshotPath)) {
20 return {}
21 }
22
23 const sandbox = {
24 exports: {}
25 }
26 const source = fs.readFileSync(full, 'utf8')
27 try {
28 vm.runInNewContext(source, sandbox)
29 return sandbox.exports
30 } catch (e) {
31 console.error('Could not load file', full)
32 console.error(source)
33 console.error(e)
34 return {}
35 }
36}
37
38function fileForSpec (specFile) {
39 const specName = path.basename(specFile)
40 const filename = path.join(snapshotsFolder, specName + '.snap-shot')
41 return path.resolve(filename)
42}
43
44function loadSnapshots (specFile) {
45 la(is.unemptyString(specFile), 'missing specFile name', specFile)
46 const filename = fileForSpec(specFile)
47 debug('loading snapshots from %s', filename)
48 let snapshots = {}
49 if (fs.existsSync(filename)) {
50 snapshots = loadSnaps(filename)
51 } else {
52 debug('could not find snapshots file %s', filename)
53 }
54 return snapshots
55}
56
57function saveSnapshots (specFile, snapshots) {
58 mkdirp.sync(snapshotsFolder)
59 const filename = fileForSpec(specFile)
60 const specRelativeName = fromCurrentFolder(specFile)
61 debug('saving snapshots into %s for %s', filename, specRelativeName)
62
63 let s = ''
64 Object.keys(snapshots).forEach(testName => {
65 const value = snapshots[testName]
66 const serialized = JSON.stringify(value, null, 2)
67 s += `exports['${testName}'] = ${serialized}\n\n`
68 })
69 fs.writeFileSync(filename, s, 'utf8')
70 return snapshots
71}
72
73const isMultiLineText = s => is.string(s) && s.includes('\n')
74const areStrings = (s, t) => is.string(s) && is.string(t)
75const compareAsStrings = (s, t) => areStrings(s, t) &&
76 (isMultiLineText(s) || isMultiLineText(t))
77
78function compareText (expected, value) {
79 const textDiff = disparity.unified(expected, value)
80 if (!textDiff) {
81 return {changed: false}
82 }
83 return {
84 changed: true,
85 text: textDiff
86 }
87}
88
89const compareObjects = diff
90
91function raiseIfDifferent ({value, expected, specName}) {
92 const diffed = compareAsStrings(value, expected)
93 ? compareText(expected + '\n', value + '\n')
94 : compareObjects(expected, value)
95 if (diffed.changed) {
96 const text = diffed.text
97 debug('Test "%s" snapshot difference', specName)
98 const msg = `snapshot difference\n${text}`
99 console.log(msg)
100 throw new Error(msg)
101 }
102}
103
104module.exports = {
105 readFileSync: fs.readFileSync,
106 fromCurrentFolder,
107 loadSnapshots,
108 saveSnapshots,
109 raiseIfDifferent
110}