Initial commit
This commit is contained in:
commit
afed023152
8152 files changed
+2086461
No files matched your search
@@ -0,0 +1,117 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { UserMenu } from '../src/auth/UserMenu'
|
||||
import { SessionCard } from '../src/auth/SessionCard'
|
||||
import { login } from '../src/auth/useSession'
|
||||
|
||||
const anonymousBody = JSON.stringify({ authenticated: false, user: null })
|
||||
const userBody = JSON.stringify({
|
||||
authenticated: true,
|
||||
user: {
|
||||
sub: 'user-1',
|
||||
name: 'Mats Test',
|
||||
email: 'mats@example.com',
|
||||
roles: ['admin'],
|
||||
},
|
||||
})
|
||||
|
||||
function stubFetch(body: string, ok = true): ReturnType<typeof vi.fn> {
|
||||
const fetchMock = vi.fn().mockResolvedValue({
|
||||
ok,
|
||||
json: () => Promise.resolve(JSON.parse(body)),
|
||||
})
|
||||
vi.stubGlobal('fetch', fetchMock)
|
||||
return fetchMock
|
||||
}
|
||||
|
||||
// jsdom's window.location is unforgeable; replace the whole global so the
|
||||
// login() navigation target can be asserted.
|
||||
beforeEach(() => {
|
||||
vi.stubGlobal('location', { href: '', pathname: '/patterns', search: '?pattern=table' })
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals()
|
||||
})
|
||||
|
||||
describe('login()', () => {
|
||||
it('navigates to the backend login with the current path as returnTo', () => {
|
||||
login()
|
||||
expect(window.location.href).toBe('/api/auth/login?returnTo=' + encodeURIComponent('/patterns?pattern=table'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('UserMenu', () => {
|
||||
it('shows Sign in when anonymous', async () => {
|
||||
stubFetch(anonymousBody)
|
||||
render(<UserMenu />)
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: 'Sign in' })).toBeInTheDocument())
|
||||
})
|
||||
|
||||
it('shows the avatar and a sign-out popover when authenticated', async () => {
|
||||
stubFetch(userBody)
|
||||
render(<UserMenu />)
|
||||
|
||||
const avatar = await waitFor(() => screen.getByRole('button', { name: 'Mats Test' }))
|
||||
expect(avatar).toHaveTextContent('MT')
|
||||
|
||||
fireEvent.click(avatar)
|
||||
expect(screen.getByRole('menu')).toBeInTheDocument()
|
||||
expect(screen.getByText('mats@example.com')).toBeInTheDocument()
|
||||
|
||||
const fetchMock = vi.mocked(globalThis.fetch)
|
||||
fireEvent.click(screen.getByRole('menuitem', { name: /sign out/i }))
|
||||
await waitFor(() =>
|
||||
expect(fetchMock).toHaveBeenCalledWith('/api/auth/logout', { method: 'POST' }),
|
||||
)
|
||||
// Back to anonymous.
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: 'Sign in' })).toBeInTheDocument())
|
||||
})
|
||||
|
||||
it('treats an unreachable backend as anonymous', async () => {
|
||||
vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new Error('backend down')))
|
||||
render(<UserMenu />)
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: 'Sign in' })).toBeInTheDocument())
|
||||
})
|
||||
|
||||
it('closes the popover on Escape', async () => {
|
||||
stubFetch(userBody)
|
||||
render(<UserMenu />)
|
||||
fireEvent.click(await waitFor(() => screen.getByRole('button', { name: 'Mats Test' })))
|
||||
expect(screen.getByRole('menu')).toBeInTheDocument()
|
||||
fireEvent.keyDown(document, { key: 'Escape' })
|
||||
expect(screen.queryByRole('menu')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe('SessionCard', () => {
|
||||
it('offers sign-in with a note when anonymous', async () => {
|
||||
stubFetch(anonymousBody)
|
||||
render(<SessionCard />)
|
||||
const button = await waitFor(() => screen.getByRole('button', { name: 'Sign in' }))
|
||||
expect(screen.getByText(/not signed in/i)).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(button)
|
||||
expect(window.location.href).toBe('/api/auth/login?returnTo=' + encodeURIComponent('/'))
|
||||
})
|
||||
|
||||
it('shows the signed-in user, roles, and sub when authenticated', async () => {
|
||||
stubFetch(userBody)
|
||||
render(<SessionCard />)
|
||||
expect(await screen.findByText('Mats Test')).toBeInTheDocument()
|
||||
expect(screen.getByText('mats@example.com')).toBeInTheDocument()
|
||||
expect(screen.getByText('sub: user-1')).toBeInTheDocument()
|
||||
expect(screen.getByText('admin')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('signs out and flips back to anonymous', async () => {
|
||||
stubFetch(userBody)
|
||||
render(<SessionCard />)
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'Sign out' }))
|
||||
const fetchMock = vi.mocked(globalThis.fetch)
|
||||
await waitFor(() =>
|
||||
expect(fetchMock).toHaveBeenCalledWith('/api/auth/logout', { method: 'POST' }),
|
||||
)
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: 'Sign in' })).toBeInTheDocument())
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user