Skip to content

g1t/apps/web/app/lib/tokens.test.ts

54 lines2,045 bytesCodeBlame
1import assert from "node:assert/strict";
2import { readFileSync } from "node:fs";
3import { test } from "node:test";
4
5// The shared tokens every site draws from (packages/theme/tokens.css).
6const css = readFileSync(new URL("../../../../packages/theme/tokens.css", import.meta.url), "utf8");
7
8function token(name: string): string {
9 const found = css.match(new RegExp(`--g1t-${name}:\\s*(#[0-9a-f]{6});`, "i"));
10 assert.ok(found, `--g1t-${name} is a six-digit hex colour`);
11 return found[1].toLowerCase();
12}
13
14function luminance(hex: string): number {
15 const [r, g, b] = [1, 3, 5]
16 .map((i) => parseInt(hex.slice(i, i + 2), 16) / 255)
17 .map((c) => (c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4));
18 return 0.2126 * r + 0.7152 * g + 0.0722 * b;
19}
20
21function contrast(a: string, b: string): number {
22 const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x);
23 return (hi + 0.05) / (lo + 0.05);
24}
25
26test("the accent is the logo's lavender, and mint means success", () => {
27 assert.equal(token("accent"), "#b6a8ff");
28 assert.equal(token("success"), "#86efc4");
29});
30
31test("merged reads apart from the accent", () => {
32 assert.notEqual(token("merged"), token("accent"));
33 assert.notEqual(token("merged"), token("success"));
34});
35
36test("text colours meet WCAG AA on every surface", () => {
37 for (const surface of ["bg", "surface", "raised"]) {
38 for (const ink of ["fg", "muted", "accent", "success", "merged", "info", "warn", "danger"]) {
39 const ratio = contrast(token(ink), token(surface));
40 assert.ok(ratio >= 4.5, `--g1t-${ink} on --g1t-${surface} is ${ratio.toFixed(2)}:1`);
41 }
42 }
43});
44
45test("the dark base reads on an accent or success button", () => {
46 for (const fill of ["accent", "accent-hover", "success"]) {
47 const ratio = contrast(token("bg"), token(fill));
48 assert.ok(ratio >= 4.5, `--g1t-bg on --g1t-${fill} is ${ratio.toFixed(2)}:1`);
49 }
50});
51
52test("focus borders in the dim accent stand out from the page", () => {
53 assert.ok(contrast(token("accent-dim"), token("bg")) >= 3);
54});