import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'
import { mount } from '@vue/test-utils'
import { createRouter, createMemoryHistory } from 'vue-router'
import ResetPasswordPage from '@/pages/ResetPasswordPage.vue'
function mockFetchResponse(status: number, body: unknown) {
return Promise.resolve({
ok: status >= 200 && status < 300,
status,
json: () => Promise.resolve(body),
})
}
function createTestRouter() {
return createRouter({
history: createMemoryHistory(),
routes: [
{
path: '/aterstall-losenord',
name: 'reset-password',
component: ResetPasswordPage,
},
{
path: '/logga-in',
name: 'login',
component: { template: '
Login
' },
},
{
path: '/glomt-losenord',
name: 'forgot-password',
component: { template: 'Forgot
' },
},
],
})
}
async function mountPage(initialPath: string) {
const router = createTestRouter()
await router.push(initialPath)
await router.isReady()
return {
router,
wrapper: mount(ResetPasswordPage, {
global: { plugins: [router] },
}),
}
}
describe('ResetPasswordPage', () => {
beforeEach(() => {
vi.useFakeTimers()
globalThis.fetch = vi.fn()
vi.mocked(globalThis.fetch).mockResolvedValue(
mockFetchResponse(200, {
message: 'Lösenordet har uppdaterats. Du kan nu logga in.',
}),
)
})
afterEach(() => {
vi.useRealTimers()
})
it('shows error when token query is missing', async () => {
const { wrapper } = await mountPage('/aterstall-losenord')
await vi.waitFor(() => {
expect(wrapper.text()).toContain(
'Återställningslänken saknar en giltig kod.',
)
})
})
it('shows password min length hint', async () => {
const { wrapper } = await mountPage('/aterstall-losenord?token=abc')
await wrapper.find('#password').setValue('short')
expect(wrapper.text()).toContain('Lösenordet måste vara minst 8 tecken')
})
it('shows mismatch hint when confirm password differs', async () => {
const { wrapper } = await mountPage('/aterstall-losenord?token=abc')
await wrapper.find('#password').setValue('password1234')
await wrapper.find('#confirmPassword').setValue('different1234')
expect(wrapper.text()).toContain('Lösenorden matchar inte')
})
it('shows success and navigates to login after reset', async () => {
const { wrapper, router } = await mountPage('/aterstall-losenord?token=abc')
await wrapper.find('#password').setValue('newpassword123')
await wrapper.find('#confirmPassword').setValue('newpassword123')
await wrapper.find('form').trigger('submit.prevent')
await vi.waitFor(() => {
expect(wrapper.text()).toContain(
'Lösenordet har uppdaterats. Du kan nu logga in.',
)
})
await vi.advanceTimersByTimeAsync(2000)
expect(router.currentRoute.value.path).toBe('/logga-in')
})
it('shows invalid token message from backend', async () => {
vi.mocked(globalThis.fetch).mockResolvedValue(
mockFetchResponse(400, {
message: 'Återställningslänken är ogiltig eller har gått ut',
}),
)
const { wrapper } = await mountPage('/aterstall-losenord?token=bad')
await wrapper.find('#password').setValue('newpassword123')
await wrapper.find('#confirmPassword').setValue('newpassword123')
await wrapper.find('form').trigger('submit.prevent')
await vi.waitFor(() => {
expect(wrapper.text()).toContain(
'Återställningslänken är ogiltig eller har gått ut',
)
expect(wrapper.find('a[href="/glomt-losenord"]').text()).toContain(
'Begär ny länk',
)
})
})
})