feat: register T1 (pending, verify)

This commit is contained in:
fsylvain committed 2026-09-26 04:56:48 +02:00
1 parent 3c3f7c6194
commit 4e41d60142
29 files changed
+2162 -42

No files matched your search

@@ -0,0 +1,129 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'
import uiPlugin from '@nuxt/ui/vue-plugin'
import ConfirmDialog from '../ConfirmDialog.vue'
afterEach(() => {
document.body.innerHTML = ''
})
function mountDialog(action: () => Promise<void>) {
return mount(ConfirmDialog, {
attachTo: document.body,
props: {
title: 'Cancel your registration?',
description:
'Your account will be deleted. You can register again with the same or a different email.',
confirmLabel: 'Cancel registration',
cancelLabel: 'Keep my account',
pendingLabel: 'Cancelling…',
tone: 'danger',
action,
},
global: {
plugins: [uiPlugin],
},
})
}
function findButtonElement(text: string) {
return Array.from(document.body.querySelectorAll('button')).find(
(button) => button.textContent?.trim() === text,
)
}
async function clickButton(text: string) {
findButtonElement(text)?.click()
await flushPromises()
}
describe('Confirm cancel — the destructive dialog opens', () => {
it('renders title, description, both buttons, role and starts focus on the cancel button', async () => {
const wrapper = mountDialog(() => new Promise(() => {}))
await flushPromises()
expect(document.body.textContent).toContain('Cancel your registration?')
expect(document.body.textContent).toContain(
'Your account will be deleted. You can register again with the same or a different email.',
)
const cancelButton = findButtonElement('Keep my account')
const confirmButton = findButtonElement('Cancel registration')
expect(cancelButton).toBeTruthy()
expect(confirmButton).toBeTruthy()
expect(document.querySelector('[role="alertdialog"]')).toBeTruthy()
expect(cancelButton).toBe(document.activeElement)
wrapper.unmount()
})
})
describe('Cancelling — the action is in flight and the dialog cannot be dismissed', () => {
it('disables both buttons, shows the pending label and sets aria-busy', async () => {
let resolveAction: (() => void) | null = null
const action = vi.fn(
() =>
new Promise<void>((resolve) => {
resolveAction = resolve
}),
)
const wrapper = mountDialog(action)
await flushPromises()
await clickButton('Cancel registration')
expect(action).toHaveBeenCalledTimes(1)
expect((findButtonElement('Keep my account') as HTMLButtonElement).disabled).toBe(true)
expect(findButtonElement('Cancelling…')).toBeTruthy()
expect((findButtonElement('Cancelling…') as HTMLButtonElement).disabled).toBe(true)
expect(document.querySelector('[aria-busy="true"]')).toBeTruthy()
resolveAction?.()
await flushPromises()
wrapper.unmount()
})
})
describe('Keep my account — the dialog is dismissed without deleting anything', () => {
it('emits close(false) without ever calling the action', async () => {
const action = vi.fn(() => Promise.resolve())
const wrapper = mountDialog(action)
await flushPromises()
await clickButton('Keep my account')
expect(action).not.toHaveBeenCalled()
expect(wrapper.emitted('close')).toEqual([[false]])
wrapper.unmount()
})
})
describe('Cancelled — resolving the action closes the dialog', () => {
it('emits close(true) once the action resolves', async () => {
const action = vi.fn(() => Promise.resolve())
const wrapper = mountDialog(action)
await flushPromises()
await clickButton('Cancel registration')
expect(wrapper.emitted('close')).toEqual([[true]])
wrapper.unmount()
})
})
describe('Cancel failed — the dialog stays open and shows the failure inline', () => {
it('re-enables both buttons and shows the rejection message inline', async () => {
const action = vi.fn(() => Promise.reject(new Error("Couldn't cancel registration.")))
const wrapper = mountDialog(action)
await flushPromises()
await clickButton('Cancel registration')
expect(wrapper.emitted('close')).toBeFalsy()
expect(document.body.textContent).toContain("Couldn't cancel registration.")
expect((findButtonElement('Keep my account') as HTMLButtonElement).disabled).toBe(false)
expect((findButtonElement('Cancel registration') as HTMLButtonElement).disabled).toBe(false)
wrapper.unmount()
})
})