Skip to content

Commit 7f6f70b

Browse files
authored
Merge pull request #43 from szolkowski/feature/wave-3-tests-and-ci
Add accessibility and JSON-LD schema validation tests
2 parents ada3773 + a73c32d commit 7f6f70b

14 files changed

Lines changed: 4367 additions & 414 deletions

.github/workflows/ci.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ jobs:
9999
- name: Run UI tests
100100
id: ui_tests
101101
run: npm test
102+
env:
103+
# GitHub Actions sets $HOME=/github/home (uid 1001), but the
104+
# Playwright container runs as root — firefox refuses to launch
105+
# under a $HOME it doesn't own. /root is owned by the running
106+
# user, satisfies firefox, and chromium/webkit don't care.
107+
HOME: /root
102108
- name: Upload Playwright report
103109
id: upload_report
104110
if: always() && steps.ui_tests.conclusion != 'skipped'
@@ -123,6 +129,73 @@ jobs:
123129
header: ui-tests
124130
path: /tmp/ui-test-summary.md
125131

132+
# Lighthouse CI (PRs only). Runs against the freshly-built site and asserts
133+
# against budgets in lighthouserc.json. Reuses the Playwright container
134+
# because it already ships Chrome + Node 20+ (lhci 0.15 needs both).
135+
lighthouse-ci:
136+
if: github.event_name == 'pull_request'
137+
runs-on: ubuntu-latest
138+
container:
139+
image: mcr.microsoft.com/playwright:v1.59.1-jammy
140+
steps:
141+
- name: Checkout
142+
uses: actions/checkout@v4
143+
- name: Install Ruby runtime + build deps
144+
run: |
145+
apt-get update -qq
146+
apt-get install -y -qq --no-install-recommends \
147+
libyaml-0-2 \
148+
build-essential \
149+
libssl-dev
150+
- name: Setup Ruby
151+
uses: ruby/setup-ruby@086ffb1a2090c870a3f881cc91ea83aa4243d408 # v1.195.0
152+
with:
153+
ruby-version: '3.1'
154+
bundler-cache: true
155+
cache-version: 0
156+
- name: Build site
157+
run: bundle exec jekyll build
158+
env:
159+
JEKYLL_ENV: production
160+
- name: Install npm deps
161+
run: npm ci
162+
- name: Run Lighthouse CI
163+
id: lhci
164+
# The Playwright image ships chromium at /ms-playwright/chromium-*/...
165+
# rather than /usr/bin/google-chrome, so chrome-launcher (used by lhci)
166+
# can't auto-detect it. Resolve the binary via the playwright Node API
167+
# and pass it through as CHROME_PATH.
168+
run: |
169+
export CHROME_PATH="$(node -e 'console.log(require("playwright").chromium.executablePath())')"
170+
echo "Using Chrome at: $CHROME_PATH"
171+
npx lhci autorun --config=lighthouserc.json
172+
env:
173+
# Optional — set this secret to post lhci status checks via the
174+
# Lighthouse CI GitHub App. Without it, lhci runs but skips the
175+
# status-check post.
176+
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
177+
- name: Upload Lighthouse reports
178+
id: upload_lhci
179+
if: always() && steps.lhci.conclusion != 'skipped'
180+
uses: actions/upload-artifact@v4
181+
with:
182+
name: lighthouse-reports
183+
path: .lighthouseci/
184+
retention-days: 14
185+
- name: Generate Lighthouse summary
186+
if: always() && steps.lhci.conclusion != 'skipped'
187+
env:
188+
ARTIFACT_URL: ${{ steps.upload_lhci.outputs.artifact-url }}
189+
run: |
190+
node scripts/ci-lighthouse-summary.mjs > /tmp/lighthouse-summary.md
191+
cat /tmp/lighthouse-summary.md >> "$GITHUB_STEP_SUMMARY"
192+
- name: Post Lighthouse comment on PR
193+
if: always() && github.event_name == 'pull_request' && steps.lhci.conclusion != 'skipped'
194+
uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.0
195+
with:
196+
header: lighthouse
197+
path: /tmp/lighthouse-summary.md
198+
126199
# Publishes the Pages artifact from build-pages. Runs only on master pushes.
127200
deploy-pages:
128201
environment:

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ vendor
99
.DS_Store
1010
node_modules/
1111
playwright-report/
12-
test-results/
12+
test-results/
13+
.lighthouseci/

