6

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>

  1. 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 document is not defined

  1. 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:

  1. How to test the user input events?
  2. How to test the code in resovle of useFetch() (in the example, it's the code handling data with pinia)

same question in GitHub

DengSihan
  • 2,119
  • 1
  • 13
  • 40

1 Answers1

0

I would unit test the component, so check if inputs work as expected and also if the correct action is triggered on submit. So don't render a whole page, just mount the component in the test.

I would test the login action afterwards separately meaning you mock the data from the API (token, user) and check if they are set correctly to the auth. Plus, if there's a redirect. This should be possible.

You want to test the whole feature (login) which is often referred as "feature testing". But the base is unit tests.

zangab
  • 428
  • 2
  • 5
  • Do you mean I should test the SSR and function of the page component separately instead of testing it in a single `test()` function? Would you like to share the test code of your idea? (Some code I already done to test the user input event in [stackblitz.com](https://stackblitz.com/edit/github-q6hne6-trebwi?file=test/form.test.js)) – DengSihan Jan 22 '23 at 04:34
  • I gave you the bounty since you're the only one who answered, but I would really appreciate it if any shared code – DengSihan Jan 23 '23 at 04:53
  • @DengSihan exactly. first you test if your component works how it should. it doesn't matter if it is SSR or not. you could then extend your testing. next3 testing uses `playwright` under the hood (see "browser" setting) which you can use for a feature test like go on page X, expect a headline/form/etc to be there, fill in some form, press submit, expect response (like beeing redirected, having a success flash/notice or errors on input fields, etc, etc). see playwright docs, https://playwright.dev/docs/writing-tests – zangab Jan 23 '23 at 14:40