Skip to content

Commit

Permalink
test: more tests for the server interceptor
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Aug 19, 2024
1 parent 2d5b629 commit 81ce390
Show file tree
Hide file tree
Showing 17 changed files with 158 additions and 42 deletions.
60 changes: 28 additions & 32 deletions packages/mocker/src/node/interceptorPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { join } from 'node:path/posix'
import { readFile } from 'node:fs/promises'
import type { Plugin } from 'vite'
import type { MockedModuleSerialized } from '../registry'
import { ManualMockedModule, MockerRegistry } from '../registry'
import { cleanUrl } from '../utils'
import { automockModule } from './automockPlugin'

export interface InterceptorPluginOptions {
/**
Expand Down Expand Up @@ -36,41 +38,50 @@ export function interceptorPlugin(options: InterceptorPluginOptions): Plugin {
.join('\n')
return `${module}\n${keys}`
}
},
async resolveId(id, importer) {
const resolved = await this.resolve(id, importer)
if (!resolved) {
return
}
const mock = registry.get(resolved.id)
if (!mock) {
return
}
if (mock.type === 'redirect') {
return mock.redirect
}
if (mock.type === 'automock' || mock.type === 'autospy') {
// handled by automockPlugin
return injectQuery(resolved.id, `mock=${mock.type}`)
return readFile(mock.redirect, 'utf-8')
}
},
transform: {
order: 'post',
handler(code, id) {
const mock = registry.get(id)
if (!mock) {
return
}
if (mock.type === 'automock' || mock.type === 'autospy') {
const m = automockModule(code, mock.type, this.parse, {
globalThisAccessor: options.globalThisAccessor,
})

return {
code: m.toString(),
map: m.generateMap({ hires: 'boundary', source: cleanUrl(id) }),
}
}
},
},
configureServer(server) {
server.ws.on('vitest:interceptor:register', (event: MockedModuleSerialized) => {
const serverUrl = event.url
// the browsers stores the url relative to the root
// but on the server "id" operates on the file paths
event.url = join(server.config.root, event.url)
if (event.type === 'manual') {
const module = ManualMockedModule.fromJSON(event, async () => {
const keys = await getFactoryExports(serverUrl)
return Object.fromEntries(keys.map(key => [key, null]))
})
Object.assign(module, {
// the browsers stores the url relative to the root
// but on the server "id" operates on the file paths
serverUrl,
})
registry.add(module)
}
else {
if (event.type === 'redirect') {
const redirectUrl = new URL(event.redirect)
event.redirect = join(server.config.root, redirectUrl.pathname)
}
registry.register(event)
}
server.ws.send('vitest:interceptor:register:result')
Expand Down Expand Up @@ -102,18 +113,3 @@ export function interceptorPlugin(options: InterceptorPluginOptions): Plugin {
},
}
}

const replacePercentageRE = /%/g
function injectQuery(url: string, queryToInject: string): string {
// encode percents for consistent behavior with pathToFileURL
// see #2614 for details
const resolvedUrl = new URL(
url.replace(replacePercentageRE, '%25'),
location.href,
)
const { search, hash } = resolvedUrl
const pathname = cleanUrl(url)
return `${pathname}?${queryToInject}${search ? `&${search.slice(1)}` : ''}${
hash ?? ''
}`
}
8 changes: 8 additions & 0 deletions test/public-mocker/fixtures/automock/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { mocker } from 'virtual:mocker'
import { calculate } from './test'

mocker.customMock(import('./test'), { spy: true })

calculate.mockReturnValue(42)

document.querySelector('#mocked').textContent = calculate(1, 2)
3 changes: 3 additions & 0 deletions test/public-mocker/fixtures/automock/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function calculate (a, b) {
return a + b
}
12 changes: 12 additions & 0 deletions test/public-mocker/fixtures/autospy/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="module" src="./index.js"></script>
<div id="mocked"></div>
</body>
</html>
10 changes: 10 additions & 0 deletions test/public-mocker/fixtures/autospy/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { mocker } from 'virtual:mocker'
import { calculate } from './test'

mocker.customMock(import('./test'))

document.querySelector('#mocked').textContent = calculate(1, 2)

calculate.mockReturnValue(42)

document.querySelector('#mocked').textContent += `, ${calculate(1, 2)}`
3 changes: 3 additions & 0 deletions test/public-mocker/fixtures/autospy/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function calculate (a, b) {
return a + b
}
12 changes: 12 additions & 0 deletions test/public-mocker/fixtures/manual-mock/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="module" src="./index.js"></script>
<div id="mocked"></div>
</body>
</html>
3 changes: 3 additions & 0 deletions test/public-mocker/fixtures/redirect/__mocks__/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function calculate() {
return 42
}
12 changes: 12 additions & 0 deletions test/public-mocker/fixtures/redirect/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="module" src="./index.js"></script>
<div id="mocked"></div>
</body>
</html>
6 changes: 6 additions & 0 deletions test/public-mocker/fixtures/redirect/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { mocker } from 'virtual:mocker'
import { calculate } from './test'

mocker.customMock(import('./test'))

document.querySelector('#mocked').textContent = calculate(1, 2)
3 changes: 3 additions & 0 deletions test/public-mocker/fixtures/redirect/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function calculate (a, b) {
return a + b
}
61 changes: 52 additions & 9 deletions test/public-mocker/test/mocker.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,54 @@
import { mockerPlugin } from '@vitest/mocker/node'
import type { UserConfig } from 'vite'
import { createServer } from 'vite'
import { expect, it, onTestFinished } from 'vitest'
import { beforeAll, expect, it, onTestFinished } from 'vitest'
import type { Browser } from 'playwright'
import { chromium } from 'playwright'

it('default server mocker works correctly', async () => {
let browser: Browser
beforeAll(async () => {
browser = await chromium.launch()
return async () => {
await browser.close()
browser = null as any
}
})

it('default server manual mocker works correctly', async () => {
const { page } = await createTestServer({
root: 'fixtures/manual-mock',
})

await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('true')
})

it('automock works correctly', async () => {
const { page } = await createTestServer({
root: 'fixtures/automock',
})

await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('42')
})

it('autospy works correctly', async () => {
const { page } = await createTestServer({
root: 'fixtures/autospy',
})

await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('3, 42')
})

it('redirect works correctly', async () => {
const { page } = await createTestServer({
root: 'fixtures/redirect',
})

await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('42')
})

async function createTestServer(config: UserConfig) {
const server = await createServer({
root: 'fixtures/custom-mocker',
...config,
plugins: [
mockerPlugin({
globalThisAccessor: 'Symbol.for("vitest.mocker")',
Expand Down Expand Up @@ -50,14 +93,14 @@ export const mocker = {
onTestFinished(async () => {
await server.close()
})
const browser = await chromium.launch()
const page = await browser.newPage()
await page.goto(server.resolvedUrls!.local[0])
onTestFinished(async () => {
await server.close()
await page.close()
await browser.close()
})
await page.goto(server.resolvedUrls!.local[0])

await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('true')
})
return {
server,
page,
}
}
2 changes: 1 addition & 1 deletion test/public-mocker/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineConfig } from 'vite'
import { mockerPlugin } from '@vitest/mocker/node'

export default defineConfig({
root: 'fixtures/custom-mocker',
root: 'fixtures/redirect',
plugins: [
mockerPlugin({
globalThisAccessor: 'Symbol.for("vitest.mocker")',
Expand Down
5 changes: 5 additions & 0 deletions test/public-mocker/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@ export default defineConfig({
test: {
isolate: false,
environment: 'node',
expect: {
poll: {
timeout: 30_000,
},
},
},
})

0 comments on commit 81ce390

Please sign in to comment.