In my Nuxt3 project, I have a very basic login page which is SSR like the following:
pages/login.vue
<template>
<form
@submit.prevent="login">
<input
name="email"
v-model="form.email"/>
<input
name="password"
v-model="form.password"/>
<button>login</button>
<form>
</template>
<script setup>
import { useAuth } from '~/store/auth.js';
const auth = useAuth();
const form = ref({email: '', password: ''});
const router = useRouter();
const login = async () => {
useFetch('/api/auth/tokens', {
method: 'POST',
body: form.value
})
.then(({ data }) => {
const { token, user } = data.value;
auth.setUser(user);
auth.setToken(token);
router.push('/profile');
})
}
</script>
- First, I try to test it like a SPA page:
import { describe, test, expect } from 'vitest';
import { mount } from '@vue/test-utils';
import LoginPage from '~/pages/login.vue';
describe('login page', async () => {
test('store tokens', async () => {
const wrapper = mount(LoginPage);
const email = 'test@example.com';
const password = 'password';
await wrapper.find('[name="email"]').setValue(email);
await wrapper.find('[name="password"]').setValue(password);
await wrapper.find('form').trigger('submit.prevent');
expect(
wrapper.emitted('submit')[0][0]
).toStrictEqual({
email,
password,
});
// But this does not test the code in `then()` which handled the response and redirect to `/profile`
});
});
Got error:
FAIL tests/pages/login.spec.js > login page > store tokens ReferenceError: document is not defined
- Then, I followed the Nuxt3 testing
import { describe, test, expect } from 'vitest';
import { setup, $fetch } from '@nuxt/test-utils';
import { JSDOM } from 'jsdom';
describe('login page', async () => {
await setup();
test('store tokens', async () => {
const wrapper = (new JSDOM(await $fetch('/login'))).window.document;
const email = 'test@example.com';
const password = 'password';
await wrapper.find('[name="email"]').setValue(email);
await wrapper.find('[name="password"]').setValue(password);
await wrapper.find('form').trigger('submit.prevent');
expect($fetch).toHaveBeenCalledWith('/api/auth/tokens', {
method: 'POST',
body: {
email: 'test@example.com',
password: 'password'
}
});
});
});
But wrapper
there is just a jsdom document instance, it can't act like a Vue component.
I wonder:
- How to test the user input events?
- How to test the code in
resovle
ofuseFetch()
(in the example, it's the code handling data with pinia)
same question in GitHub