Files
nexarch/web/dms-upload/components/CameraCapture.test.tsx
rootandClaude Sonnet 5 0097c8cf2b
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (pull_request) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Canceled after 0s
CI / Web (dms-browser) (pull_request) Canceled after 0s
CI / Web (pdf-viewer) (pull_request) Canceled after 0s
CI / Web (shl) (pull_request) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Canceled after 0s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Canceled after 0s
INT-19: mobile erfassung mobilfreundliche weboberflaeche
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 12:06:19 +00:00

78 lines
3.1 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { CameraCapture } from "./CameraCapture";
import * as mobileCapture from "../lib/mobileCapture";
function mockGetUserMedia(shouldFail = false) {
const stop = vi.fn();
const stream = { getTracks: () => [{ stop }] } as unknown as MediaStream;
Object.defineProperty(globalThis.navigator, "mediaDevices", {
configurable: true,
value: {
getUserMedia: vi.fn(() => (shouldFail ? Promise.reject(new Error("nein")) : Promise.resolve(stream))),
},
});
return { stop };
}
beforeEach(() => {
mockGetUserMedia();
vi.spyOn(mobileCapture, "captureFrame").mockImplementation(async () => ({
id: `seite-${Math.random()}`,
blob: new Blob(["x"], { type: "image/jpeg" }),
previewUrl: "blob:mock",
}));
});
afterEach(() => {
vi.restoreAllMocks();
});
describe("CameraCapture", () => {
// Akzeptanzkriterium 1: Kamera-Aufnahme mit Live-Vorschau, mehrere Seiten sammelbar.
it("sammelt mehrere aufgenommene Seiten vor dem Absenden", async () => {
const onSubmit = vi.fn();
render(<CameraCapture onSubmit={onSubmit} submitting={false} />);
const captureButton = await screen.findByRole("button", { name: "Seite aufnehmen" });
await waitFor(() => expect(captureButton).not.toBeDisabled());
await userEvent.click(captureButton);
await userEvent.click(captureButton);
expect(await screen.findAllByAltText(/Seite \d/)).toHaveLength(2);
expect(screen.getByRole("button", { name: "2 Seite(n) absenden" })).toBeInTheDocument();
});
// Akzeptanzkriterium 1: erneute Aufnahme moeglich (eine Seite entfernen und neu aufnehmen).
it("erlaubt das Entfernen einer aufgenommenen Seite (erneute Aufnahme)", async () => {
render(<CameraCapture onSubmit={vi.fn()} submitting={false} />);
const captureButton = await screen.findByRole("button", { name: "Seite aufnehmen" });
await waitFor(() => expect(captureButton).not.toBeDisabled());
await userEvent.click(captureButton);
const removeButton = await screen.findByRole("button", { name: /entfernen/ });
await userEvent.click(removeButton);
expect(screen.queryByAltText(/Seite \d/)).not.toBeInTheDocument();
});
it("uebergibt genau die gesammelten Seiten beim Absenden", async () => {
const onSubmit = vi.fn();
render(<CameraCapture onSubmit={onSubmit} submitting={false} />);
const captureButton = await screen.findByRole("button", { name: "Seite aufnehmen" });
await waitFor(() => expect(captureButton).not.toBeDisabled());
await userEvent.click(captureButton);
await userEvent.click(await screen.findByRole("button", { name: /absenden/ }));
expect(onSubmit).toHaveBeenCalledTimes(1);
expect(onSubmit.mock.calls[0][0]).toHaveLength(1);
});
it("zeigt einen Hinweis, wenn die Kamera nicht geoeffnet werden kann", async () => {
mockGetUserMedia(true);
render(<CameraCapture onSubmit={vi.fn()} submitting={false} />);
expect(await screen.findByRole("alert")).toHaveTextContent(/Kamera/);
});
});