Skip to content

Instantly share code, notes, and snippets.

@kudoh
Last active January 31, 2024 07:47
Show Gist options
  • Select an option

  • Save kudoh/e69e8b1f227f58866264d6a928ca0093 to your computer and use it in GitHub Desktop.

Select an option

Save kudoh/e69e8b1f227f58866264d6a928ca0093 to your computer and use it in GitHub Desktop.
Nuxt3(ofetch) + MSW + Vitest with request assertion
import { flushPromises, mount, type VueWrapper } from '@vue/test-utils';
import { expect } from 'vitest';
import foo from '~/pages/foo.vue';
import { getJsonRequests, server } from '~/tests/mocks/server';
import { HttpResponse, http } from 'msw';
describe('foo', () => {
let wrapper: VueWrapper;
afterEach(() => {
wrapper.unmount();
});
test('get', async () => {
server.use(http.get('/api/foo', () => HttpResponse.json({ hello: 'mock' }, { status: 200 })));
server.listen();
wrapper = mount(foo);
await wrapper.get('#foo-button').trigger('click');
await flushPromises();
expect(wrapper.get('#label').text()).toBe('mock');
});
test('post with request assertion', async () => {
server.use(http.post('/api/foo', () => new HttpResponse()));
server.listen();
wrapper = mount(foo);
await wrapper.get('#bar-button').trigger('click');
await flushPromises();
const [request] = await getJsonRequests('post', '/api/foo');
expect(request.body).toEqual({ bar: 'ofetch' });
});
});
<script setup lang="ts">
import { createFetch } from 'ofetch';
const value = ref('');
const get = async () => {
const fetch = createFetch(); // working on msw!!
// const api = $fetch.create({}) // no mock!!
const resp = await fetch('/api/foo', { method: 'GET' });
value.value = resp.hello;
};
const post = async () => {
const fetch = createFetch();
await fetch('/api/foo', {
method: 'post', body: {
bar: 'ofetch'
}
});
};
</script>
<template>
<div>
<button id="foo-button" @click="get">foo</button>
<button id="bar-button" @click="post">bar</button>
<div id="label">{{ value }}</div>
</div>
</template>
import { setupServer } from 'msw/node';
import { fail } from 'node:assert';
const server = setupServer();
server.events.on('request:start', ({ request }) => {
console.debug('MSW intercepted:', request.method, request.url);
});
let requests: Record<string, Partial<Pick<Request, 'headers' | 'url' | 'method'>> & {
payload: Promise<string>
}[]> = {};
function createKey(request: { method?: string, path: string }) {
return `${request.method?.toLowerCase() ?? 'get'} ${request.path}`;
}
server.events.on('request:match', async ({ request }) => {
console.log('request:match', request.method);
const key = createKey({ method: request.method, path: new URL(request.url).pathname });
const promise = request.text();
if (requests[key]) {
requests[key].push({ ...request, payload: promise });
} else {
requests[key] = [{ ...request, payload: promise }];
}
});
async function getJsonRequests(method: 'get' | 'post' | 'put' | 'delete', path: string) {
const key = createKey({ method, path });
if (!requests[key]) {
fail(`no request found: ${key}\n\nhistory: \n${Object.keys(requests).join('\n')}`);
}
const result = [];
for (const request of requests[key]) {
try {
const body = JSON.parse((await request.payload));
result.push({ ...request, body });
} catch (e) {
console.error(`cannot parse json: ${key}`);
throw e
}
}
return result;
}
function resetRequests() {
requests = {};
}
export { server, getJsonRequests, resetRequests };
import { resetRequests, server } from './server';
afterAll(() => {
server.close();
});
afterEach(() => {
server.resetHandlers();
resetRequests();
});
import { defineVitestConfig } from '@nuxt/test-utils/config'
export default defineVitestConfig({
test: {
environment: 'nuxt',
globals: true,
setupFiles: ['tests/mocks/setup.ts']
}
})
@kudoh
Copy link
Author

kudoh commented Jan 31, 2024

tested by Nuxt 3.10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment