Skip to content

Commit 8382797

Browse files
authored
CI: test PRs; fix midnight-flaky forecastLabel test (#15)
* fix: pin forecastLabel test fixtures away from midnight hoursFromNow(1)/(3) used the real wall clock, so the "still today" cases intermittently rolled into the next calendar day (UTC, as on the GH Actions runner) and forecastLabel correctly added a weekday the assertions didn't expect. Failed the post-merge deploy on flip. Reproduced by pinning system time to 23:30 UTC (matches the CI failure exactly), fixed by pinning it to noon UTC instead so the fixtures can't cross midnight regardless of when or where the suite runs. * ci: run lint + tests on PRs, not only on push to main PR #14 merged with mergeStateStatus CLEAN and zero checks: static.yml only triggered on push to main, so nothing ran against the PR branch itself. The break it introduced (forecastLabel test fixtures crossing a UTC midnight) was caught by the post-merge deploy job instead, after landing on main. Split into a test job (push + pull_request, no deploy secrets needed) and a deploy job (needs: test, push-only) so a PR can't merge past a red test run again. Pinned every action in the file to its commit SHA while touching it, per repo convention.
1 parent 5eb78ba commit 8382797

2 files changed

Lines changed: 40 additions & 9 deletions

File tree

.github/workflows/static.yml

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ on:
66
push:
77
branches: ["main"]
88

9+
# Also test-only on PRs targeting main, so a break is caught before merge
10+
pull_request:
11+
branches: ["main"]
12+
913
# Allows you to run this workflow manually from the Actions tab
1014
workflow_dispatch:
1115

@@ -22,36 +26,51 @@ concurrency:
2226
cancel-in-progress: false
2327

2428
jobs:
25-
# Single deploy job since we're just deploying
29+
# Lint + test: runs on every push and every PR against main.
30+
test:
31+
runs-on: ubuntu-latest
32+
steps:
33+
- name: Checkout
34+
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
35+
- name: Use Node.js
36+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
37+
with:
38+
node-version: 24
39+
cache: 'npm'
40+
- run: npm install
41+
- run: npm run lint
42+
- run: npm test
43+
44+
# Build + deploy: only for pushes to main, and only once tests pass.
2645
deploy:
46+
needs: test
47+
if: github.event_name == 'push'
2748
environment:
2849
name: github-pages
2950
url: ${{ steps.deployment.outputs.page_url }}
3051
runs-on: ubuntu-latest
3152
steps:
3253
- name: Checkout
33-
uses: actions/checkout@v4
54+
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
3455
- name: Setup Pages
35-
uses: actions/configure-pages@v5
56+
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
3657
- name: Use Node.js
37-
uses: actions/setup-node@v4
58+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
3859
with:
3960
node-version: 24
4061
cache: 'npm'
4162
- run: npm install
42-
- run: npm run lint
43-
- run: npm test
4463
- run: node scripts/inject-ga.js
4564
env:
4665
GA_ID: ${{ secrets.GA_ID }}
4766
- run: npm run build --if-present
4867
env:
4968
VITE_GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
5069
- name: Upload artifact
51-
uses: actions/upload-pages-artifact@v3
70+
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
5271
with:
5372
# Upload entire repository
5473
path: 'build'
5574
- name: Deploy to GitHub Pages
5675
id: deployment
57-
uses: actions/deploy-pages@v4
76+
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5

src/components/WindsComponent.test.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// @vitest-environment jsdom
22
import { fireEvent, render, screen } from '@testing-library/react';
33
import React from 'react';
4-
import { beforeEach, describe, expect, it, vi } from 'vitest';
4+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
55

66
import { AppStateProvider } from '../hooks/useAppState';
77
import { SOURCE_MANUAL, createWindProfile, createWindRow } from '../core/wind';
@@ -151,6 +151,18 @@ function hoursFromNow(hours: number): Date {
151151
}
152152

153153
describe('forecastLabel', () => {
154+
// Pinned mid-day (not near a UTC midnight rollover, which real wall-clock
155+
// runs hit intermittently — hoursFromNow(1)/(3) would tip into the next
156+
// calendar day and pick up a weekday the "today" cases don't expect).
157+
beforeEach(() => {
158+
vi.useFakeTimers();
159+
vi.setSystemTime(new Date('2026-08-14T12:00:00Z'));
160+
});
161+
162+
afterEach(() => {
163+
vi.useRealTimers();
164+
});
165+
154166
it('says Now rather than an offset of zero', () => {
155167
expect(forecastLabel(null, 0)).toBe('Now');
156168
});

0 commit comments

Comments
 (0)