nuxt- msw (正数)
nuxt-msw 整合 MSW (移动服务工人) 输入 Nuxt 工程, 允许您在开发时用于 API 模拟 。 大部分代码可以直接与测试模拟共享.
特征
- QQ 写一次, 随处使用
- QQ 在 Nuxt 开发中使用 MSW 强大的嘲弄功能
- QQ 截取服务器端和客户端请求, 包括
$fetch, (中文(简体) ),useFetch和任何其他的api请求. - 支持 Nuxt 层 .
在线游戏场
您可以试探 nuxt-msw 通过下列网站进行在线访问.
迁移 : 0.x - > (中文) 1.x 用户
感谢0.x版的所有用户. 我认为你不需要付出太多努力.
0.x和1.x之间的差别如下:
optionPath内nuxt.config已改为folderPath。它最初指向一个文件,但现在指向一个文件夹.- 你需要手动输入MSW的工人文件.
nuxt-msw不再自动提供工人文件. - 工人和服务器的设置先前是在同一文件中被写入的. 为了更好地利用它们运行的环境,工人和服务器现在将分开运行。 请参阅以下说明.
- 增加了对 Nuxt 环境中单位测试的支持 .
- 添加了 Nuxt 层的支持 .
如果您现在不想升级到1.x, 您可以在这里找到 0.x doc : 0.2.x 医生
设置
要将模块安装到您的 Nuxt 应用程序 :
npm install @crazydos/nuxt-msw msw --save-dev
export default defineNuxtConfig({
modules: ['@crazydos/nuxt-msw'],
msw : {
// Options, see below
}
})
使用量
你需要分别设置MSW工人和服务器. 当其中之一被设置, 一方将开始运行.
设置位置在 ~/msw 目录(默认情况下),您通过相应的文件配置它.
劳动者
要建立工人,你需要跟随 MSW 文档 创建工人档案.
# For example
npx msw init public --save
接下来,您需要创建 worker.{ts|js|mjs|cjs} 文档中 ~/msw 目录。 工人文件将在浏览器上下文的 Nuxt 客户端插件中运行 。 表示您可以在此文件中使用浏览器 api 和 Nuxt 可相容 .
// ~/msw/worker.ts
import { http, HttpResponse } from 'msw'
export default defineNuxtMswWorkerOption(() => {
const handlers = [
// Intercept "GET /api/user" requests...
http.get('/api/user', () => {
// ...and respond to them using this JSON response.
return HttpResponse.json({
message: "Hello Worker!",
})
}),
]
// You can access any browser api
// window.location.href
return {
handlers,
workerOptions: {
// ...you can pass options to worker.start()
// onUnhandledRequest: 'bypass',
},
onWorkerStarted(worker, nuxtApp) {
// Module will setup worker when nuxt run client plugin
// Means this function will be called after plugin call worker.start()
nuxtApp.hook('app:mounted', () => {
// const route = useRoute()
// console.log(worker.listHandlers())
})
},
}
})
你可以尝试从工人那里获取数据.
<script setup>
onMounted(async () => {
const res = await $fetch("/api/user")
console.log(res) // { message: "Hello Worker!" }
})
</script>
服务器
服务器的设置方式与工人类似. 你需要创建一个 server.{ts|js|mjs|cjs} 文档中 ~/msw 目录.
服务器文件将在 Node.js 运行 Nitro 上下文。 由于它是在 NuxtApp 创建之前, 你不能访问 NuxtApp 和 composition哪一个访问它。 但是您可以访问 msw 服务器并请求 (h3Event).
更重要的是,对于你的模拟和硝基服务器处理器的正常工作,你需要设置 baseURL 在服务器选项中。 BaseURL 必须与您的服务器监听地址相同 .
并且,在嘲笑服务器侧请求时,需要将baseURL包含在您的处理器路径中.
// ~/msw/server.ts
import { http, HttpResponse } from 'msw'
export default defineNuxtMswServerOption(() => {
// assume your server listening at http://localhost:3000
const baseURL = "http://localhost:3000"
// composables that not related to NuxtApp can be used here, like: useRuntimeConfig
const handlers = [
// Intercept "GET http://localhost:3000/user" requests...
http.get(baseURL + '/api/user', () => {
// ...and respond to them using this JSON response.
return HttpResponse.json({
message: "Hello msw server!"
})
}),
]
return {
baseURL, // baseURL is required
handlers,
serverOptions: {
onUnhandledRequest: 'bypass',
},
onRequest(mswServer, h3Event) {
// This funtion will be call when Nitro server "request" hook
console.log('Hello from onRequest')
mswServer.use(/*...*/)
},
}
})
在设置服务器后, 您可以尝试从服务器取取数据 .
<template>
<h1>{{ data?.message }}</h1>
<!-- Hello msw server! -->
</template>
<script setup>
const { data, error } = await useFetch('/api/user')
</script>
这个 h3Event 掌握有关请求的一些基本信息,例如: event.path。如果需要更多,可以明确安装 h3,然后用它来获取更多.
import { getQuery } from 'h3'
// ...
{
// ....
onRequest(mswServer, h3Event) {
const query = useQuery(h3Event)
// do something with query
}
}
模块选项
选择的用法如下.
[注]
必须理解这些选项是构建时间配置。 因此,如果你使用环境变量像.env要决定这些选项, 您需要设置.env时间nuxi build我也一样.
export default defineNuxtConfig({
modules: ['@crazydos/nuxt-msw'],
msw: {
/**
* Whether to enable the module. Default to `true`
*
* This is useful when you need to enable or disable msw based on the environment.
*
* When `enable: false`, the msw worker and server will not try to intercept requests, but keeps auto import composables for type checking.
*
* @default true
*
* @example
* {
* enable: process.env.TEST === 'true'
* }
*/
enable: true, // default: true
/**
* Path to the nuxt-msw runtime folder that include worker and server files.
* @default "~/msw"
*/
folderPath: "~/msw"
/**
* Should include nuxt layers msw settings or not
* @default true
*/
includeLayer?: boolean
/**
*
* Enable unit test mode. default: false
*
* When this mode is enabled, you can use `setupNuxtMswServer` to start the msw server in a unit test environment (which is a Node.js environment).
*
* When enable: false, this mode is inactive.
*
* @default true
*/
testUtils?: boolean
},
})
测试中如何使用
当表演单位与Nuxt测试时,你可能会使用 @nuxt/test-utils 与 vitest。 。 。 .
测试
如果你只是使用Vitest没有 @nuxt/test-utils 环境,你需要手动设置MSW.
维特有一个 实例 在单位测试中如何使用 msw.
[注] 在此情况下, 如果您在 Nuxt 层中设置了处理器, 您需要导出它们以供使用 .
@nuxt/test-utils
我们先谈谈单元测试的部分.
单位测试
根据"Nuxt"的官方文档,如果需要在"Nuxt"上下文范围内进行测试(以确保可相容性和其他特征功能正确),则必须设置"Nuxt"环境.
为确保MSW在这种情况下工作正确,nuxt-msw为环境设置和配置MSW服务器提供了辅助功能.
首先,你需要启用 testUtils 选项 nuxt-msw 模块。 建议启用于 vitest.config.ts。 。 。 .
// vitest.config.ts
import { defineVitestConfig } from '@nuxt/test-utils/config'
export default defineVitestConfig({
// any custom Vitest config you require
test: {
// .....
environmentOptions: {
nuxt: {
domEnvionment: 'happy-dom',
host: 3000,
overrides: {
msw: {
testUtils: true,
},
},
},
},
},
})
那样你就可以用 setupNuxtMswServer 在单位测试中设置 MSW 服务器。 (注:目前无法在设置文件中运行. 所以,你需要运行 在每一个测试文件。 )
这个部件可能是这样的:
<script setup lang="ts">
const { data } = await useFetch(
'/api/user',
{ baseURL: 'http://localhost:3000' }
)
</script>
<template>
<div id="name">{{ data.name }}</div>
</template>
// @vitest-environment nuxt
import { it, expect, afterEach } from 'vitest'
import { mountSuspended } from '@nuxt/test-utils/runtime'
import UserName from './UserName.vue'
import { setupNuxtMswServer } from '@crazydos/nuxt-msw/test-utils'
import { http, HttpResponse } from "msw"
const mswServer = await setupNuxtMswServer({
handlers: [
http.get(
'http://localhost:3000/api/user',
() => HttpResponse.json({ name: 'msw server unit' })
)
],
serverOptions: {
// onUnhandledRequest: 'bypass',
},
})
afterEach(() => {
// you can do anything with mswServer
mswServer.resetHandlers()
})
it('displays message', async () => {
// replace handler if needed
// mswServer.use(
// http.get('/api/user', () => {
// return HttpResponse.json({
// name: 'msw server unit replaced',
// })
// })
// )
const component = await mountSuspended(UserName)
expect(component.find('#name').text()).toBe('msw server unit')
})
然后,你可以运行测试 vitest数字 :
npx vitest
说明: baseURL 单位测试
使用时 $fetch 或者说 useFetch 没有 baseURL 设置,使用没有域的路径 /some/path。你可以嘲讽如下:
// for example
await useFetch('/api/user')
// mock with baseURL
const baseURL = 'http://localhost:3000'
await setupNuxtMswServer({
baseURL,
handlers: [
http.get(baseURL + '/api/user', () => {
return HttpResponse.json({ name: 'msw server unit' })
})
]
})
[注]
baseURL这里只是一个有效的域名, 不需要匹配 nuxt 服务器地址 。 但如果运行一个真正的服务器并想要msw倒回那里,则需要将baseURL设置到真正的服务器地址.
E2E 测试
@nuxt/test-utils 使用Playwright作为E2E测试驱动程序,它实际上在单独的进程中运行了Nuxt服务器和浏览器. 这意味着在测试中我们不能直接修改模拟.
为了修改这种情况下的模拟,你需要利用各种变通办法,例如改变模拟,通过 动态模拟。 。 。 .
这种情况下 nuxt-msw 运行的方式就像正常 Nuxt 应用一样. 所以你可以使用同样的方法来设置MSW服务器和工人.
// For example: dynamic mock
// Normal test case
test('normal mock', async ({ page, goto }) => {
await goto('/', { waitUntil: 'hydration' })
await expect(page.getByText('John')).toBeVisible()
})
// Alternative test case
test('test dynamic mock', async ({ page, goto }) => {
// The server response still the same
await goto('/?alternative=true', { waitUntil: 'hydration' })
// Next, we click a button that make a request from client side
await page.getByTestId('get-data-button').click()
// We get a different response from same api endpoints
await expect(page.getByText('Jane')).toBeVisible()
})
说明: $fetch 财务报告和审定财务报表 fetch 内 @nuxt/test-utils/e2e
@nuxt/test-utils/e2e 提供 $fetch 财务报告和审定财务报表 fetch 在 e2e 测试中向 nuxt 服务器提出请求. nuxt-msw 将不做与这两个函数合并的动作。 故用为常.
import { $fetch, fetch } from '@nuxt/test-utils/e2e'
const html = await $fetch('/')
核子图层
(虽然我认为分享处理器最简单的方式就是分享处理器. ) 您的团队可能要共享 msw 设置, 由 核子层。 。 。 . nuxt-msw 也支持这一点.
nuxt-msw 将合并各个级别的工人和服务器配置。 视配置选项而定,它们将被合并或覆盖。 以下是每个选项的行为:
// worker and server options
{
handlers: [] // merge. the higher level take precedence
workerOptions: {} // merge. the higher level take precedence
serverOptions: {} // merge. the higher level take precedence
baseURL: "" // overwrite. the higher level take precedence
onWorkerStarted: () => {} // merge. the lower level execute first
onRequest: () => {} // merge. the lower level execute first
}
是这样的 nuxt.config 将解决:
export default defineNuxtConfig({
msw: {
includeLayer // overwrite. the higher level take precedence
enable // overwrite. the higher level take precedence
testUtils // overwrite. the higher level take precedence
folderPath // every layer follow its own folderPath setting
}
})
folderPath 是唯一没有合并的选项。 每层都会跟着自己的 folderPath 设置。 例如,如果设置 folderPath 改为 ./msw 设定 ~/msw 在层用户级别, nuxt-msw 将在以下文件夹中找到 msw 文件 :
~/msw/path-to-layer-folder/msw
nuxt 层和单位测试
如果您需要分层共享 msw 设置进行单位测试, 您可以添加一个名为 MSW 的文件 unit.{ts|js|mjs|cjs} 在层文件夹中(应用程序级别也支持此文件)。 合并策略与工人和服务器文件相同.
unit.{ts|js|mjs|cjs} 文件将在 Vitest 环境中运行, 这样您就可以在此文件中访问 。 归根结底,是本组织工作的一部分 setupNuxtMswServer 在单位测试中导入此文件并合并选项.
setupNuxtMswServer 接受与 defineNuxtMswTestOptions 返回时。 备选方案 setupNuxtMswServer 将合并为 unit.{ts|js|mjs|cjs} 文档. setupNuxtMswServer 将享有最高优先.
import { http, HttpResponse } from 'msw'
export default defineNuxtMswTestOptions(() => {
const handlers = [
http.get('/api/user', () => {
// ...and respond to them using this JSON response.
return HttpResponse.json({
id: 'Mock01',
name: 'msw server unit',
})
}),
]
return {
baseURL: 'http://localhost:3000',
handlers,
serverOptions: {
// onUnhandledRequest: 'bypass',
},
}
})
// xxx.spec.ts
import { setupNuxtMswServer } from '@crazydos/nuxt-msw/test-utils'
import { http, HttpResponse } from "msw"
const mswServer = await setupNuxtMswServer(
/**
* You can still pass options to overwrite the options in unit.ts
*/
)
捐款
地方发展
# Install dependencies
pnpm install
# Generate type stubs
pnpm dev:prepare
# Develop with the playground
pnpm dev
# Build the playground
pnpm dev:build
# Run ESLint
pnpm lint
学习更多关于 正在编写 nuxt 模块