feat: add user selection flow
This commit is contained in:
@ -1,21 +1,145 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { afterEach, expect, test, vi } from 'vitest'
|
||||
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
|
||||
import { afterEach, beforeEach, expect, test, vi } from 'vitest'
|
||||
import App from './App'
|
||||
|
||||
const users = [
|
||||
{
|
||||
id: 'd56b54dd-31b0-4d71-8a10-82464be59a61',
|
||||
name: 'Urban',
|
||||
createdAt: '2026-07-24T10:15:30Z',
|
||||
},
|
||||
{
|
||||
id: '2213a673-c859-462b-a031-7b68b6f01c73',
|
||||
name: 'Anna',
|
||||
createdAt: '2026-07-24T10:16:30Z',
|
||||
},
|
||||
]
|
||||
|
||||
beforeEach(() => {
|
||||
window.localStorage.clear()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
cleanup()
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
test('visar sidans rubrik', () => {
|
||||
vi.spyOn(globalThis, 'fetch').mockResolvedValue(
|
||||
new Response(JSON.stringify({ status: 'UP' }), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
}),
|
||||
test('tom användarlista visar Skapa användare', async () => {
|
||||
mockJsonResponse([])
|
||||
|
||||
render(<App />)
|
||||
|
||||
expect(await screen.findByRole('heading', { name: 'Skapa användare' })).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('befintliga användare utan lokalt val visar Vem är du', async () => {
|
||||
mockJsonResponse(users)
|
||||
|
||||
render(<App />)
|
||||
|
||||
expect(await screen.findByRole('heading', { name: 'Vem är du?' })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'Urban' })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'Anna' })).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('val av användare lagrar id och visar startsidan', async () => {
|
||||
mockJsonResponse(users)
|
||||
render(<App />)
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'Urban' }))
|
||||
|
||||
expect(screen.getByRole('heading', { name: 'Hej Urban' })).toBeInTheDocument()
|
||||
expect(window.localStorage.getItem('hemhub.activeUserId')).toBe(users[0].id)
|
||||
})
|
||||
|
||||
test('skapad användare blir automatiskt aktiv', async () => {
|
||||
const createdUser = users[0]
|
||||
const fetchMock = vi.spyOn(globalThis, 'fetch')
|
||||
fetchMock.mockResolvedValueOnce(jsonResponse([]))
|
||||
fetchMock.mockResolvedValueOnce(jsonResponse(createdUser, 201))
|
||||
|
||||
render(<App />)
|
||||
|
||||
fireEvent.change(await screen.findByLabelText('Namn'), { target: { value: ' Urban ' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Skapa användare' }))
|
||||
|
||||
expect(await screen.findByRole('heading', { name: 'Hej Urban' })).toBeInTheDocument()
|
||||
expect(window.localStorage.getItem('hemhub.activeUserId')).toBe(createdUser.id)
|
||||
expect(fetchMock).toHaveBeenLastCalledWith('/api/users', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name: 'Urban' }),
|
||||
})
|
||||
})
|
||||
|
||||
test('skapandefel visas utan att namnet försvinner', async () => {
|
||||
const fetchMock = vi.spyOn(globalThis, 'fetch')
|
||||
fetchMock.mockResolvedValueOnce(jsonResponse([]))
|
||||
fetchMock.mockResolvedValueOnce(
|
||||
jsonResponse(
|
||||
{
|
||||
code: 'USER_NAME_ALREADY_EXISTS',
|
||||
message: 'En användare med det namnet finns redan.',
|
||||
},
|
||||
409,
|
||||
),
|
||||
)
|
||||
|
||||
render(<App />)
|
||||
|
||||
expect(screen.getByRole('heading', { name: 'HemHub' })).toBeInTheDocument()
|
||||
const input = await screen.findByLabelText('Namn')
|
||||
fireEvent.change(input, { target: { value: 'Urban' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Skapa användare' }))
|
||||
|
||||
expect(await screen.findByRole('alert')).toHaveTextContent(
|
||||
'En användare med det namnet finns redan.',
|
||||
)
|
||||
expect(input).toHaveValue('Urban')
|
||||
})
|
||||
|
||||
test('Byt användare rensar valt id och visar användarvalet', async () => {
|
||||
window.localStorage.setItem('hemhub.activeUserId', users[0].id)
|
||||
mockJsonResponse(users)
|
||||
render(<App />)
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'Byt användare' }))
|
||||
|
||||
expect(screen.getByRole('heading', { name: 'Vem är du?' })).toBeInTheDocument()
|
||||
expect(window.localStorage.getItem('hemhub.activeUserId')).toBeNull()
|
||||
})
|
||||
|
||||
test('hämtningsfel visas som fel och kan återförsökas', async () => {
|
||||
const fetchMock = vi.spyOn(globalThis, 'fetch')
|
||||
fetchMock.mockRejectedValueOnce(new Error('Nätverksfel'))
|
||||
fetchMock.mockResolvedValueOnce(jsonResponse(users))
|
||||
render(<App />)
|
||||
|
||||
expect(await screen.findByText('Kunde inte ansluta till HemHub.')).toBeInTheDocument()
|
||||
expect(screen.queryByRole('heading', { name: 'Skapa användare' })).not.toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Försök igen' }))
|
||||
|
||||
expect(await screen.findByRole('heading', { name: 'Vem är du?' })).toBeInTheDocument()
|
||||
expect(fetchMock).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
test('ogiltigt lagrat användar-id rensas', async () => {
|
||||
window.localStorage.setItem('hemhub.activeUserId', 'finns-inte')
|
||||
mockJsonResponse(users)
|
||||
|
||||
render(<App />)
|
||||
|
||||
expect(await screen.findByRole('heading', { name: 'Vem är du?' })).toBeInTheDocument()
|
||||
expect(window.localStorage.getItem('hemhub.activeUserId')).toBeNull()
|
||||
})
|
||||
|
||||
function mockJsonResponse(body: unknown, status = 200) {
|
||||
return vi.spyOn(globalThis, 'fetch').mockResolvedValue(jsonResponse(body, status))
|
||||
}
|
||||
|
||||
function jsonResponse(body: unknown, status = 200) {
|
||||
return new Response(JSON.stringify(body), {
|
||||
status,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user