Skip to content

Commit f131f93

Browse files
authoredSep 25, 2024··
fix(browser): fix browser mock factory event race condition (#6530)
1 parent b553c7d commit f131f93

File tree

10 files changed

+49
-20
lines changed

10 files changed

+49
-20
lines changed
 

‎packages/browser/src/client/channel.ts

+3
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,19 @@ export interface IframeMockingDoneEvent {
3939

4040
export interface IframeMockFactoryRequestEvent {
4141
type: 'mock-factory:request'
42+
eventId: string
4243
id: string
4344
}
4445

4546
export interface IframeMockFactoryResponseEvent {
4647
type: 'mock-factory:response'
48+
eventId: string
4749
exports: string[]
4850
}
4951

5052
export interface IframeMockFactoryErrorEvent {
5153
type: 'mock-factory:error'
54+
eventId: string
5255
error: any
5356
}
5457

‎packages/browser/src/client/tester/mocker.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { IframeChannelOutgoingEvent } from '@vitest/browser/client'
1+
import type { IframeChannelOutgoingEvent, IframeMockFactoryErrorEvent, IframeMockFactoryResponseEvent } from '@vitest/browser/client'
22
import { channel } from '@vitest/browser/client'
33
import { ModuleMocker } from '@vitest/mocker/browser'
44
import { getBrowserState } from '../utils'
@@ -14,18 +14,20 @@ export class VitestBrowserClientMocker extends ModuleMocker {
1414
const exports = Object.keys(module)
1515
channel.postMessage({
1616
type: 'mock-factory:response',
17+
eventId: e.data.eventId,
1718
exports,
18-
})
19+
} satisfies IframeMockFactoryResponseEvent)
1920
}
2021
catch (err: any) {
2122
channel.postMessage({
2223
type: 'mock-factory:error',
24+
eventId: e.data.eventId,
2325
error: {
2426
name: err.name,
2527
message: err.message,
2628
stack: err.stack,
2729
},
28-
})
30+
} satisfies IframeMockFactoryErrorEvent)
2931
}
3032
}
3133
},

‎packages/browser/src/client/tester/msw.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { channel } from '@vitest/browser/client'
22
import type {
33
IframeChannelEvent,
4+
IframeMockFactoryRequestEvent,
45
IframeMockingDoneEvent,
56
} from '@vitest/browser/client'
67
import type { MockedModuleSerialized } from '@vitest/mocker'
78
import { ManualMockedModule } from '@vitest/mocker'
89
import { ModuleMockerMSWInterceptor } from '@vitest/mocker/browser'
10+
import { nanoid } from '@vitest/utils'
911

1012
export class VitestBrowserModuleMockerInterceptor extends ModuleMockerMSWInterceptor {
1113
override async register(event: MockedModuleSerialized): Promise<void> {
@@ -42,19 +44,21 @@ export function createModuleMockerInterceptor() {
4244
}
4345

4446
function getFactoryExports(id: string) {
47+
const eventId = nanoid()
4548
channel.postMessage({
4649
type: 'mock-factory:request',
50+
eventId,
4751
id,
48-
})
52+
} satisfies IframeMockFactoryRequestEvent)
4953
return new Promise<string[]>((resolve, reject) => {
5054
channel.addEventListener(
5155
'message',
5256
function onMessage(e: MessageEvent<IframeChannelEvent>) {
53-
if (e.data.type === 'mock-factory:response') {
57+
if (e.data.type === 'mock-factory:response' && e.data.eventId === eventId) {
5458
resolve(e.data.exports)
5559
channel.removeEventListener('message', onMessage)
5660
}
57-
if (e.data.type === 'mock-factory:error') {
61+
if (e.data.type === 'mock-factory:error' && e.data.eventId === eventId) {
5862
reject(e.data.error)
5963
channel.removeEventListener('message', onMessage)
6064
}

‎packages/utils/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,5 @@ export type {
5151
SerializedError,
5252
TestError,
5353
} from './types'
54+
55+
export { nanoid } from './nanoid'

‎packages/utils/src/nanoid.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// port from nanoid
2+
// https://github.com/ai/nanoid
3+
const urlAlphabet
4+
= 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
5+
export function nanoid(size = 21): string {
6+
let id = ''
7+
let i = size
8+
while (i--) {
9+
id += urlAlphabet[(Math.random() * 64) | 0]
10+
}
11+
return id
12+
}

‎packages/vitest/src/utils/base.ts

+1-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Arrayable, Nullable } from '../types/general'
22

3-
export { notNullish, getCallLastIndex } from '@vitest/utils'
3+
export { notNullish, getCallLastIndex, nanoid } from '@vitest/utils'
44

55
export interface GlobalConstructors {
66
Object: ObjectConstructor
@@ -203,16 +203,3 @@ export function wildcardPatternToRegExp(pattern: string): RegExp {
203203
'i',
204204
)
205205
}
206-
207-
// port from nanoid
208-
// https://github.com/ai/nanoid
209-
const urlAlphabet
210-
= 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
211-
export function nanoid(size = 21) {
212-
let id = ''
213-
let i = size
214-
while (i--) {
215-
id += urlAlphabet[(Math.random() * 64) | 0]
216-
}
217-
return id
218-
}

‎test/browser/fixtures/mocking/mocked-factory.test.ts

+13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { expect, test, vi } from 'vitest'
22
import { calculator, mocked } from './src/mocks_factory'
3+
import factoryMany from './src/mocks_factory_many'
34

45
vi.mock(import('./src/mocks_factory'), () => {
56
return {
@@ -8,7 +9,19 @@ vi.mock(import('./src/mocks_factory'), () => {
89
}
910
})
1011

12+
vi.mock(import('./src/mocks_factory_many_dep1'), () => ({
13+
dep1: "dep1-mocked"
14+
}))
15+
vi.mock(import('./src/mocks_factory_many_dep2'), () => ({
16+
dep2: "dep2-mocked"
17+
}))
18+
1119
test('adds', () => {
1220
expect(mocked).toBe(true)
1321
expect(calculator('plus', 1, 2)).toBe(1166)
22+
23+
expect(factoryMany).toEqual({
24+
"dep1": "dep1-mocked",
25+
"dep2": "dep2-mocked",
26+
})
1427
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { dep1 } from "./mocks_factory_many_dep1";
2+
import { dep2 } from "./mocks_factory_many_dep2";
3+
4+
export default { dep1, dep2 }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const dep1: string = "dep1"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const dep2: string = "dep2"

0 commit comments

Comments
 (0)
Please sign in to comment.