import { afterEach, describe, expect, it, vi } from 'vitest' import { defineComponent, h } from 'vue' import { mount, flushPromises, type VueWrapper } from '@vue/test-utils' import { createPinia, setActivePinia } from 'pinia' import uiPlugin from '@nuxt/ui/vue-plugin' import UApp from '@nuxt/ui/components/App.vue' import router from '@/router' import { useSessionStore } from '@/stores/session' import { DESKTOP_WIDTH, setViewportWidth } from '@/components/__tests__/viewport' import AuthorsView from '../AuthorsView.vue' import SitesView from '../SitesView.vue' import { accessFor } from '@/test/access' let wrapper: VueWrapper | null = null function reply(status: number, body = '') { return new Response(body, { status, headers: { 'Content-Type': 'text/plain' }, }) } async function mountWith( view: typeof AuthorsView | typeof SitesView, path: string, verified: boolean, ) { setViewportWidth(DESKTOP_WIDTH) setActivePinia(createPinia()) const session = useSessionStore() session.session = { verified, username: 'marta', id: 1, displayName: '', access: accessFor('owner'), } session.status = 'ready' await router.push(path) wrapper = mount( defineComponent({ render: () => h(UApp, null, { default: () => h(view) }), }), { attachTo: document.body, global: { plugins: [router, uiPlugin] }, }, ) await flushPromises() } afterEach(async () => { wrapper?.unmount() wrapper = null vi.unstubAllGlobals() await router.push('/login') document.body.innerHTML = '' }) describe('Session problems use the app-wide handling', () => { it.each([ ['/authors', AuthorsView, '/v1/author/'], ['/settings/sites', SitesView, '/v1/site/'], ])('sends a 401 on %s to the login page with the expired reason', async (path, view, api) => { const calls: string[] = [] vi.stubGlobal( 'fetch', vi.fn(async (input: string) => { calls.push(input) return reply(401) }), ) await mountWith(view, path, true) await vi.waitFor(() => expect(router.currentRoute.value.path).toBe('/login')) expect(calls.some((call) => call.startsWith(api))).toBe(true) expect(router.currentRoute.value.path).toBe('/login') expect(router.currentRoute.value.query).toEqual({ redirect: path, reason: 'expired', }) expect(document.body.querySelector('[role="alert"]')).toBeNull() }) it('sends an unverified 403 on /authors to /register/pending', async () => { vi.stubGlobal( 'fetch', vi.fn(async () => reply(403)), ) await mountWith(AuthorsView, '/authors', false) await flushPromises() expect(router.currentRoute.value.path).toBe('/register/pending') }) })