test: implement comprehensive test strategy

- Add Playwright for E2E testing with auth.spec.ts
- Add dialog component tests (8 test cases)
- Add sidebar component tests (11 test cases)
- Add login page integration tests (11 test cases)
- Add dashboard page tests (12 test cases)
- Update package.json with e2e test scripts
- Configure Playwright for Chromium and Firefox
- Test coverage for UI interactions, auth flows, and navigation
This commit is contained in:
Millian Lamiaux
2026-03-17 13:51:39 +01:00
parent b177656efc
commit 3da40c97ce
7 changed files with 814 additions and 1 deletions

View File

@@ -0,0 +1,184 @@
import { describe, it, expect, vi } from 'vitest'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from './dialog'
import { Button } from './button'
describe('Dialog', () => {
it('should render dialog trigger', () => {
render(
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Test Title</DialogTitle>
</DialogHeader>
</DialogContent>
</Dialog>
)
expect(screen.getByRole('button', { name: /open dialog/i })).toBeInTheDocument()
})
it('should open dialog when trigger is clicked', async () => {
render(
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Test Title</DialogTitle>
<DialogDescription>Test Description</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
)
await userEvent.click(screen.getByRole('button', { name: /open dialog/i }))
await waitFor(() => {
expect(screen.getByRole('dialog')).toBeInTheDocument()
})
expect(screen.getByText('Test Title')).toBeInTheDocument()
expect(screen.getByText('Test Description')).toBeInTheDocument()
})
it('should close dialog when clicking outside', async () => {
render(
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Test Title</DialogTitle>
</DialogHeader>
</DialogContent>
</Dialog>
)
await userEvent.click(screen.getByRole('button', { name: /open dialog/i }))
await waitFor(() => {
expect(screen.getByRole('dialog')).toBeInTheDocument()
})
// Click on the backdrop (outside the dialog content)
const backdrop = document.querySelector('[data-state="open"]')
if (backdrop) {
await userEvent.click(backdrop)
}
})
it('should close dialog when pressing escape', async () => {
render(
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Test Title</DialogTitle>
</DialogHeader>
</DialogContent>
</Dialog>
)
await userEvent.click(screen.getByRole('button', { name: /open dialog/i }))
await waitFor(() => {
expect(screen.getByRole('dialog')).toBeInTheDocument()
})
await userEvent.keyboard('{Escape}')
})
it('should render dialog with footer', async () => {
render(
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Delete Item</DialogTitle>
</DialogHeader>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button>Delete</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)
await userEvent.click(screen.getByRole('button', { name: /open dialog/i }))
await waitFor(() => {
expect(screen.getByRole('button', { name: /cancel/i })).toBeInTheDocument()
expect(screen.getByRole('button', { name: /delete/i })).toBeInTheDocument()
})
})
it('should support custom styling', async () => {
render(
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent className="bg-neutral-900 border-neutral-800 text-white">
<DialogHeader>
<DialogTitle>Styled Dialog</DialogTitle>
</DialogHeader>
</DialogContent>
</Dialog>
)
await userEvent.click(screen.getByRole('button', { name: /open dialog/i }))
await waitFor(() => {
const dialog = screen.getByRole('dialog')
expect(dialog).toHaveClass('bg-neutral-900')
expect(dialog).toHaveClass('border-neutral-800')
expect(dialog).toHaveClass('text-white')
})
})
it('should be accessible', async () => {
render(
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Accessible Dialog</DialogTitle>
<DialogDescription>This is a description</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
)
const trigger = screen.getByRole('button', { name: /open dialog/i })
expect(trigger).toHaveAttribute('aria-haspopup', 'dialog')
expect(trigger).toHaveAttribute('aria-expanded', 'false')
await userEvent.click(trigger)
await waitFor(() => {
const dialog = screen.getByRole('dialog')
expect(dialog).toHaveAttribute('aria-modal', 'true')
})
})
})