-
-
Notifications
You must be signed in to change notification settings - Fork 270
/
provider.ts
98 lines (84 loc) · 2.59 KB
/
provider.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import { mkdirSync, statSync, unlinkSync, writeFileSync } from 'fs'
import { dirname } from 'path'
import type { SnapshotProvider } from './index.js'
import { req } from './require.js'
const envMsg = `
Run with TAP_SNAPSHOT=1 in the environment to create snapshots`
const snapshotHeading = `/* IMPORTANT
* This snapshot file is auto-generated, but designed for humans.
* It should be checked into source control and tracked carefully.
* Re-generate by setting TAP_SNAPSHOT=1 and running tests.
* Make sure to inspect the output below. Do not ignore changes!
*/
'use strict'`
const snapshotExport = (k: string, v: string) =>
`exports[\`${escape(k)}\`] = \`\n${escape(v)}\n\`\n`
const snapshotData = (data: { [k: string]: string }) =>
`${snapshotHeading}
${Object.entries(data)
.sort(([a], [b]) => a.localeCompare(b, 'en'))
.map(([k, v]) => snapshotExport(k, v))
.join('\n')}`
const escape = (s: string) =>
s
.replace(/\\/g, '\\\\')
.replace(/\`/g, '\\`')
.replace(/\$\{/g, '\\${')
/**
* This is the default snapshot provider that ships with the plugin.
* It can be overridden by providing a `snapshotProvider` option to
* the test options.
*/
export class SnapshotProviderDefault implements SnapshotProvider {
#indexes: Map<string, number> = new Map()
#snapshot?: { [k: string]: string }
file: string
constructor(file: string) {
this.file = file
}
read(msg: string): string {
if (!this.#snapshot) {
this.#load()
}
// bump the index if this one gets used again
const index = this.#indexes.get(msg) || 1
const entry = msg + ' ' + index
const s = this.#snapshot?.[entry]
if (s === undefined) {
throw new Error(`Snapshot entry not found: "${msg}"${envMsg}`)
}
this.#indexes.set(msg, index + 1)
return s.replace(/^\n|\n$/g, '')
}
snap(data: string, msg: string) {
const index = this.#indexes.get(msg) || 1
this.#indexes.set(msg, index + 1)
this.#snapshot = this.#snapshot || {}
this.#snapshot[msg + ' ' + index] = data
}
save() {
if (!this.#snapshot) {
try {
unlinkSync(this.file)
} catch (err) {
const er = err as NodeJS.ErrnoException
if (er.code !== 'ENOENT') throw er
}
return
}
mkdirSync(dirname(this.file), { recursive: true })
writeFileSync(this.file, snapshotData(this.#snapshot))
}
#load() {
try {
if (!statSync(this.file).isFile()) {
throw 'not a file'
}
this.#snapshot = req(this.file)
} catch (er) {
throw new Error(
`Snapshot file not found: ${this.file}${envMsg}`,
)
}
}
}