Skip to content

Commit 9a9e90b

Browse files
committed
test: more tests for the server interceptor
1 parent fac977c commit 9a9e90b

File tree

17 files changed

+158
-42
lines changed

17 files changed

+158
-42
lines changed

packages/mocker/src/node/interceptorPlugin.ts

+28-32
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { join } from 'node:path/posix'
2+
import { readFile } from 'node:fs/promises'
23
import type { Plugin } from 'vite'
34
import type { MockedModuleSerialized } from '../registry'
45
import { ManualMockedModule, MockerRegistry } from '../registry'
56
import { cleanUrl } from '../utils'
7+
import { automockModule } from './automockPlugin'
68

79
export interface InterceptorPluginOptions {
810
/**
@@ -36,41 +38,50 @@ export function interceptorPlugin(options: InterceptorPluginOptions): Plugin {
3638
.join('\n')
3739
return `${module}\n${keys}`
3840
}
39-
},
40-
async resolveId(id, importer) {
41-
const resolved = await this.resolve(id, importer)
42-
if (!resolved) {
43-
return
44-
}
45-
const mock = registry.get(resolved.id)
46-
if (!mock) {
47-
return
48-
}
4941
if (mock.type === 'redirect') {
50-
return mock.redirect
51-
}
52-
if (mock.type === 'automock' || mock.type === 'autospy') {
53-
// handled by automockPlugin
54-
return injectQuery(resolved.id, `mock=${mock.type}`)
42+
return readFile(mock.redirect, 'utf-8')
5543
}
5644
},
45+
transform: {
46+
order: 'post',
47+
handler(code, id) {
48+
const mock = registry.get(id)
49+
if (!mock) {
50+
return
51+
}
52+
if (mock.type === 'automock' || mock.type === 'autospy') {
53+
const m = automockModule(code, mock.type, this.parse, {
54+
globalThisAccessor: options.globalThisAccessor,
55+
})
56+
57+
return {
58+
code: m.toString(),
59+
map: m.generateMap({ hires: 'boundary', source: cleanUrl(id) }),
60+
}
61+
}
62+
},
63+
},
5764
configureServer(server) {
5865
server.ws.on('vitest:interceptor:register', (event: MockedModuleSerialized) => {
5966
const serverUrl = event.url
67+
// the browsers stores the url relative to the root
68+
// but on the server "id" operates on the file paths
6069
event.url = join(server.config.root, event.url)
6170
if (event.type === 'manual') {
6271
const module = ManualMockedModule.fromJSON(event, async () => {
6372
const keys = await getFactoryExports(serverUrl)
6473
return Object.fromEntries(keys.map(key => [key, null]))
6574
})
6675
Object.assign(module, {
67-
// the browsers stores the url relative to the root
68-
// but on the server "id" operates on the file paths
6976
serverUrl,
7077
})
7178
registry.add(module)
7279
}
7380
else {
81+
if (event.type === 'redirect') {
82+
const redirectUrl = new URL(event.redirect)
83+
event.redirect = join(server.config.root, redirectUrl.pathname)
84+
}
7485
registry.register(event)
7586
}
7687
server.ws.send('vitest:interceptor:register:result')
@@ -102,18 +113,3 @@ export function interceptorPlugin(options: InterceptorPluginOptions): Plugin {
102113
},
103114
}
104115
}
105-
106-
const replacePercentageRE = /%/g
107-
function injectQuery(url: string, queryToInject: string): string {
108-
// encode percents for consistent behavior with pathToFileURL
109-
// see #2614 for details
110-
const resolvedUrl = new URL(
111-
url.replace(replacePercentageRE, '%25'),
112-
location.href,
113-
)
114-
const { search, hash } = resolvedUrl
115-
const pathname = cleanUrl(url)
116-
return `${pathname}?${queryToInject}${search ? `&${search.slice(1)}` : ''}${
117-
hash ?? ''
118-
}`
119-
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { mocker } from 'virtual:mocker'
2+
import { calculate } from './test'
3+
4+
mocker.customMock(import('./test'), { spy: true })
5+
6+
calculate.mockReturnValue(42)
7+
8+
document.querySelector('#mocked').textContent = calculate(1, 2)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function calculate (a, b) {
2+
return a + b
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Document</title>
7+
</head>
8+
<body>
9+
<script type="module" src="./index.js"></script>
10+
<div id="mocked"></div>
11+
</body>
12+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { mocker } from 'virtual:mocker'
2+
import { calculate } from './test'
3+
4+
mocker.customMock(import('./test'))
5+
6+
document.querySelector('#mocked').textContent = calculate(1, 2)
7+
8+
calculate.mockReturnValue(42)
9+
10+
document.querySelector('#mocked').textContent += `, ${calculate(1, 2)}`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function calculate (a, b) {
2+
return a + b
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Document</title>
7+
</head>
8+
<body>
9+
<script type="module" src="./index.js"></script>
10+
<div id="mocked"></div>
11+
</body>
12+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function calculate() {
2+
return 42
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Document</title>
7+
</head>
8+
<body>
9+
<script type="module" src="./index.js"></script>
10+
<div id="mocked"></div>
11+
</body>
12+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { mocker } from 'virtual:mocker'
2+
import { calculate } from './test'
3+
4+
mocker.customMock(import('./test'))
5+
6+
document.querySelector('#mocked').textContent = calculate(1, 2)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function calculate (a, b) {
2+
return a + b
3+
}

test/public-mocker/test/mocker.test.ts

+52-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,54 @@
11
import { mockerPlugin } from '@vitest/mocker/node'
2+
import type { UserConfig } from 'vite'
23
import { createServer } from 'vite'
3-
import { expect, it, onTestFinished } from 'vitest'
4+
import { beforeAll, expect, it, onTestFinished } from 'vitest'
5+
import type { Browser } from 'playwright'
46
import { chromium } from 'playwright'
57

6-
it('default server mocker works correctly', async () => {
8+
let browser: Browser
9+
beforeAll(async () => {
10+
browser = await chromium.launch()
11+
return async () => {
12+
await browser.close()
13+
browser = null as any
14+
}
15+
})
16+
17+
it('default server manual mocker works correctly', async () => {
18+
const { page } = await createTestServer({
19+
root: 'fixtures/manual-mock',
20+
})
21+
22+
await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('true')
23+
})
24+
25+
it('automock works correctly', async () => {
26+
const { page } = await createTestServer({
27+
root: 'fixtures/automock',
28+
})
29+
30+
await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('42')
31+
})
32+
33+
it('autospy works correctly', async () => {
34+
const { page } = await createTestServer({
35+
root: 'fixtures/autospy',
36+
})
37+
38+
await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('3, 42')
39+
})
40+
41+
it('redirect works correctly', async () => {
42+
const { page } = await createTestServer({
43+
root: 'fixtures/redirect',
44+
})
45+
46+
await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('42')
47+
})
48+
49+
async function createTestServer(config: UserConfig) {
750
const server = await createServer({
8-
root: 'fixtures/custom-mocker',
51+
...config,
952
plugins: [
1053
mockerPlugin({
1154
globalThisAccessor: 'Symbol.for("vitest.mocker")',
@@ -50,14 +93,14 @@ export const mocker = {
5093
onTestFinished(async () => {
5194
await server.close()
5295
})
53-
const browser = await chromium.launch()
5496
const page = await browser.newPage()
55-
await page.goto(server.resolvedUrls!.local[0])
5697
onTestFinished(async () => {
57-
await server.close()
5898
await page.close()
59-
await browser.close()
6099
})
100+
await page.goto(server.resolvedUrls!.local[0])
61101

62-
await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('true')
63-
})
102+
return {
103+
server,
104+
page,
105+
}
106+
}

test/public-mocker/vite.config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { defineConfig } from 'vite'
22
import { mockerPlugin } from '@vitest/mocker/node'
33

44
export default defineConfig({
5-
root: 'fixtures/custom-mocker',
5+
root: 'fixtures/redirect',
66
plugins: [
77
mockerPlugin({
88
globalThisAccessor: 'Symbol.for("vitest.mocker")',

test/public-mocker/vitest.config.ts

+5
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,10 @@ export default defineConfig({
44
test: {
55
isolate: false,
66
environment: 'node',
7+
expect: {
8+
poll: {
9+
timeout: 30_000,
10+
},
11+
},
712
},
813
})

0 commit comments

Comments
 (0)