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
45 changes: 45 additions & 0 deletions .github/workflows/release-qa-browsers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Throughline release QA browsers

# Additional, read-only release-candidate verification. The regular CI
# retains Chromium and the distributable/consumer checks.
on:
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: throughline-release-browser-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
cross-browser:
name: Browser regressions (${{ matrix.browser }})
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
browser: [firefox, webkit]
steps:
- name: Checkout source
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install locked dependencies
run: pnpm install --frozen-lockfile
- name: Verify lockfile unchanged
run: git diff --exit-code -- pnpm-lock.yaml
- name: Install tested browser and system dependencies
run: pnpm exec playwright install --with-deps ${{ matrix.browser }}
- name: Run the complete browser regression suite
env:
THROUGHLINE_QA_BROWSER: ${{ matrix.browser }}
run: pnpm test:browser:run
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Semantic Versioning independently of the version-1 trace and program schemas.

## Unreleased

### Fixed (cross-browser toolbar)

- Keep the wide playback toolbar compact in WebKit without constraining native selector height; verify the compact bar still encloses every control across browser engines.

### Fixed (narration review)

- Coordinate browser-global speech synthesis between multiple Throughline players; newer narration takes over while displaced players pause and stop owning cancellation.
Expand Down
17 changes: 15 additions & 2 deletions src/react/__tests__/toolbar.browser.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,23 @@ it("forms one aligned compact toolbar on wide screens and adapts by container wi
expect(Math.abs(centerY(chapter) - centerY(entity))).toBeLessThan(3);
expect(Math.abs(centerY(chapter) - centerY(play))).toBeLessThan(3);
expect(Math.abs(centerY(chapter) - centerY(timeline))).toBeLessThan(3);
expect(bottom.getBoundingClientRect().height).toBeLessThan(55);
const toolbarBounds = bottom.getBoundingClientRect();
expect(toolbarBounds.height).toBeLessThan(55);
// A compact bar must still enclose native form controls in every engine.
for (const control of bottom.querySelectorAll<HTMLElement>("button, select, input")) {
const rect = control.getBoundingClientRect();
const name = control.getAttribute("aria-label") ?? control.tagName;
expect(rect.top, name + " escapes toolbar top").toBeGreaterThanOrEqual(toolbarBounds.top - 1);
expect(rect.bottom, name + " escapes toolbar bottom").toBeLessThanOrEqual(toolbarBounds.bottom + 1);
}
expect(zoom.getBoundingClientRect().width).toBe(34);
expect(getComputedStyle(zoom.querySelector("svg")!).width).toBe("14px");
expect(chapter.getBoundingClientRect().height).toBe(34);
// Native select widgets are 34px in Chromium/Firefox and 42px in WebKit.
// Constrain the allowable size while the toolbar-height and bounds checks
// above enforce the actual compact, unclipped layout contract.
const chapterHeight = chapter.getBoundingClientRect().height;
expect(chapterHeight).toBeGreaterThanOrEqual(34);
expect(chapterHeight).toBeLessThanOrEqual(42);
expect(getComputedStyle(chapter).borderTopLeftRadius).toBe("2px");
expect(getComputedStyle(chapter).paddingLeft).toBe("8px");

Expand Down
3 changes: 2 additions & 1 deletion src/styles/throughline.css
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@
column-gap: 0.75rem;
row-gap: 0.375rem;
min-width: 0;
padding-block: 0.375rem;
/* Preserve native select height (notably WebKit) within the compact bar. */
padding-block: 0.25rem;
border-top: 1px solid var(--thl-line);
border-bottom: 1px solid var(--thl-line);
}
Expand Down
10 changes: 9 additions & 1 deletion vitest.browser.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { playwright } from "@vitest/browser-playwright";
import { defineConfig } from "vitest/config";

// Main quality CI uses Chromium. The separate release QA workflow exercises
// the identical browser suite in Firefox and WebKit without changing defaults.
const requestedBrowser = process.env.THROUGHLINE_QA_BROWSER ?? "chromium";
if (!["chromium", "firefox", "webkit"].includes(requestedBrowser)) {
throw new Error("Unsupported Throughline QA browser: " + requestedBrowser);
}
const browser = requestedBrowser as "chromium" | "firefox" | "webkit";

export default defineConfig({
test: {
css: true,
Expand All @@ -9,7 +17,7 @@ export default defineConfig({
browser: {
enabled: true,
provider: playwright(),
instances: [{ browser: "chromium" }],
instances: [{ browser }],
},
},
});
Loading