Skip to content

Commit f44cc91

Browse files
authored
fix(browser): allow immidiate reinvalidation of mocked dependencies (#6108)
1 parent 840e02f commit f44cc91

File tree

11 files changed

+99
-4
lines changed

11 files changed

+99
-4
lines changed

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

+18
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ export function createModuleMocker() {
2727
http.get(/.+/, async ({ request }) => {
2828
const path = cleanQuery(request.url.slice(location.origin.length))
2929
if (!mocks.has(path)) {
30+
if (path.includes('/deps/')) {
31+
return fetch(bypass(request))
32+
}
33+
3034
return passthrough()
3135
}
3236

@@ -128,6 +132,20 @@ function passthrough() {
128132
})
129133
}
130134

135+
function bypass(request: Request) {
136+
const clonedRequest = request.clone()
137+
clonedRequest.headers.set('x-msw-intention', 'bypass')
138+
const cacheControl = clonedRequest.headers.get('cache-control')
139+
if (cacheControl) {
140+
clonedRequest.headers.set(
141+
'cache-control',
142+
// allow reinvalidation of the cache so mocks can be updated
143+
cacheControl.replace(', immutable', ''),
144+
)
145+
}
146+
return clonedRequest
147+
}
148+
131149
const postfixRE = /[?#].*$/
132150
function cleanUrl(url: string): string {
133151
return url.replace(postfixRE, '')

packages/browser/src/node/plugin.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default (browserServer: BrowserServer, base = '/'): Plugin[] => {
4141
})
4242
// eslint-disable-next-line prefer-arrow-callback
4343
server.middlewares.use(async function vitestBrowserMode(req, res, next) {
44-
if (!req.url) {
44+
if (!req.url || !browserServer.provider) {
4545
return next()
4646
}
4747
const url = new URL(req.url, 'http://localhost')

test/browser/cjs-lib/lib.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export function lib(): string

test/browser/cjs-lib/lib.mjs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function lib() {
2+
return 'original'
3+
}

test/browser/cjs-lib/package.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
"name": "@vitest/cjs-lib",
33
"type": "commonjs",
44
"exports": {
5-
"default": "./index.js"
5+
"./lib": {
6+
"types": "./lib.d.ts",
7+
"default": "./lib.mjs"
8+
},
9+
".": "./index.js"
610
}
711
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { lib } from '@vitest/cjs-lib/lib'
2+
import { vi, test, expect } from 'vitest'
3+
4+
vi.mock(import('@vitest/cjs-lib/lib'), () => {
5+
return {
6+
lib: vi.fn(() => 'mocked')
7+
}
8+
})
9+
10+
test('mocks correctly', () => {
11+
expect(lib()).toBe('mocked')
12+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { lib } from '@vitest/cjs-lib/lib'
2+
import { test, expect } from 'vitest'
3+
4+
test('not mocked', () => {
5+
expect(lib()).toBe('original')
6+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { fileURLToPath } from 'node:url'
2+
import { defineConfig } from 'vitest/config'
3+
4+
const provider = process.env.PROVIDER || 'playwright'
5+
const name =
6+
process.env.BROWSER || (provider === 'playwright' ? 'chromium' : 'chrome')
7+
8+
export default defineConfig({
9+
optimizeDeps: {
10+
include: ['@vitest/cjs-lib', '@vitest/cjs-lib/lib'],
11+
},
12+
cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)),
13+
test: {
14+
browser: {
15+
fileParallelism: false,
16+
enabled: true,
17+
provider,
18+
name,
19+
headless: true,
20+
},
21+
},
22+
})

test/browser/fixtures/mocking/vitest.config.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { fileURLToPath } from 'node:url'
12
import { defineConfig } from 'vitest/config'
23

34
const provider = process.env.PROVIDER || 'playwright'
@@ -9,6 +10,7 @@ export default defineConfig({
910
include: ['@vitest/cjs-lib'],
1011
needsInterop: ['@vitest/cjs-lib'],
1112
},
13+
cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)),
1214
test: {
1315
browser: {
1416
enabled: true,

test/browser/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"test:safaridriver": "PROVIDER=webdriverio BROWSER=safari pnpm run test:unit",
1111
"test-fixtures": "vitest",
1212
"test-mocking": "vitest --root ./fixtures/mocking",
13+
"test-mocking-watch": "vitest --root ./fixtures/mocking-watch",
1314
"test-snapshots": "vitest --root ./fixtures/update-snapshot",
1415
"coverage": "vitest --coverage.enabled --coverage.provider=istanbul --browser.headless=yes",
1516
"test:browser:preview": "PROVIDER=preview vitest",

test/browser/specs/mocking.test.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { expect, onTestFailed, test } from 'vitest'
2-
import { runVitest } from '../../test-utils'
1+
import { expect, onTestFailed, onTestFinished, test } from 'vitest'
2+
import { editFile, runVitest } from '../../test-utils'
33

44
test.each([true, false])('mocking works correctly - isolated %s', async (isolate) => {
55
const result = await runVitest({
@@ -26,3 +26,29 @@ test.each([true, false])('mocking works correctly - isolated %s', async (isolate
2626
expect(result.stdout).toContain('mocked-do-mock-factory.test.ts')
2727
expect(result.exitCode).toBe(0)
2828
})
29+
30+
test('mocking dependency correctly invalidates it on rerun', async () => {
31+
const { vitest, ctx } = await runVitest({
32+
root: 'fixtures/mocking-watch',
33+
watch: true,
34+
})
35+
onTestFinished(async () => {
36+
await ctx.close()
37+
await ctx.closingPromise
38+
})
39+
40+
await vitest.waitForStdout('Waiting for file changes...')
41+
42+
expect(vitest.stderr).toBe('')
43+
expect(vitest.stdout).toContain('1_mocked-on-watch-change.test.ts')
44+
expect(vitest.stdout).toContain('2_not-mocked-import.test.ts')
45+
46+
vitest.resetOutput()
47+
editFile('./fixtures/mocking-watch/1_mocked-on-watch-change.test.ts', content => `${content}\n`)
48+
49+
await vitest.waitForStdout('Waiting for file changes...')
50+
51+
expect(vitest.stderr).toBe('')
52+
expect(vitest.stdout).toContain('1_mocked-on-watch-change.test.ts')
53+
expect(vitest.stdout).not.toContain('2_not-mocked-import.test.ts')
54+
})

0 commit comments

Comments
 (0)