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
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
78 lines
3.1 KiB
TypeScript
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/);
|
|
});
|
|
});
|