feat(ST-1136): mobile Settings-pagina + LogoutButton (T-325/T-326/T-327)
- app/(mobile)/m/settings/page.tsx — read-only account-info, product-selector (hergebruikt ActivateProductButton + setActiveProductAction met redirectTo /m/products/[id]/solo), QR-pairing-instructie, logout - components/mobile/logout-button.tsx — AlertDialog "Uitloggen?" met bevestig + annuleer; demo-user mag uitloggen (geen demo-block) - Tests: LogoutButton render + open + bevestig (logoutAction) + annuleer Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
13ab53ab8d
commit
0a3dc401b7
3 changed files with 194 additions and 0 deletions
46
__tests__/components/mobile/logout-button.test.tsx
Normal file
46
__tests__/components/mobile/logout-button.test.tsx
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// @vitest-environment jsdom
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
|
||||
|
||||
const { logoutMock } = vi.hoisted(() => ({
|
||||
logoutMock: vi.fn().mockResolvedValue(undefined),
|
||||
}))
|
||||
vi.mock('@/actions/auth', () => ({ logoutAction: logoutMock }))
|
||||
|
||||
import { LogoutButton } from '@/components/mobile/logout-button'
|
||||
|
||||
beforeEach(() => {
|
||||
logoutMock.mockClear()
|
||||
})
|
||||
|
||||
describe('LogoutButton', () => {
|
||||
it('toont initieel alleen de Uitloggen-knop, geen dialog', () => {
|
||||
render(<LogoutButton />)
|
||||
expect(screen.getByRole('button', { name: /Uitloggen/ })).toBeTruthy()
|
||||
expect(screen.queryByText(/Weet je zeker/)).toBeNull()
|
||||
})
|
||||
|
||||
it('opent AlertDialog bij klikken op de knop', () => {
|
||||
render(<LogoutButton />)
|
||||
fireEvent.click(screen.getByRole('button', { name: /Uitloggen/ }))
|
||||
expect(screen.getByText('Uitloggen?')).toBeTruthy()
|
||||
expect(screen.getByText(/Weet je zeker/)).toBeTruthy()
|
||||
})
|
||||
|
||||
it('roept logoutAction aan op bevestigen', async () => {
|
||||
const { container } = render(<LogoutButton />)
|
||||
fireEvent.click(screen.getByRole('button', { name: /Uitloggen/ }))
|
||||
// Het body-portal wordt buiten container gerenderd; query op document.body.
|
||||
const allButtons = Array.from(document.body.querySelectorAll('button'))
|
||||
const confirmBtn = allButtons.find(b => b.textContent?.trim() === 'Uitloggen' && !container.contains(b)) ?? allButtons[allButtons.length - 1]
|
||||
fireEvent.click(confirmBtn)
|
||||
await waitFor(() => expect(logoutMock).toHaveBeenCalledTimes(1))
|
||||
})
|
||||
|
||||
it('roept logoutAction NIET aan bij annuleren', () => {
|
||||
render(<LogoutButton />)
|
||||
fireEvent.click(screen.getByRole('button', { name: /Uitloggen/ }))
|
||||
fireEvent.click(screen.getByText('Annuleren'))
|
||||
expect(logoutMock).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue