fix(lotus): transparent-theme contrast guard; phone-only rail shrink; live URL params
- lotusTransparent without lotusTheme warns and applies the theme anyway; name tags/header/footer get a subtle text-shadow + backdrop blur under body.lotus-transparent (#21). - Landscape filmstrip shrink requires (pointer: coarse) so a short desktop/PiP window isn't reflowed as a phone (#32). - lotusParam re-reads window.location on every call (#33). Fixes #21 Fixes #32 Fixes #33 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
co-authored by
Claude Opus 5
parent
c7494e68ca
commit
e9a59336c7
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright 2026 Lotus Guild
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { afterEach, describe, expect, test, vi } from "vitest";
|
||||
|
||||
vi.mock("../widget", () => ({ widget: null }));
|
||||
|
||||
import { lotusFlag, lotusParam, lotusSendToHost } from "./lotusWidget";
|
||||
import { LotusWidgetActions } from "./lotusActions";
|
||||
|
||||
/**
|
||||
* Point `window.location` at a URL for the duration of one assertion. Uses a
|
||||
* path relative to the current origin — `pushState` throws a `SecurityError`
|
||||
* on a cross-origin URL, and jsdom's default test origin doesn't match a
|
||||
* hard-coded `http://localhost/`.
|
||||
*/
|
||||
function setLocation(path: string): void {
|
||||
window.history.pushState({}, "", path);
|
||||
}
|
||||
|
||||
describe("lotusParam / lotusFlag", () => {
|
||||
afterEach(() => {
|
||||
setLocation("/");
|
||||
});
|
||||
|
||||
test("reads a param from the query string", () => {
|
||||
setLocation("/?lotusTheme=1");
|
||||
expect(lotusParam("lotusTheme")).toBe("1");
|
||||
});
|
||||
|
||||
test("reads a param from the hash fragment's query portion", () => {
|
||||
setLocation("/#/room?lotusTransparent=1");
|
||||
expect(lotusParam("lotusTransparent")).toBe("1");
|
||||
});
|
||||
|
||||
test("the hash fragment wins over the query string for the same key", () => {
|
||||
setLocation("/?lotusTheme=fromQuery#/room?lotusTheme=fromHash");
|
||||
expect(lotusParam("lotusTheme")).toBe("fromHash");
|
||||
});
|
||||
|
||||
test("falls back to the query string for keys absent from the hash", () => {
|
||||
setLocation("/?onlyInQuery=1#/room?lotusTheme=1");
|
||||
expect(lotusParam("onlyInQuery")).toBe("1");
|
||||
});
|
||||
|
||||
test("returns null when the param is present nowhere", () => {
|
||||
setLocation("/#/room");
|
||||
expect(lotusParam("missing")).toBeNull();
|
||||
});
|
||||
|
||||
test.each([
|
||||
["1", true],
|
||||
["true", true],
|
||||
["0", false],
|
||||
["false", false],
|
||||
[null, false],
|
||||
])("lotusFlag treats %s as %s", (value, expected) => {
|
||||
setLocation(value === null ? "/" : `/?f=${value}`);
|
||||
expect(lotusFlag("f")).toBe(expected);
|
||||
});
|
||||
|
||||
// [lotus #33] lotusParam must re-derive from window.location on every call
|
||||
// rather than caching the first read, so a later navigation (e.g. lobby ->
|
||||
// in-call) that rewrites the URL is picked up.
|
||||
test("re-reads window.location on every call instead of caching the first result", () => {
|
||||
setLocation("/?lotusTheme=1");
|
||||
expect(lotusParam("lotusTheme")).toBe("1");
|
||||
|
||||
setLocation("/?lotusTheme=0");
|
||||
expect(lotusParam("lotusTheme")).toBe("0");
|
||||
|
||||
setLocation("/");
|
||||
expect(lotusParam("lotusTheme")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("lotusSendToHost", () => {
|
||||
test("returns false when no widget transport is available", () => {
|
||||
expect(lotusSendToHost(LotusWidgetActions.CallState, {})).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user