简体   繁体   中英

Vue: How to mock Auth0 for testing with Vitest

I am trying to test a Vue component with Vitest but in order to do that I need to mock auth0

Below is my Navbar.test.ts file, however when I run the test I keep getting the following error Cannot read properties of undefined (reading 'mockReturnValue' as useAuth0 seems to be undefined even though I am imported it at the top of the page. Maybe I'm just not understanding the mocking side of it very well but any help would be appreciated.

import { vi } from 'vitest'
import { ref } from "vue";
import { shallowMount } from '@vue/test-utils'
import { useAuth0 } from '@auth0/auth0-vue';
import NavBar from "@/components/NavBar.vue";

const user = {
    email: "user@test.com",
    email_verified: true,
    sub: ""
};

vi.mock("@auth0/auth0-vue");

const mockedUseAuth0 = vi.mocked(useAuth0, true);

describe("NavBar.vue", () => {
    beforeEach(() => {
        mockedUseAuth0.mockReturnValue({
            isAuthenticated: ref(true),
            user: ref(user),
            logout: vi.fn(),
            loginWithRedirect: vi.fn(),
            ...
            isLoading: ref(false),
        });
    });

    it("mounts", () => {
        const wrapper = shallowMount(NavBar, {
            props: { },
        });

        expect(wrapper).toBeTruthy();
    });

    afterEach(() => vi.clearAllMocks());
});

Mocking auth0.useAuth0

To access the mocked module, import the whole module with a wildcard import, and avoid named imports. Also, vi.mocked() is just a helper for TypeScript support. It doesn't mock anything.

So instead of this:

import { useAuth0 } from '@auth0/auth0-vue' ❌

vi.mock('@auth0/auth0-vue')
const mockedUseAuth0 = vi.mocked(useAuth0, true) ❌

...do this:

import * as auth0 from '@auth0/auth0-vue' ✅

vi.mock('@auth0/auth0-vue')

Then, mock useAuth0 by attaching a property directly to the mocked auth0 import:

describe('NavBar.vue', () => {
  it('does something', async () => {
                      👇
    (auth0 as any).useAuth0 = vi.fn().mockReturnValue({
      // relevant fields for test
    });
  })
})

The value of useAuth0 should be a mock function ( vi.fn() ) that returns the fields relevant to the test. Assuming the component under test is NavBar.vue from Auth0's sample app , one could write a test to verify the login button calls loginWithRedirect . That button is only available when isAuthenticated and isLoading are false . Note the fields do not need to be Vue ref s.

So such a test could look like this:

describe('NavBar.vue', () => {
  it('login button invokes useAuth.loginWithRedirect', async () => {
    const loginWithRedirect = vi.fn();
    (auth0 as any).useAuth0 = vi.fn().mockReturnValue({
      isAuthenticated: false,
      isLoading: false,
      loginWithRedirect,
    });

    const wrapper = shallowMount(NavBar);
    await wrapper.find('button#qsLoginBtn').trigger('click');

    expect(auth0.useAuth0).toHaveBeenCalled();
    expect(loginWithRedirect).toHaveBeenCalled();
  })
})

Mocking useAuth().user

One could also write a test to verify the authenticated user's details are shown in the component. Specifically, the user's name is shown in .user-info , and the user's picture is shown in .user-info img when isAuthenticated is true. The mocked useAuth0 should thus return isAuthenticated and user as follows:

describe('NavBar', () => {
  it('authenticated user details are shown', async () => {
    const user = {
      name: 'john@gmail.com',
      picture: 'https://s.gravatar.com/avatar/1f9d9a9efc2f523b2f09629444632b5c?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fjo.png',
    };

    (auth0 as any).useAuth0 = vi.fn().mockReturnValue({
      isAuthenticated: true,
      user,
    });

    const wrapper = shallowMount(NavBar);

    expect(wrapper.find('.user-info').text()).toBe(user.name);
    expect(wrapper.find('.user-info img').attributes('src')).toBe(user.picture);
  })
})

demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM