Skip to content

Commit e8ce94c

Browse files
authored
fix(snapshot)!: reset snapshot state for retry and repeats (#6817)
1 parent db7a888 commit e8ce94c

31 files changed

+554
-145
lines changed

packages/snapshot/src/client.ts

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@ export interface Context {
3434

3535
interface AssertOptions {
3636
received: unknown
37-
filepath?: string
38-
name?: string
37+
filepath: string
38+
name: string
39+
/**
40+
* Not required but needed for `SnapshotClient.clearTest` to implement test-retry behavior.
41+
* @default name
42+
*/
43+
testId?: string
3944
message?: string
4045
isInline?: boolean
4146
properties?: object
@@ -50,51 +55,55 @@ export interface SnapshotClientOptions {
5055
}
5156

5257
export class SnapshotClient {
53-
filepath?: string
54-
name?: string
55-
snapshotState: SnapshotState | undefined
5658
snapshotStateMap: Map<string, SnapshotState> = new Map()
5759

5860
constructor(private options: SnapshotClientOptions = {}) {}
5961

60-
async startCurrentRun(
62+
async setup(
6163
filepath: string,
62-
name: string,
6364
options: SnapshotStateOptions,
6465
): Promise<void> {
65-
this.filepath = filepath
66-
this.name = name
67-
68-
if (this.snapshotState?.testFilePath !== filepath) {
69-
await this.finishCurrentRun()
70-
71-
if (!this.getSnapshotState(filepath)) {
72-
this.snapshotStateMap.set(
73-
filepath,
74-
await SnapshotState.create(filepath, options),
75-
)
76-
}
77-
this.snapshotState = this.getSnapshotState(filepath)
66+
if (this.snapshotStateMap.has(filepath)) {
67+
return
7868
}
69+
this.snapshotStateMap.set(
70+
filepath,
71+
await SnapshotState.create(filepath, options),
72+
)
7973
}
8074

81-
getSnapshotState(filepath: string): SnapshotState {
82-
return this.snapshotStateMap.get(filepath)!
75+
async finish(filepath: string): Promise<SnapshotResult> {
76+
const state = this.getSnapshotState(filepath)
77+
const result = await state.pack()
78+
this.snapshotStateMap.delete(filepath)
79+
return result
80+
}
81+
82+
skipTest(filepath: string, testName: string): void {
83+
const state = this.getSnapshotState(filepath)
84+
state.markSnapshotsAsCheckedForTest(testName)
8385
}
8486

85-
clearTest(): void {
86-
this.filepath = undefined
87-
this.name = undefined
87+
clearTest(filepath: string, testId: string): void {
88+
const state = this.getSnapshotState(filepath)
89+
state.clearTest(testId)
8890
}
8991

90-
skipTestSnapshots(name: string): void {
91-
this.snapshotState?.markSnapshotsAsCheckedForTest(name)
92+
getSnapshotState(filepath: string): SnapshotState {
93+
const state = this.snapshotStateMap.get(filepath)
94+
if (!state) {
95+
throw new Error(
96+
`The snapshot state for '${filepath}' is not found. Did you call 'SnapshotClient.setup()'?`,
97+
)
98+
}
99+
return state
92100
}
93101

94102
assert(options: AssertOptions): void {
95103
const {
96-
filepath = this.filepath,
97-
name = this.name,
104+
filepath,
105+
name,
106+
testId = name,
98107
message,
99108
isInline = false,
100109
properties,
@@ -109,6 +118,8 @@ export class SnapshotClient {
109118
throw new Error('Snapshot cannot be used outside of test')
110119
}
111120

121+
const snapshotState = this.getSnapshotState(filepath)
122+
112123
if (typeof properties === 'object') {
113124
if (typeof received !== 'object' || !received) {
114125
throw new Error(
@@ -122,7 +133,7 @@ export class SnapshotClient {
122133
if (!pass) {
123134
throw createMismatchError(
124135
'Snapshot properties mismatched',
125-
this.snapshotState?.expand,
136+
snapshotState.expand,
126137
received,
127138
properties,
128139
)
@@ -139,9 +150,8 @@ export class SnapshotClient {
139150

140151
const testName = [name, ...(message ? [message] : [])].join(' > ')
141152

142-
const snapshotState = this.getSnapshotState(filepath)
143-
144153
const { actual, expected, key, pass } = snapshotState.match({
154+
testId,
145155
testName,
146156
received,
147157
isInline,
@@ -153,7 +163,7 @@ export class SnapshotClient {
153163
if (!pass) {
154164
throw createMismatchError(
155165
`Snapshot \`${key || 'unknown'}\` mismatched`,
156-
this.snapshotState?.expand,
166+
snapshotState.expand,
157167
actual?.trim(),
158168
expected?.trim(),
159169
)
@@ -165,7 +175,7 @@ export class SnapshotClient {
165175
throw new Error('Raw snapshot is required')
166176
}
167177

168-
const { filepath = this.filepath, rawSnapshot } = options
178+
const { filepath, rawSnapshot } = options
169179

170180
if (rawSnapshot.content == null) {
171181
if (!filepath) {
@@ -189,16 +199,6 @@ export class SnapshotClient {
189199
return this.assert(options)
190200
}
191201

192-
async finishCurrentRun(): Promise<SnapshotResult | null> {
193-
if (!this.snapshotState) {
194-
return null
195-
}
196-
const result = await this.snapshotState.pack()
197-
198-
this.snapshotState = undefined
199-
return result
200-
}
201-
202202
clear(): void {
203203
this.snapshotStateMap.clear()
204204
}

packages/snapshot/src/port/inlineSnapshot.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99

1010
export interface InlineSnapshot {
1111
snapshot: string
12+
testId: string
1213
file: string
1314
line: number
1415
column: number

0 commit comments

Comments
 (0)