From 9a62743e6fa26a3cadd3026d34981a9153ecd981 Mon Sep 17 00:00:00 2001 From: gilles Date: Tue, 22 Sep 2026 08:39:02 +0200 Subject: [PATCH] =?UTF-8?q?test(ui):=20couvrir=20les=20pages=20Cartes,=20d?= =?UTF-8?q?=C3=A9tail,=20=C3=A9dition=20et=20Jeu=20+=20page=20de=20cr?= =?UTF-8?q?=C3=A9ation=20manquante=20(P4,=20F-05=20=C3=A0=20F-10)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/cards/[id]/edit/page.test.tsx | 59 +++++++++++++++++++++++++++ src/app/cards/[id]/page.test.tsx | 41 +++++++++++++++++++ src/app/cards/new/page.test.tsx | 23 +++++++++++ src/app/cards/new/page.tsx | 24 +++++++++++ src/app/cards/page.test.tsx | 25 ++++++++++++ 5 files changed, 172 insertions(+) create mode 100644 src/app/cards/[id]/edit/page.test.tsx create mode 100644 src/app/cards/[id]/page.test.tsx create mode 100644 src/app/cards/new/page.test.tsx create mode 100644 src/app/cards/new/page.tsx create mode 100644 src/app/cards/page.test.tsx diff --git a/src/app/cards/[id]/edit/page.test.tsx b/src/app/cards/[id]/edit/page.test.tsx new file mode 100644 index 0000000..0ccdcac --- /dev/null +++ b/src/app/cards/[id]/edit/page.test.tsx @@ -0,0 +1,59 @@ +import { render, screen } from '@testing-library/react' +import { describe, expect, it, vi } from 'vitest' +import EditCardPage from './page' + +vi.mock('@/lib/api-client', () => { + class ApiClientErrorMock extends Error { + status: number + constructor(status: number, name: string, message: string) { + super(message) + this.name = name + this.status = status + } + } + return { + ApiClientError: ApiClientErrorMock, + cardsApi: { get: vi.fn() }, + } +}) + +const notFoundMock = vi.fn() +vi.mock('next/navigation', () => ({ + useRouter: () => ({ push: vi.fn(), refresh: vi.fn() }), + notFound: () => notFoundMock(), +})) + +import { ApiClientError, cardsApi } from '@/lib/api-client' + +const CARD = { + id: '1', + question: 'Cest quoi un commit ?', + response: 'Un snapshot', + theme: 'git', + tags: [], + createdAt: new Date('2026-01-01T08:00:00Z'), + updatedAt: new Date('2026-01-01T08:00:00Z'), +} + +describe('EditCardPage', () => { + it('pré-remplit le formulaire depuis la carte (F-06)', async () => { + vi.mocked(cardsApi.get).mockResolvedValue(CARD) + const element = await EditCardPage({ params: Promise.resolve({ id: '1' }) }) + render(element) + expect(screen.getByLabelText('Question')).toHaveValue('Cest quoi un commit ?') + expect(screen.getByLabelText('R\u00e9ponse')).toHaveValue('Un snapshot') + expect(screen.getByRole('button', { name: 'Enregistrer' })).toBeInTheDocument() + }) + + it('déclenche notFound si la carte est inconnue', async () => { + notFoundMock.mockImplementation(() => { + throw new Error('not-found') + }) + vi.mocked(cardsApi.get).mockRejectedValue( + new ApiClientError(404, 'NotFoundError', 'Carte introuvable'), + ) + await expect(EditCardPage({ params: Promise.resolve({ id: 'x' }) })).rejects.toThrow( + 'not-found', + ) + }) +}) diff --git a/src/app/cards/[id]/page.test.tsx b/src/app/cards/[id]/page.test.tsx new file mode 100644 index 0000000..2a43666 --- /dev/null +++ b/src/app/cards/[id]/page.test.tsx @@ -0,0 +1,41 @@ +import { render, screen } from '@testing-library/react' +import { describe, expect, it, vi } from 'vitest' +import CardDetailPage from './page' + +vi.mock('@/lib/api-client', () => { + class ApiClientErrorMock extends Error { + status: number + constructor(status: number, name: string, message: string) { + super(message) + this.name = name + this.status = status + } + } + return { + ApiClientError: ApiClientErrorMock, + cardsApi: { get: vi.fn() }, + } +}) + +import { cardsApi } from '@/lib/api-client' + +const CARD = { + id: '1', + question: 'Q ?', + response: 'R', + theme: 'git', + tags: [], + createdAt: new Date('2026-01-01T08:00:00Z'), + updatedAt: new Date('2026-01-01T08:00:00Z'), +} + +describe('CardDetailPage', () => { + it('affiche le détail complet de la carte (F-09)', async () => { + vi.mocked(cardsApi.get).mockResolvedValue(CARD) + const element = await CardDetailPage({ params: Promise.resolve({ id: '1' }) }) + render(element) + expect(await screen.findByRole('heading', { name: 'Q ?' })).toBeInTheDocument() + expect(screen.getByText('R')).toBeInTheDocument() + expect(screen.getByText('git')).toBeInTheDocument() + }) +}) diff --git a/src/app/cards/new/page.test.tsx b/src/app/cards/new/page.test.tsx new file mode 100644 index 0000000..2aee1d5 --- /dev/null +++ b/src/app/cards/new/page.test.tsx @@ -0,0 +1,23 @@ +import { render, screen } from '@testing-library/react' +import { describe, expect, it, vi } from 'vitest' +import NewCardPage from './page' + +vi.mock('@/lib/api-client', () => ({ + ApiClientError: class extends Error { + status = 0 + }, + cardsApi: { create: vi.fn() }, +})) + +vi.mock('next/navigation', () => ({ + useRouter: () => ({ push: vi.fn(), refresh: vi.fn() }), +})) + +describe('NewCardPage', () => { + it('affiche le formulaire de création (F-05)', () => { + render() + expect(screen.getByRole('heading', { level: 1, name: 'Nouvelle carte' })).toBeInTheDocument() + expect(screen.getByLabelText('Question')).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'Cr\u00e9er la carte' })).toBeInTheDocument() + }) +}) diff --git a/src/app/cards/new/page.tsx b/src/app/cards/new/page.tsx new file mode 100644 index 0000000..fa1dc5c --- /dev/null +++ b/src/app/cards/new/page.tsx @@ -0,0 +1,24 @@ +import type { Metadata } from 'next' +import Link from 'next/link' +import { CardForm } from '@/components/card-form' + +export const metadata: Metadata = { + title: 'Nouvelle carte', +} + +export default function NewCardPage() { + return ( +
+
+ + ← Retour à la liste + +

Nouvelle carte

+
+ +
+ ) +} diff --git a/src/app/cards/page.test.tsx b/src/app/cards/page.test.tsx new file mode 100644 index 0000000..bdf7b10 --- /dev/null +++ b/src/app/cards/page.test.tsx @@ -0,0 +1,25 @@ +import { render, screen } from '@testing-library/react' +import { describe, expect, it, vi } from 'vitest' +import CardsPage from './page' + +vi.mock('@/lib/api-client', () => ({ + ApiClientError: class extends Error { + status = 0 + }, + cardsApi: { list: vi.fn() }, +})) + +import { cardsApi } from '@/lib/api-client' + +describe('CardsPage', () => { + it('affiche la liste des cartes et un lien vers la création (F-05, F-08)', async () => { + vi.mocked(cardsApi.list).mockResolvedValue([]) + render() + expect(screen.getByRole('heading', { level: 1, name: 'Cartes' })).toBeInTheDocument() + expect(screen.getByRole('link', { name: 'Nouvelle carte' })).toHaveAttribute( + 'href', + '/cards/new', + ) + await screen.findByRole('status') + }) +})