Skip to content

Commit 00556b2

Browse files
committed
decorateSnapshotUi: get file from stacktrace (#88950)
1 parent 99cd66f commit 00556b2

14 files changed

Lines changed: 240 additions & 168 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@
589589
"base64-js": "^1.3.1",
590590
"base64url": "^3.0.1",
591591
"broadcast-channel": "^3.0.3",
592+
"callsites": "^3.1.0",
592593
"chai": "3.5.0",
593594
"chance": "1.0.18",
594595
"chromedriver": "^87.0.3",

packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.test.ts

Lines changed: 147 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,32 @@ import { decorateSnapshotUi, expectSnapshot } from './decorate_snapshot_ui';
1212
import path from 'path';
1313
import fs from 'fs';
1414

15+
const createMockTest = ({
16+
title = 'Test',
17+
passed = true,
18+
}: { title?: string; passed?: boolean } = {}) => {
19+
return {
20+
fullTitle: () => title,
21+
isPassed: () => passed,
22+
parent: {},
23+
} as Test;
24+
};
25+
1526
describe('decorateSnapshotUi', () => {
27+
const snapshotFolder = path.resolve(__dirname, '__snapshots__');
28+
const snapshotFile = path.resolve(snapshotFolder, 'decorate_snapshot_ui.test.snap');
29+
30+
const cleanup = () => {
31+
if (fs.existsSync(snapshotFile)) {
32+
fs.unlinkSync(snapshotFile);
33+
fs.rmdirSync(snapshotFolder);
34+
}
35+
};
36+
37+
beforeEach(cleanup);
38+
39+
afterAll(cleanup);
40+
1641
describe('when running a test', () => {
1742
let lifecycle: Lifecycle;
1843
beforeEach(() => {
@@ -21,15 +46,7 @@ describe('decorateSnapshotUi', () => {
2146
});
2247

2348
it('passes when the snapshot matches the actual value', async () => {
24-
const test: Test = {
25-
title: 'Test',
26-
file: 'foo.ts',
27-
parent: {
28-
file: 'foo.ts',
29-
tests: [],
30-
suites: [],
31-
},
32-
} as any;
49+
const test = createMockTest();
3350

3451
await lifecycle.beforeEachTest.trigger(test);
3552

@@ -39,15 +56,7 @@ describe('decorateSnapshotUi', () => {
3956
});
4057

4158
it('throws when the snapshot does not match the actual value', async () => {
42-
const test: Test = {
43-
title: 'Test',
44-
file: 'foo.ts',
45-
parent: {
46-
file: 'foo.ts',
47-
tests: [],
48-
suites: [],
49-
},
50-
} as any;
59+
const test = createMockTest();
5160

5261
await lifecycle.beforeEachTest.trigger(test);
5362

@@ -57,27 +66,10 @@ describe('decorateSnapshotUi', () => {
5766
});
5867

5968
it('writes a snapshot to an external file if it does not exist', async () => {
60-
const test: Test = {
61-
title: 'Test',
62-
file: __filename,
63-
isPassed: () => true,
64-
} as any;
65-
66-
// @ts-expect-error
67-
test.parent = {
68-
file: __filename,
69-
tests: [test],
70-
suites: [],
71-
};
69+
const test: Test = createMockTest();
7270

7371
await lifecycle.beforeEachTest.trigger(test);
7472

75-
const snapshotFile = path.resolve(
76-
__dirname,
77-
'__snapshots__',
78-
'decorate_snapshot_ui.test.snap'
79-
);
80-
8173
expect(fs.existsSync(snapshotFile)).toBe(false);
8274

8375
expect(() => {
@@ -87,10 +79,48 @@ describe('decorateSnapshotUi', () => {
8779
await lifecycle.afterTestSuite.trigger(test.parent);
8880

8981
expect(fs.existsSync(snapshotFile)).toBe(true);
82+
});
83+
});
9084

91-
fs.unlinkSync(snapshotFile);
85+
describe('when writing multiple snapshots to a single file', () => {
86+
let lifecycle: Lifecycle;
87+
beforeEach(() => {
88+
lifecycle = new Lifecycle();
89+
decorateSnapshotUi({ lifecycle, updateSnapshots: false, isCi: false });
90+
});
91+
92+
beforeEach(() => {
93+
fs.mkdirSync(path.resolve(__dirname, '__snapshots__'));
94+
fs.writeFileSync(
95+
snapshotFile,
96+
`// Jest Snapshot v1, https://goo.gl/fbAQLP
97+
98+
exports[\`Test1 1\`] = \`"foo"\`;
99+
100+
exports[\`Test2 1\`] = \`"bar"\`;
101+
`,
102+
{ encoding: 'utf-8' }
103+
);
104+
});
105+
106+
it('compares to an existing snapshot', async () => {
107+
const test1 = createMockTest({ title: 'Test1' });
108+
109+
await lifecycle.beforeEachTest.trigger(test1);
110+
111+
expect(() => {
112+
expectSnapshot('foo').toMatch();
113+
}).not.toThrow();
114+
115+
const test2 = createMockTest({ title: 'Test2' });
92116

93-
fs.rmdirSync(path.resolve(__dirname, '__snapshots__'));
117+
await lifecycle.beforeEachTest.trigger(test2);
118+
119+
expect(() => {
120+
expectSnapshot('foo').toMatch();
121+
}).toThrow();
122+
123+
await lifecycle.afterTestSuite.trigger(test1.parent);
94124
});
95125
});
96126

@@ -102,15 +132,7 @@ describe('decorateSnapshotUi', () => {
102132
});
103133

104134
it("doesn't throw if the value does not match", async () => {
105-
const test: Test = {
106-
title: 'Test',
107-
file: 'foo.ts',
108-
parent: {
109-
file: 'foo.ts',
110-
tests: [],
111-
suites: [],
112-
},
113-
} as any;
135+
const test = createMockTest();
114136

115137
await lifecycle.beforeEachTest.trigger(test);
116138

@@ -128,21 +150,90 @@ describe('decorateSnapshotUi', () => {
128150
});
129151

130152
it('throws on new snapshots', async () => {
131-
const test: Test = {
132-
title: 'Test',
133-
file: 'foo.ts',
134-
parent: {
135-
file: 'foo.ts',
136-
tests: [],
137-
suites: [],
138-
},
139-
} as any;
153+
const test = createMockTest();
140154

141155
await lifecycle.beforeEachTest.trigger(test);
142156

143157
expect(() => {
144158
expectSnapshot('bar').toMatchInline();
145159
}).toThrow();
146160
});
161+
162+
describe('when adding to an existing file', () => {
163+
beforeEach(() => {
164+
fs.mkdirSync(path.resolve(__dirname, '__snapshots__'));
165+
fs.writeFileSync(
166+
snapshotFile,
167+
`// Jest Snapshot v1, https://goo.gl/fbAQLP
168+
169+
exports[\`Test 1\`] = \`"foo"\`;
170+
171+
exports[\`Test2 1\`] = \`"bar"\`;
172+
`,
173+
{ encoding: 'utf-8' }
174+
);
175+
});
176+
177+
it('does not throw on an existing test', async () => {
178+
const test = createMockTest({ title: 'Test' });
179+
180+
await lifecycle.beforeEachTest.trigger(test);
181+
182+
expect(() => {
183+
expectSnapshot('foo').toMatch();
184+
}).not.toThrow();
185+
});
186+
187+
it('throws on a new test', async () => {
188+
const test = createMockTest({ title: 'New test' });
189+
190+
await lifecycle.beforeEachTest.trigger(test);
191+
192+
expect(() => {
193+
expectSnapshot('foo').toMatch();
194+
}).toThrow();
195+
});
196+
197+
it('does not throw when all snapshots are used ', async () => {
198+
const test = createMockTest({ title: 'Test' });
199+
200+
await lifecycle.beforeEachTest.trigger(test);
201+
202+
expect(() => {
203+
expectSnapshot('foo').toMatch();
204+
}).not.toThrow();
205+
206+
const test2 = createMockTest({ title: 'Test2' });
207+
208+
await lifecycle.beforeEachTest.trigger(test2);
209+
210+
expect(() => {
211+
expectSnapshot('bar').toMatch();
212+
}).not.toThrow();
213+
214+
const afterTestSuite = lifecycle.afterTestSuite.trigger({});
215+
216+
await expect(afterTestSuite).resolves.toBe(undefined);
217+
});
218+
219+
it('throws on unused snapshots', async () => {
220+
const test = createMockTest({ title: 'Test' });
221+
222+
await lifecycle.beforeEachTest.trigger(test);
223+
224+
expect(() => {
225+
expectSnapshot('foo').toMatch();
226+
}).not.toThrow();
227+
228+
const afterTestSuite = lifecycle.afterTestSuite.trigger({});
229+
230+
await expect(afterTestSuite).rejects.toMatchInlineSnapshot(`
231+
[Error: 1 obsolete snapshot(s) found:
232+
Test2 1.
233+
234+
Run tests again with \`--updateSnapshots\` to remove them.]
235+
`);
236+
});
237+
});
147238
});
148239
});

0 commit comments

Comments
 (0)