Skip to content

Commit 8978253

Browse files
authored
Merge branch 'main' into copilot/feat-add-pdf-powerpoint-export
2 parents 5f7e291 + 092e889 commit 8978253

3 files changed

Lines changed: 74 additions & 9 deletions

File tree

‎.github/workflows/e2e.yml‎

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
---
22
name: E2E
33

4-
# Runs the Playwright end-to-end + mobile/responsive suite across Chromium,
4+
# Runs the Playwright end-to-end + mobile/responsive suite. To keep PR feedback
5+
# fast, pull requests run only the Chromium engine (desktop + emulated mobile);
6+
# pushes to main and manual runs exercise the full matrix across Chromium,
57
# Firefox and WebKit (desktop) plus emulated mobile devices. Unit/component
68
# tests (Vitest) run in the Pages workflow; this workflow focuses on real
79
# browser flows. See playwright.config.js for projects and the dev web server.
@@ -49,20 +51,66 @@ jobs:
4951
- name: Install dependencies
5052
run: npm ci
5153

54+
- name: Determine browser scope
55+
id: scope
56+
# PRs validate against the Chromium engine only (desktop + mobile-chrome)
57+
# for fast feedback; main / manual runs cover the full browser matrix.
58+
run: |-
59+
if [ "${{ github.event_name }}" = "pull_request" ]; then
60+
{
61+
echo "browsers=chromium"
62+
echo "projects=--project=chromium --project=mobile-chrome"
63+
echo "label=chromium"
64+
} >> "$GITHUB_OUTPUT"
65+
else
66+
{
67+
echo "browsers=chromium firefox webkit"
68+
echo "projects="
69+
echo "label=all"
70+
} >> "$GITHUB_OUTPUT"
71+
fi
72+
73+
- name: Resolve Playwright version
74+
id: playwright-version
75+
# Key the cache on the resolved Playwright version (stable across
76+
# lockfile churn) rather than hashFiles(package-lock.json).
77+
run: |-
78+
version=$(node -p "require('./package-lock.json').packages['node_modules/@playwright/test'].version")
79+
echo "version=$version" >> "$GITHUB_OUTPUT"
80+
5281
- name: Cache Playwright browsers
5382
id: playwright-cache
5483
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
5584
with:
5685
path: ~/.cache/ms-playwright
57-
key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
58-
restore-keys: |-
59-
playwright-${{ runner.os }}-
86+
key: >-
87+
playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}-${{
88+
steps.scope.outputs.label }}
6089
6190
- name: Install Playwright browsers
62-
run: npx playwright install --with-deps
91+
if: steps.playwright-cache.outputs.cache-hit != 'true'
92+
env:
93+
BROWSERS: ${{ steps.scope.outputs.browsers }}
94+
run: |-
95+
# shellcheck disable=SC2086 # intentional word splitting into args
96+
npx playwright install $BROWSERS --with-deps
97+
98+
- name: Install Playwright system dependencies
99+
# Browser binaries are cached, but apt system libraries are not persisted
100+
# across ephemeral runners, so refresh them on a cache hit.
101+
if: steps.playwright-cache.outputs.cache-hit == 'true'
102+
env:
103+
BROWSERS: ${{ steps.scope.outputs.browsers }}
104+
run: |-
105+
# shellcheck disable=SC2086 # intentional word splitting into args
106+
npx playwright install-deps $BROWSERS
63107
64108
- name: Run Playwright tests
65-
run: npm run test:e2e
109+
env:
110+
PROJECTS: ${{ steps.scope.outputs.projects }}
111+
run: |-
112+
# shellcheck disable=SC2086 # intentional word splitting into args
113+
npm run test:e2e -- $PROJECTS
66114
67115
- name: Upload Playwright report
68116
if: ${{ !cancelled() }}

‎playwright.config.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default defineConfig({
1212
fullyParallel: true,
1313
forbidOnly: !!process.env.CI,
1414
retries: process.env.CI ? 2 : 0,
15-
workers: process.env.CI ? 1 : undefined,
15+
workers: process.env.CI ? 2 : undefined,
1616
reporter: process.env.CI
1717
? [['html', { open: 'never' }], ['github'], ['list']]
1818
: [['html', { open: 'never' }], ['list']],

‎src/components/MeasureDetailPanel.jsx‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useEffect, useRef } from 'react';
12
import { t } from '../i18n/strings.js';
23
import {
34
localized,
@@ -7,10 +8,26 @@ import {
78
} from '../data/grip.js';
89
import LicenseBadge from './LicenseBadge.jsx';
910

11+
// Breakpoint at which the layout switches to a single column (matches CSS).
12+
const MOBILE_BREAKPOINT = 1080;
13+
1014
export default function MeasureDetailPanel({ measure, lang, onClose }) {
15+
const panelRef = useRef(null);
16+
17+
useEffect(() => {
18+
if (
19+
measure &&
20+
panelRef.current &&
21+
typeof panelRef.current.scrollIntoView === 'function' &&
22+
window.innerWidth <= MOBILE_BREAKPOINT
23+
) {
24+
panelRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
25+
}
26+
}, [measure]);
27+
1128
if (!measure) {
1229
return (
13-
<aside className="detail detail--empty" aria-live="polite">
30+
<aside ref={panelRef} className="detail detail--empty" aria-live="polite">
1431
<h2 className="detail__empty-title">{t(lang, 'selectMeasure')}</h2>
1532
<p className="detail__empty-hint">{t(lang, 'selectMeasureHint')}</p>
1633
</aside>
@@ -26,7 +43,7 @@ export default function MeasureDetailPanel({ measure, lang, onClose }) {
2643
measure.type === 'T' ? t(lang, 'technical') : t(lang, 'organisational');
2744

2845
return (
29-
<aside className="detail" aria-live="polite">
46+
<aside ref={panelRef} className="detail" aria-live="polite">
3047
<header className="detail__head">
3148
<div className="detail__head-meta">
3249
<span className="detail__code">{measure.code}</span>

0 commit comments

Comments
 (0)