UNPKG

3.2 kBJavaScriptView Raw
1'use strict'
2
3const la = require('lazy-ass')
4const is = require('check-more-types')
5const Result = require('folktale/result')
6const jsesc = require('jsesc')
7
8// TODO: we should also consider the file spec name + test name id:5
9// Gleb Bahmutov
10// gleb.bahmutov@gmail.com
11// https://github.com/bahmutov/snap-shot-core/issues/90
12// not just spec name (which is test name here)
13function snapshotIndex (options) {
14 const counters = options.counters
15 const file = options.file
16 const specName = options.specName
17
18 la(is.object(counters), 'expected counters', counters)
19 la(is.unemptyString(specName), 'expected specName', specName)
20 la(is.unemptyString(file), 'missing filename', file)
21
22 if (!(specName in counters)) {
23 counters[specName] = 1
24 } else {
25 counters[specName] += 1
26 }
27 return counters[specName]
28}
29
30// make sure values in the object are "safe" to be serialized
31// and compared from loaded value
32function strip (o) {
33 if (is.fn(o)) {
34 return o
35 }
36 return JSON.parse(JSON.stringify(o))
37}
38
39function compare (options) {
40 const expected = options.expected
41 const value = options.value
42
43 const e = JSON.stringify(expected)
44 const v = JSON.stringify(value)
45 if (e === v) {
46 return Result.Ok()
47 }
48 return Result.Error(`${e} !== ${v}`)
49}
50
51const sameTypes = (a, b) => typeof expected === typeof value
52
53const compareTypes = options => {
54 const expected = options.expected
55 const value = options.value
56 return sameTypes(expected, value) ? Result.Ok() : Result.Error('no message')
57}
58
59/**
60 * Serializes and escapes a string value before saving.
61 * @param {string} name for the snapshot
62 * @param {string} value text to be escaped for saving
63 */
64function exportText (name, value) {
65 la(is.unemptyString(name), 'expected snapshot name, got:', name)
66 la(is.string(value), 'expected string value', value)
67
68 // jsesc replace "\n" with "\\n"
69 // https://github.com/mathiasbynens/jsesc/issues/20
70 const serialized = value
71 .split('\n')
72 .map(line => {
73 return jsesc(line, {
74 quotes: 'backtick',
75 minimal: true
76 })
77 })
78 .join('\n')
79 const withNewLines = '\n' + serialized + '\n'
80 return `exports['${name}'] = \`${withNewLines}\`\n`
81}
82
83/**
84 * Escapes properties of an object to be safe for saving
85 */
86function exportObject (name, value) {
87 const serialized = jsesc(value, {
88 json: true,
89 compact: false,
90 indent: ' ',
91 minimal: true
92 })
93 return `exports['${name}'] = ${serialized}\n`
94}
95
96const isSurroundedByNewLines = s =>
97 is.string(s) && s.length > 1 && s[0] === '\n' && s[s.length - 1] === '\n'
98
99// when we save string snapshots we add extra new lines to
100// avoid long first lines
101// when loading snapshots we should remove these new lines
102// from string properties
103function removeExtraNewLines (snapshots) {
104 Object.keys(snapshots).forEach(key => {
105 const value = snapshots[key]
106 if (isSurroundedByNewLines(value)) {
107 snapshots[key] = value.substr(1, value.length - 2)
108 }
109 })
110 return snapshots
111}
112
113const DEFAULT_EXTENSION = '.snapshot.js'
114
115module.exports = {
116 snapshotIndex,
117 strip,
118 compare,
119 sameTypes,
120 compareTypes,
121 exportText,
122 exportObject,
123 removeExtraNewLines,
124 DEFAULT_EXTENSION
125}