Skip to content

Commit a4c80cd

Browse files
committed
Add snapshot testing for examples
1 parent b566f71 commit a4c80cd

File tree

2 files changed

+169
-20
lines changed

2 files changed

+169
-20
lines changed

examples/.snapshot

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
exports[`examples > fibonacci.plz --input="not a number" > stderr 1`] = `
2+
3+
`;
4+
5+
exports[`examples > fibonacci.plz --input="not a number" > stdout 1`] = `
6+
"input must be a natural number"
7+
8+
`;
9+
10+
exports[`examples > fibonacci.plz --input=-1 > stderr 1`] = `
11+
12+
`;
13+
14+
exports[`examples > fibonacci.plz --input=-1 > stdout 1`] = `
15+
"input must be a natural number"
16+
17+
`;
18+
19+
exports[`examples > fibonacci.plz --input=0 > stderr 1`] = `
20+
21+
`;
22+
23+
exports[`examples > fibonacci.plz --input=0 > stdout 1`] = `
24+
0
25+
26+
`;
27+
28+
exports[`examples > fibonacci.plz --input=1 > stderr 1`] = `
29+
30+
`;
31+
32+
exports[`examples > fibonacci.plz --input=1 > stdout 1`] = `
33+
1
34+
35+
`;
36+
37+
exports[`examples > fibonacci.plz --input=10 > stderr 1`] = `
38+
39+
`;
40+
41+
exports[`examples > fibonacci.plz --input=10 > stdout 1`] = `
42+
55
43+
44+
`;
45+
46+
exports[`examples > fibonacci.plz --input=2 > stderr 1`] = `
47+
48+
`;
49+
50+
exports[`examples > fibonacci.plz --input=2 > stdout 1`] = `
51+
1
52+
53+
`;
54+
55+
exports[`examples > fibonacci.plz > stderr 1`] = `
56+
57+
`;
58+
59+
exports[`examples > fibonacci.plz > stdout 1`] = `
60+
"missing input argument"
61+
62+
`;
63+
64+
exports[`examples > kitchen-sink.plz > stderr 1`] = `
65+
"this goes to stderr"
66+
67+
`;
68+
69+
exports[`examples > kitchen-sink.plz > stdout 1`] = `
70+
{
71+
foo: bar
72+
bar: bar
73+
sky_is_blue: true
74+
colors: {
75+
red
76+
green
77+
blue
78+
}
79+
two: 2
80+
add_one: :integer.add(1)
81+
three: 3
82+
function: x => {
83+
value: :x
84+
}
85+
conditional_value: {
86+
value: 2
87+
}
88+
side_effect: "this goes to stderr"
89+
}
90+
91+
`;
92+
93+
exports[`examples > lookup-environment-variable.plz > stderr 1`] = `
94+
95+
`;
96+
97+
exports[`examples > lookup-environment-variable.plz > stdout 1`] = `
98+
{}
99+
100+
`;

src/examples.test.ts

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
11
import { exec } from 'node:child_process'
22
import { promises as fs } from 'node:fs'
33
import path from 'node:path'
4-
import test, { suite } from 'node:test'
4+
import test, { snapshot, suite } from 'node:test'
5+
6+
// All examples will be tested with no additional command-line arguments. To
7+
// also test with specific sets of arguments, add them here:
8+
const additionalCommandLineArguments: Readonly<
9+
Record<string, readonly string[]>
10+
> = {
11+
'fibonacci.plz': [
12+
'--input=0',
13+
'--input=1',
14+
'--input=2',
15+
'--input=10',
16+
'--input="not a number"',
17+
'--input=-1',
18+
],
19+
}
20+
21+
snapshot.setResolveSnapshotPath(_ =>
22+
path.join(import.meta.dirname, '..', 'examples', '.snapshot'),
23+
)
524

625
const exampleDirectoryPath = path.join(import.meta.dirname, '..', 'examples')
726
const pleasePath = path.join(
@@ -16,24 +35,54 @@ suite('examples', async () => {
1635
fileName => fileName.endsWith('.plz'),
1736
)
1837
for (const exampleFileName of exampleFileNames) {
19-
const exampleFilePath = path.join(exampleDirectoryPath, exampleFileName)
20-
// TODO: Use snapshot testing instead of merely checking for errors.
21-
test(
22-
exampleFileName,
23-
() =>
24-
new Promise((resolve, reject) => {
25-
const _childProcess = exec(
26-
`cat "${exampleFilePath}" | node "${pleasePath}" --output-format=plz`,
27-
(error, _stdout, _stderr) => {
28-
// `error` is an `ExecError` when exit status is nonzero.
29-
if (error !== null) {
30-
reject(error)
31-
} else {
32-
resolve(undefined)
33-
}
34-
},
35-
)
36-
}),
37-
)
38+
const setsOfCommandLineArguments = [
39+
'', // Always test with no arguments.
40+
...(additionalCommandLineArguments[exampleFileName] ?? []),
41+
] as const
42+
43+
for (const commandLineArguments of setsOfCommandLineArguments) {
44+
const exampleFilePath = path.join(exampleDirectoryPath, exampleFileName)
45+
test(
46+
exampleFileName.concat(
47+
commandLineArguments === '' ? '' : ` ${commandLineArguments}`,
48+
),
49+
_ =>
50+
new Promise((resolve, reject) => {
51+
const _childProcess = exec(
52+
`cat "${exampleFilePath}" | node "${pleasePath}" --no-color --output-format=plz ${commandLineArguments}`,
53+
(error, stdout, stderr) => {
54+
// `error` is an `ExecException` when exit status is nonzero.
55+
if (error !== null) {
56+
reject(error)
57+
} else {
58+
Promise.all([
59+
test('stdout', t =>
60+
t.assert.snapshot(stdout, snapshotOptions)),
61+
test('stderr', t =>
62+
t.assert.snapshot(stderr, snapshotOptions)),
63+
])
64+
.then(_ => resolve(undefined))
65+
.catch(reject)
66+
}
67+
},
68+
)
69+
}),
70+
)
71+
}
3872
}
3973
})
74+
75+
// Expect snapshots to already be strings.
76+
const snapshotOptions = {
77+
serializers: [
78+
(value: unknown) => {
79+
if (typeof value !== 'string') {
80+
throw new Error(
81+
`snapshot was not a string (was \`${JSON.stringify(value)}\`)`,
82+
)
83+
} else {
84+
return value
85+
}
86+
},
87+
],
88+
}

0 commit comments

Comments
 (0)