Files
ThothII/frontend/src/shell/host/OmicsPortalAdapter.test.ts
T
Codex d8a29bfbdd Add full shell, replaceable Omics adapter and bilingual interaction
Implement approved specification #32 and tickets #33-#37. Keep host authentication server-verified and pin session interaction language. Compile scoped base selectors for browser compatibility and retain full gutters during CSS pruning.
2026-09-13 14:26:39 +02:00

77 lines
3.4 KiB
TypeScript

import { afterEach, expect, test, vi } from "vitest";
import { OmicsPortalAdapter } from "./OmicsPortalAdapter";
afterEach(() => {
document.body.replaceChildren();
document.documentElement.removeAttribute("data-bs-theme");
vi.restoreAllMocks();
});
function portal() {
document.documentElement.lang = "en";
document.documentElement.setAttribute("data-bs-theme", "dark");
document.body.innerHTML = '<form action="/i18n/setlang/"><select class="omics-language-select" data-lang="it"><option value="it">Italiano</option></select></form>';
}
test("publishes rendered language, observes theme and actual fullscreen, and cleans up repeated mounts", async () => {
portal();
let fullscreen: Element | null = null;
Object.defineProperty(document, "fullscreenElement", { configurable: true, get: () => fullscreen });
const adapter = new OmicsPortalAdapter();
for (let mount = 0; mount < 2; mount++) {
document.documentElement.setAttribute("data-bs-theme", "dark");
const state = vi.fn();
const error = vi.fn();
const unsubscribe = adapter.subscribe(state, error);
expect(state).toHaveBeenLastCalledWith({ locale: "it", theme: "dark", fullscreen: false });
document.documentElement.setAttribute("data-bs-theme", "light");
await Promise.resolve();
expect(state).toHaveBeenLastCalledWith({ locale: "it", theme: "light", fullscreen: false });
fullscreen = document.documentElement;
document.dispatchEvent(new Event("fullscreenchange"));
expect(state).toHaveBeenLastCalledWith({ locale: "it", theme: "light", fullscreen: true });
fullscreen = null;
document.dispatchEvent(new Event("fullscreenchange"));
expect(state).toHaveBeenLastCalledWith({ locale: "it", theme: "light", fullscreen: false });
unsubscribe();
state.mockClear();
document.documentElement.setAttribute("data-bs-theme", "dark");
document.dispatchEvent(new Event("fullscreenchange"));
await Promise.resolve();
expect(state).not.toHaveBeenCalled();
expect(error).not.toHaveBeenCalled();
}
});
test("missing Omics DOM reports an integration error instead of using fixed html language", () => {
document.documentElement.lang = "it";
const state = vi.fn();
const error = vi.fn();
const unsubscribe = new OmicsPortalAdapter().subscribe(state, error);
expect(state).not.toHaveBeenCalled();
expect(error).toHaveBeenCalledWith(expect.objectContaining({ message: expect.stringMatching(/portal preferences/i) }));
unsubscribe();
});
test.each(["not_a_locale", "en--US", " "])("rejects malformed portal language %j", locale => {
portal();
document.querySelector<HTMLSelectElement>(".omics-language-select")!.dataset.lang = locale;
const state = vi.fn();
const error = vi.fn();
const unsubscribe = new OmicsPortalAdapter().subscribe(state, error);
expect(state).not.toHaveBeenCalled();
expect(error).toHaveBeenCalledWith(expect.objectContaining({ message: expect.stringMatching(/portal preferences/i) }));
unsubscribe();
});
test("accepts a well-formed unsupported language for the shell's catalogue fallback", () => {
portal();
document.querySelector<HTMLSelectElement>(".omics-language-select")!.dataset.lang = "fr-ca";
const state = vi.fn();
const error = vi.fn();
const unsubscribe = new OmicsPortalAdapter().subscribe(state, error);
expect(state).toHaveBeenCalledWith(expect.objectContaining({ locale: "fr-CA" }));
expect(error).not.toHaveBeenCalled();
unsubscribe();
});