feat: Phase 2+3 frontend coverage — responsive + accessibility tests + CI threshold
CI / test (push) Failing after 9s
CI / docker (push) Skipped

- Viewer accessibility: 5 tests (aria-labels, aria-expanded, label association, alert role)
- Viewer responsive: 3 tests (chat-collapsed, CSS grid, now-playing aria-live)
- Admin accessibility: 3 tests (nav aria-label, aria-current, focusability)
- Admin responsive: 2 tests (tab visibility, essential tabs)
- Coverage: vitest v8 provider, 40% stmt/lines, 30% branches/funcs
- CI: test:coverage step between lint and build
- Total: 44 frontend tests (31 + 13 new)
- Updated TODO.md (Phase 2+3 done), DONE.md, MEMORY.md
This commit is contained in:
zwitschi committed 2026-08-10 17:37:51 +02:00
1 parent 9178b7b295
commit d823763dc3
8 files changed
+168 -6

No files matched your search

+65
View File
@@ -371,3 +371,68 @@ describe("player error recovery", () => {
}
});
});
describe("accessibility", () => {
it("player video has controls and aria attributes", () => {
const video = document.getElementById("player") as HTMLVideoElement;
expect(video.controls).toBe(true);
expect(video.hasAttribute("autoplay")).toBe(true);
expect(video.hasAttribute("playsinline")).toBe(true);
});
it("chat panel has aria-labels for live region", () => {
const messages = document.getElementById("messages");
expect(messages?.getAttribute("aria-live")).toBe("polite");
const chatPanel = document.getElementById("chat-panel");
expect(chatPanel?.getAttribute("aria-label")).toBe("Chat panel");
});
it("chat toggle exposes aria-expanded state", () => {
const toggle = document.getElementById("chat-toggle")!;
expect(toggle.getAttribute("aria-expanded")).toBe("true");
window.toggleChatPanel();
expect(toggle.getAttribute("aria-expanded")).toBe("false");
});
it("message input has associated label", () => {
const input = document.getElementById("message-input") as HTMLInputElement;
expect(input.getAttribute("type")).toBe("text");
expect(input.placeholder).toBe("Type a message...");
const label = document.querySelector("label[for='message-input']");
expect(label).toBeTruthy();
expect(label?.textContent).toBe("Message input");
});
it("reconnecting overlay is an aria-live assertive region", () => {
const overlay = document.getElementById("reconnecting-overlay");
expect(overlay?.getAttribute("role")).toBe("alert");
expect(overlay?.getAttribute("aria-live")).toBe("assertive");
});
});
describe("responsive layout", () => {
it("chat-collapsed class hides sidebar at narrow viewport", () => {
const shell = document.querySelector(".viewer-shell")!;
expect(shell.classList.contains("chat-collapsed")).toBe(false);
window.toggleChatPanel();
expect(shell.classList.contains("chat-collapsed")).toBe(true);
window.toggleChatPanel();
expect(shell.classList.contains("chat-collapsed")).toBe(false);
});
it("viewer-shell uses CSS grid for content layout", () => {
const content = document.querySelector(".viewer-content");
expect(content).toBeTruthy();
const style = window.getComputedStyle(content!);
expect(style.display).toBe("grid");
});
it("now-playing overlay is accessible at small sizes", () => {
const np = document.getElementById("now-playing");
expect(np?.getAttribute("aria-live")).toBe("polite");
});
});