Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
# leaves it none, so every line looks new.
fetch-depth: 0

# Turns off the browser sweeps, Lighthouse, the uploads and Chromatic when
# Turns off the browser suites, Lighthouse, the uploads and Chromatic when
# nothing they check changed: a release PR, or a PR touching only Markdown
# and docs/. Lighthouse, the bundle stats and Chromatic also skip when every
# change is on a path known not to reach the built page or Chromatic's specs.
Expand Down Expand Up @@ -128,7 +128,7 @@ jobs:

# After the sweep, which leaves both things this needs in place: the browser
# binary and the build. Before the scan, so a broken flow reports as itself.
- name: End-to-end sweep
- name: End-to-end tests
if: env.HEAVY_CHECKS == 'true'
run: npm run test:e2e

Expand All @@ -143,8 +143,8 @@ jobs:
retention-days: 7

# Advisory: a slow score or a failed audit never fails the job. Reuses the
# build and the headless shell the sweeps above already have in place.
- name: Lighthouse
# build and the headless shell the suites above already have in place.
- name: Lighthouse (advisory)
if: env.UI_CHECKS == 'true'
run: npm run lighthouse
continue-on-error: true
Expand Down Expand Up @@ -220,7 +220,7 @@ jobs:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar

# After the sweeps, so a failing test reports as itself rather than as an
# After the browser suites, so a failing test reports as itself, not as an
# absent coverage report. Skipped for the updater, whose empty token would
# fail the job; a version bump touches no source for the scan to read.
- name: SonarQube scan
Expand All @@ -241,7 +241,7 @@ jobs:
# Last, because every step above carries no status function and so inherits
# success(): a Chromatic failure placed earlier would skip the two uploads,
# the scan and the Pages artifact. It reads the archives the end-to-end
# sweep already wrote, so it rebuilds and re-runs nothing.
# tests already wrote, so it rebuilds and re-runs nothing.
#
# Exits once the build is uploaded rather than waiting out the capture, so
# a slow queue cannot spend the job's budget. The accept gate is
Expand Down Expand Up @@ -271,7 +271,7 @@ jobs:
# later runs. A job of its own so the write token never meets `npm ci`. Skipped
# for forks and the updater, whose tokens are read-only.
report:
name: Report
name: Lighthouse report
needs: verify
if: >-
github.event_name == 'pull_request'
Expand Down
32 changes: 32 additions & 0 deletions src/toolchain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,38 @@ describe("toolchain baseline", () => {
}
});

// A web manifest and a theme-color meta cannot read a custom property, so the
// brand hex is copied into each; this holds every copy to the token.
it("keeps the manifest and shell theme colors on the brand token", () => {
const tokens = JSON.parse(
readFileSync(join(projectRoot, "tokens", "base.tokens.json"), "utf8"),
) as {
color: { brand: { $value: string } };
primitive: Record<string, { $value: { hex: string } } | undefined>;
};
const webManifest = JSON.parse(
readFileSync(join(projectRoot, "public", "manifest.json"), "utf8"),
) as { theme_color?: string };
const primitive = /^\{primitive\.(.+)\}$/.exec(
tokens.color.brand.$value,
)?.[1];
const brand = tokens.primitive[primitive ?? ""]?.$value.hex.toLowerCase();

expect(brand, "color.brand resolves to no primitive hex").toMatch(/^#/);
expect(webManifest.theme_color?.toLowerCase()).toBe(brand);

for (const shell of shells()) {
const html = readFileSync(join(projectRoot, shell), "utf8");

const meta = /<meta[^>]*\bname="theme-color"[^>]*>/.exec(html)?.[0];

expect(
/\bcontent="([^"]*)"/.exec(meta ?? "")?.[1]?.toLowerCase(),
`${shell} theme-color`,
).toBe(brand);
}
});

// The browser sweeps mount into a harness document, and the application
// restamps documentElement.lang, so a shell that dropped its language or title
// would still sweep clean. Nothing else checks either fact.
Expand Down
Loading