Files
OwnCord/Client/tauri-client/tests/unit/appearance-high-contrast.test.ts
T
J3vbandClaude Fable 5 7be9ccd2f9 fix: batch of 22 correctness fixes across server and client (#1371)
* fix(voice): 4 defect(s) (OC-0008, OC-0009, OC-0042, OC-0080)

Guard LiveKit session state against supersession: bump the camera/screen
generation in leaveVoice and teardownForReconnect so an in-flight enable
discards its track, bail out of restoreLocalVoiceState when a newer room
claimed _room mid-await, and recheck isStateConnected in the auto-reconnect
tail.

* fix(ws): 1 defect(s) (OC-0019)

* fix(db): 1 defect(s) (OC-0023)

* fix(ws): 1 defect(s) (OC-0029)

* fix(ws): 1 defect(s) (OC-0032)

* fix(voice): 1 defect(s) (OC-0034)

* fix(admin): 1 defect(s) (OC-0035)

* fix(service): 2 defect(s) (OC-0036, OC-0128)

* fix(voice): 2 defect(s) (OC-0038, OC-0065)

OC-0038: the LiveKit participant_left webhook cleared the leaver's own
client voice state before broadcasting voice_leave, so the broadcast
audience (READ_MESSAGES holders union still-in-the-room participants)
could no longer see them. Voice membership is gated on CONNECT_VOICE
alone, so a participant without READ_MESSAGES never learned the server
had torn down their call. Extracted finishVoiceLeave's audience logic
into broadcastVoiceEventWithLeaver and used it on the webhook path.

OC-0065: handleWebhookParticipantJoined OR'd a GetVoiceState read error
into the same branch as "no matching row", so a transient DB failure
ejected a legitimate participant from the SFU mid-call. Now the read
error is logged and the check skipped, matching sweepStaleVoiceStates.

* fix(client): 1 defect(s) (OC-0041)

* fix(client): 1 defect(s) (OC-0043)

* fix(client): 1 defect(s) (OC-0046)

* fix(client): 1 defect(s) (OC-0047)

* fix(client): 1 defect(s) (OC-0049)

* fix(client): 1 defect(s) (OC-0108)

* fix(client): 2 defect(s) (OC-0111, OC-0143)

OC-0111: retry a presence_update dropped by the 1-per-10s limiter once the
window reopens, so auto-idle's return-to-online does not leave the server
and every other client stuck on idle.

OC-0143: pass apiConfig.host to the DM profile sidebar so per-user notes
are scoped per server, matching channel mutes, the NSFW gate and volume.

* test(ws): align aborted-switch test with OC-0034 no-resurrect behavior

The fix agent rewrote this pre-existing test (it locked the buggy restore
path) but the prove agent left it out of c67d25ed; committed state alone
failed go test ./ws/ without it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-14 16:15:32 +02:00

51 lines
2.3 KiB
TypeScript

// jsdom never applies app.css, so a computed-style assertion here would pass
// whether or not the rules exist (see status-picker-userbar.test.ts for the
// same pattern). Instead this pins the CSS *source*.
//
// applyTheme() (components/settings/helpers.ts) writes theme tokens --
// including --text-normal -- as an *inline* style on document.documentElement.
// An inline declaration always beats a plain class rule on the same element,
// so `.high-contrast { --text-normal: ... }` can never win against it: the
// High Contrast toggle's headline promise (pure-white body text) is a no-op
// unless the override is `!important`.
//
// applyThemeByName() (lib/themes.ts) does the same thing for custom themes,
// except it writes the inline override on document.body instead of
// documentElement -- so the override also needs a selector that reaches body
// while high-contrast is active, not just one that targets html.
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, it, expect } from "vitest";
describe("high-contrast CSS overrides beat inline theme styles", () => {
const css = readFileSync(join(process.cwd(), "src/styles/app.css"), "utf8");
function highContrastRuleBody(): string {
const match = /\.high-contrast[^{]*\{([^}]*)\}/.exec(css);
expect(match, "expected a `.high-contrast { ... }` rule in app.css").not.toBeNull();
return match![1]!;
}
it("declares --text-normal, --text-muted, and --bg-active with !important", () => {
const body = highContrastRuleBody();
for (const prop of ["--text-normal", "--text-muted", "--bg-active"]) {
const declaration = new RegExp(`${prop}\\s*:[^;]*;`).exec(body);
expect(declaration, `expected a declaration for ${prop}`).not.toBeNull();
expect(
declaration![0],
`${prop} must be !important -- otherwise applyTheme()'s inline style on ` +
`documentElement always wins and the toggle does nothing`,
).toMatch(/!important/);
}
});
it("also reaches document.body, where custom-theme inline overrides live", () => {
expect(
css,
"expected a selector reaching body while .high-contrast is active (e.g. " +
"`.high-contrast body`), otherwise custom themes' inline body vars never see the override",
).toMatch(/\.high-contrast[^{,]*body\s*[{,]/);
});
});