Gemfile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ source "https://rubygems.org"
88
# This will help ensure the proper Jekyll version is running.
99
# Happy Jekylling!
1010
gem "jekyll", "~> 4.3.3"
11-
gem "minima", "~> 2.5"
12-
# This is the default theme for new Jekyll sites. You may change this to anything you like.
13-
# gem "minima", "~> 2.5"
11+
# Theme is pulled via remote_theme: pages-themes/architect (see _config.yml);
12+
# no `gem "<theme>"` line is needed.
1413
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
1514
# uncomment the line below. To upgrade, run `bundle update github-pages`.
1615
# gem "github-pages", group: :jekyll_plugins

Gemfile.lock

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,6 @@ GEM
6262
rb-fsevent (~> 0.10, >= 0.10.3)
6363
rb-inotify (~> 0.9, >= 0.9.10)
6464
mercenary (0.4.0)
65-
minima (2.5.1)
66-
jekyll (>= 3.5, < 5.0)
67-
jekyll-feed (~> 0.9)
68-
jekyll-seo-tag (~> 2.1)
6965
pathutil (0.16.2)
7066
forwardable-extended (~> 2.6)
7167
public_suffix (5.0.5)
@@ -104,7 +100,6 @@ DEPENDENCIES
104100
jekyll-remote-theme
105101
jekyll-seo-tag (~> 2.8.0)
106102
jekyll-sitemap
107-
minima (~> 2.5)
108103
tzinfo (~> 1.2)
109104
tzinfo-data
110105
wdm (~> 0.1.1)

_includes/_header.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<a class="skip-link" href="#main-content">Skip to main content</a>
12
<header>
23
<div class="inner">
34
<nav class="site-nav" aria-label="Main navigation">

assets/css/custom-styles.scss

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,38 @@
22
---
33

44
@import "{{ site.theme }}";
5+
6+
// Skip-to-main-content link — visually hidden until keyboard-focused so
7+
// screen-reader and keyboard users can bypass the site nav on every page.
8+
.skip-link {
9+
position: absolute;
10+
left: -9999px;
11+
top: 0;
12+
z-index: 9999;
13+
padding: 0.5rem 1rem;
14+
background: #2879d0;
15+
color: #fff;
16+
text-decoration: none;
17+
font-weight: bold;
18+
}
19+
20+
.skip-link:focus {
21+
left: 0;
22+
}
23+
24+
// Uniform :focus-visible ring on interactive elements. currentColor adapts to
25+
// the surrounding text colour (dark ring on light backgrounds, light ring on
26+
// the dark hero), which keeps WCAG 2.1 AA contrast everywhere.
27+
a:focus-visible,
28+
button:focus-visible,
29+
input:focus-visible,
30+
select:focus-visible,
31+
textarea:focus-visible,
32+
[tabindex]:focus-visible {
33+
outline: 2px solid currentColor;
34+
outline-offset: 2px;
35+
}
36+
537
ul.share-buttons{
638
list-style: none;
739
padding: 0;

lighthouserc.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"ci": {
3+
"collect": {
4+
"staticDistDir": "_site",
5+
"url": [
6+
"http://localhost/",
7+
"http://localhost/about/",
8+
"http://localhost/2026/04/13/optipowertools-hangfire-2-0-cms-13-support/",
9+
"http://localhost/2026/03/03/catalog-traversal-with-hangfire-part-3-advanced-job-management/",
10+
"http://localhost/2026/04/09/optimizely-alloy-on-macos-apple-silicon/",
11+
"http://localhost/tags/"
12+
],
13+
"numberOfRuns": 1,
14+
"settings": {
15+
"preset": "desktop",
16+
"chromeFlags": "--no-sandbox --disable-dev-shm-usage --disable-gpu"
17+
}
18+
},
19+
"assert": {
20+
"assertions": {
21+
"categories:performance": ["warn", { "minScore": 0.9 }],
22+
"categories:accessibility": ["error", { "minScore": 0.95 }],
23+
"categories:best-practices": ["warn", { "minScore": 0.9 }],
24+
"categories:seo": ["error", { "minScore": 0.95 }]
25+
}
26+
},
27+
"upload": {
28+
"target": "temporary-public-storage"
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)