Skip to content

Commit a72b6a8

Browse files
authored
Merge pull request #436 from webstackdev/infrastructure/implement-e2e-tests
Infrastructure/implement e2e tests
2 parents eea9a77 + b58a8ea commit a72b6a8

251 files changed

Lines changed: 15187 additions & 8966 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/instructions/general.instructions.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ applyTo: "**"
3535
- JavaScript loading warnings from happy-dom are silenced in vitest.setup.ts for clean test output.
3636
- A working example test using the Container API is available at /home/kevin/Repos/Webstack Builders/Corporate Website/astro.webstackbuilders.com/src/components/Test/container.spec.ts
3737
- **NEVER hard-code content slugs in e2e tests** (e.g., `/articles/typescript-best-practices`, `/services/web-development`). Content can be deleted or renamed. Always dynamically fetch the first available item from listing pages (articles, services, case-studies, etc.) and navigate to it. This prevents test breakage when content changes.
38-
- **Playwright E2E Tests**: Set `DEBUG=1` environment variable to prevent the dev server from being launched by the Playwright test runner. This is useful when you want to run tests against an already running dev server.
38+
- **Playwright E2E Tests**: ALWAYS run with `DEBUG=1` environment variable (e.g., `DEBUG=1 npx playwright test`). This prevents the Playwright test runner from launching its own dev server. The user maintains a running dev server for development.
39+
- **NEVER run the full e2e test suite** unless explicitly requested by the user. The full suite is very resource intensive and takes over 10 minutes to run. Only run specific e2e test files when verification is needed (e.g., `DEBUG=1 npx playwright test test/e2e/specific-file.spec.ts`).
40+
- **NEVER start a dev server yourself**. The user runs their own dev server for development. When you need a dev server running, notify the user instead of starting one.
3941

4042
# Personality
4143
- Do not apologize

.github/workflows/build-and-test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ name: CI - Build & Test
33

44
on:
55
push:
6-
branches: [main]
76
pull_request:
87
branches: [main]
98

@@ -25,6 +24,9 @@ jobs:
2524
- name: Install dependencies
2625
run: npm ci
2726

27+
- name: Run TypeScript check
28+
run: npm run check
29+
2830
- name: Run lint
2931
run: npm run lint
3032

.github/workflows/type-check.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Fast code quality checks (TypeScript + Linting)
2+
name: Code Quality Check
3+
4+
on:
5+
push:
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
quality-check:
11+
name: Code Quality Check
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout repository
16+
uses: actions/checkout@v4
17+
18+
- name: Setup Node.js
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version: "22.x"
22+
cache: 'npm'
23+
24+
- name: Install dependencies
25+
run: npm ci
26+
27+
- name: Run TypeScript check
28+
run: npm run check
29+
30+
- name: Run linting
31+
run: npm run lint

.husky/pre-commit

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
11
#!/bin/sh
22

3+
# Load nvm if available and use appropriate node version
4+
if [ -f "$HOME/.nvm/nvm.sh" ]; then
5+
. "$HOME/.nvm/nvm.sh"
6+
# Try different nvm use strategies in order of preference
7+
if nvm use 2>/dev/null; then
8+
echo "Using current nvm node version"
9+
elif nvm use node 2>/dev/null; then
10+
echo "Using latest nvm node version"
11+
elif nvm use --lts 2>/dev/null; then
12+
echo "Using LTS node version"
13+
else
14+
echo "Using system node version"
15+
fi
16+
fi
17+
18+
# Run TypeScript check (fast feedback on type errors)
19+
npm run check
20+
321
# Run unit tests (fast feedback)
4-
nvm use default && npm run test:unit
22+
npm run test:unit
523

624
# Verify branch naming convention
725
.husky/scripts/check-branch-name.sh

.vscode/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"Flink",
3232
"FNAME",
3333
"fosstodon",
34+
"glidejs",
3435
"GSAP",
3536
"hocho",
3637
"Hudi",
@@ -67,9 +68,12 @@
6768
"Qualys",
6869
"repost",
6970
"reposts",
71+
"RGAA",
7072
"Ryuk",
73+
"samp",
7174
"SCORM",
7275
"shiki",
76+
"shikijs",
7377
"shipit",
7478
"SIEM",
7579
"signup",

README.md

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -143,58 +143,7 @@ To add a new theme (e.g., a holiday theme), follow these steps:
143143

144144
#### 1. Add CSS Variables in `src/styles/themes.css`
145145

146-
Add a new CSS rule with your theme's custom properties:
147-
148-
```css
149-
/* Holiday Theme Example */
150-
[data-theme="holiday"] {
151-
/* Background Colors */
152-
--color-bg: #0f172a;
153-
--color-bg-offset: #1e293b;
154-
155-
/* Text Colors */
156-
--color-text: #f1f5f9;
157-
--color-text-offset: #cbd5e1;
158-
159-
/* Primary Brand Colors */
160-
--color-primary: #dc2626;
161-
--color-primary-offset: #991b1b;
162-
--color-primary-bg: #7f1d1d;
163-
--color-primary-bg-hover: #991b1b;
164-
--color-primary-hover: #b91c1c;
165-
166-
/* Secondary Colors */
167-
--color-secondary: #16a34a;
168-
--color-secondary-offset: #15803d;
169-
--color-secondary-bg: #052e16;
170-
171-
/* Status Colors */
172-
--color-success: #16a34a;
173-
--color-success-offset: #22c55e;
174-
--color-success-bg: #052e16;
175-
176-
--color-info: #0891b2;
177-
--color-info-bg: #164e63;
178-
179-
--color-warning: #a16207;
180-
--color-warning-offset: #ca8a04;
181-
--color-warning-bg: #451a03;
182-
183-
--color-danger: #dc2626;
184-
--color-danger-bg: #7f1d1d;
185-
186-
/* Special Colors */
187-
--color-twitter: #1da1f2;
188-
--color-modal-background: #0f172a;
189-
190-
/* Accent Colors */
191-
--color-accent: #fbbf24;
192-
--color-accent-bg: #451a03;
193-
194-
/* Syntax Highlighting */
195-
--shiki-theme: 'github-dark';
196-
}
197-
```
146+
Add a new CSS rule with the theme's custom colors following the pattern of existing themes in this file.
198147

199148
#### 2. Register Theme in `src/lib/themes.ts`
200149

THEME_SYSTEM_WIP.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Theme System - Work in Progress
2+
3+
## Current Status
4+
5+
### What's Working
6+
- ✅ Theme picker tests: 9/10 @ready (63 tests passing across 7 browsers)
7+
- ✅ Manual theme selection and persistence works correctly
8+
- ✅ Theme switching via theme picker UI works
9+
- ✅ View Transitions correctly maintain theme across page navigations
10+
- ✅ CSS architecture refactored: `@theme inline` uses `var()` references instead of hard-coded values
11+
12+
### What's Broken
13+
-**System preference (prefers-color-scheme) not respected on first visit in real browser**
14+
- Test passes but real usage fails
15+
- Opening site in new incognito window with dark mode preference shows light theme
16+
- Google.com correctly shows dark, but our site doesn't
17+
18+
-**Theme picker buttons should show their own theme's colors**
19+
- Dark theme button should use `--dark-color-*` variables
20+
- Default theme button should use `--light-color-*` variables
21+
- Currently all buttons use light theme colors (partially fixed but needs completion)
22+
23+
## Root Cause Analysis
24+
25+
### System Preference Issue
26+
27+
The problem is a **race condition** between:
28+
1. HEAD inline script (synchronous) - correctly sets `data-theme="dark"` based on `prefers-color-scheme`
29+
2. `persistentAtom` restore (asynchronous) - overwrites theme back to 'default'
30+
31+
**Sequence of events:**
32+
```
33+
1. HEAD script runs → checks localStorage (empty) → checks prefersDark=true → sets data-theme="dark" ✓
34+
2. persistentAtom initializes with default value 'default'
35+
3. Our init code runs with setTimeout(100ms)
36+
4. persistentAtom's restore() completes (async) → fires .listen() → overwrites to 'default' ✗
37+
```
38+
39+
**Current fix attempt:**
40+
- Using `isInitialized` flag to prevent `.listen()` from applying themes until init completes
41+
- Using `setTimeout(100ms)` to delay init until after `persistentAtom.restore()` completes
42+
- **Problem:** The timing is unreliable - 100ms might not be enough on slower devices
43+
44+
**Test vs Reality:**
45+
- Playwright test passes because it's using `emulateMedia({ colorScheme: 'dark' })`
46+
- Real browser behavior is different - the race condition manifests differently
47+
- Test needs to be improved to catch this real-world bug
48+
49+
## Files Modified
50+
51+
### Theme Initialization
52+
- `src/components/Scripts/state/store/themes.ts` (lines 127-180)
53+
- Changed from `.subscribe()` to `.listen()` to avoid immediate firing
54+
- Added `isInitialized` flag to gate theme applications
55+
- Added `setTimeout(100)` to wait for `persistentAtom.restore()`
56+
- **HAS DEBUG LOGGING** - needs to be removed before commit
57+
58+
### Theme Picker UI
59+
- `src/components/ThemePicker/Themes.astro` (lines 97-120)
60+
- **NOT YET FIXED** - still needs to map theme.id to color prefix
61+
- Should use `--${colorPrefix}-color-*` variables per button
62+
63+
### HEAD Script
64+
- `src/components/Head/index.astro` (lines 56-63)
65+
- Correctly checks `prefers-color-scheme` and sets `data-theme`
66+
- Logic: stored theme (if not 'default') > system preference > 'default'
67+
68+
### CSS Architecture
69+
- `src/styles/themes.css`
70+
- ✅ Lines 65-105: `@theme inline` refactored to use `var()` references
71+
- ✅ All theme-specific colors defined at `:root` level
72+
- Has `--light-color-*`, `--dark-color-*`, and base `--color-*` variables
73+
74+
## Next Steps
75+
76+
### High Priority
77+
1. **Fix system preference detection**
78+
- Option A: Find more reliable way to detect when `persistentAtom.restore()` completes
79+
- Option B: Use `MutationObserver` to watch for theme changes from restore
80+
- Option C: Initialize theme BEFORE importing `persistentAtom`
81+
- Option D: Use regular `atom` for store, manually sync to localStorage after restore completes
82+
- Option E: Don't rely on setTimeout - use `requestIdleCallback` or similar
83+
84+
2. **Fix theme picker button colors**
85+
- Complete the Themes.astro fix to show each theme's own colors
86+
- Map `theme.id` to color variable prefix: 'default' → 'light', 'dark' → 'dark'
87+
- Update color swatches to use theme-specific variables
88+
89+
3. **Remove debug logging**
90+
- `src/components/Scripts/state/store/themes.ts` has console.log statements
91+
- Clean these up before final commit
92+
93+
### Test Improvements
94+
4. **Make test match real browser behavior**
95+
- Current test uses `emulateMedia()` which might not trigger same race condition
96+
- Consider testing with actual localStorage clearing and page reload
97+
- Add test that validates theme immediately on page load (before JS runs)
98+
99+
## Technical Constraints
100+
101+
- **MUST use `persistentAtom`** - required for View Transitions to maintain theme across navigations
102+
- **CANNOT use regular `atom`** - will lose persistence across page navigations
103+
- HEAD script must run synchronously to prevent FOUC (Flash of Unstyled Content)
104+
- Theme must be applied before page renders (critical for UX)
105+
106+
## Code Locations
107+
108+
- Theme store: `src/components/Scripts/state/store/themes.ts`
109+
- Theme picker UI: `src/components/ThemePicker/Themes.astro`
110+
- Theme picker element: `src/components/ThemePicker/theme-picker-element.ts`
111+
- HEAD script: `src/components/Head/index.astro` (lines 56-63)
112+
- CSS themes: `src/styles/themes.css`
113+
- E2E tests: `test/e2e/specs/04-components/theme-picker.spec.ts` (line 134 is failing test)
114+
115+
## Questions to Answer
116+
117+
1. When exactly does `persistentAtom.restore()` complete?
118+
2. Is there an event or promise we can wait for?
119+
3. Should we implement our own localStorage persistence instead of using `persistentAtom`?
120+
4. Can we leverage the `@media (prefers-color-scheme: dark)` CSS to avoid needing JS for system preference?
121+
122+
## Useful Context
123+
124+
- The `@media (prefers-color-scheme: dark)` CSS rule at lines 337-373 in themes.css correctly applies dark theme
125+
- This CSS works WITHOUT JavaScript
126+
- The issue is the JS is overriding this CSS by setting `data-theme="default"`
127+
- Maybe we should NOT set `data-theme` at all when using system preference?

TODO.md

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,75 @@
11
# TODO
22

3-
From the error output, the article page has:
4-
5-
<h1 id="article-title"> - the actual article title (correct)
6-
<h1 id="create-custom-font-sets-use-font-forge"> - from markdown content (wrong!)
7-
<h1>No islands detected.</h1> - from some debug/dev tool
8-
<h1>Audit</h1> - from some debug/dev tool
9-
<h1>No accessibility or performance issues detected.</h1> - from debug/dev tool
10-
<h1>Settings</h1> - from debug/dev tool
3+
Files with Skipped Tests:
4+
5+
social-shares.spec.ts - 12 @wip
6+
gdpr-consent.spec.ts - 10 @wip
7+
8+
Blocked Categories (44 tests):
9+
10+
Visual regression testing (18) - Needs Percy/Chromatic
11+
PWA functionality (12) - Service workers not implemented
12+
Lighthouse audits (6) - Integration pending
13+
Newsletter double opt-in (6) - Email testing infrastructure
14+
Axe accessibility (2) - axe-core integration
15+
16+
\[color:var\(--color-(.*?)\)\]
17+
18+
## Axe tags
19+
20+
cat.aria: Rules related to Accessible Rich Internet Applications (ARIA) attributes and roles.
21+
cat.color: Rules related to color contrast and meaning conveyed by color.
22+
cat.controls: Rules for interactive controls, such as form elements and links.
23+
cat.forms: Rules specifically for forms, form fields, and their labels.
24+
cat.keyboard: Rules related to keyboard operability.
25+
cat.links: Rules for links, including their names and destinations.
26+
cat.name-role-value: Rules that check if an element has a name, role, and value that can be correctly interpreted by assistive technologies.
27+
cat.semantics: Rules related to the semantic structure of a document, such as headings and landmarks.
28+
cat.sensory-and-visual-cues: Rules that deal with information conveyed by sensory or visual characteristics.
29+
cat.structure: Rules related to the document's overall structure, like the proper nesting of elements.
30+
cat.tables: Rules for data tables, including headers and associations.
31+
cat.text-alternatives: Rules for ensuring that text alternatives are provided for non-text content, such as images.
32+
33+
## Social Media Preview Cards
34+
35+
Looking at the social-card endpoint implementation, it's designed to work with third-party screenshot services, not the social networks themselves.
36+
37+
Here's how it works:
38+
39+
The Two Formats
40+
HTML format (format=html or default): Returns a full HTML page with inline CSS styled as a 1200x630px card - the standard Open Graph image dimensions.
41+
42+
OG format (format=og): Returns JSON with Open Graph meta tags, where the og:image URL points back to the HTML version of the card.
43+
44+
How Social Networks Actually Work
45+
Social networks like Twitter, Facebook, LinkedIn, etc. don't screenshot HTML pages. They expect:
46+
47+
- Direct image URLs (PNG, JPEG, etc.)
48+
- Standard dimensions (1200x630px for most platforms)
49+
50+
The Intended Workflow
51+
52+
This endpoint is designed to integrate with screenshot services like:
53+
54+
- Puppeteer or Playwright - Run your own screenshot service
55+
- Vercel OG Image Generation - Vercel's built-in service
56+
- Cloudinary - Can fetch and screenshot URLs
57+
- ScreenshotOne or ApiFlash - Dedicated screenshot APIs
58+
- Satori - Convert HTML/CSS to SVG/PNG
59+
60+
Current Limitation
61+
62+
As implemented, this endpoint would need an additional step to be useful for social sharing:
63+
64+
Your endpoint → Screenshot service → Image file → Social networks
65+
66+
Better Approaches
67+
68+
For a production Astro site, you'd typically:
69+
70+
- Use @vercel/og or Satori to generate actual images server-side
71+
- Pre-generate images at build time for static content
72+
- Use a screenshot service that can be called from your endpoint to return actual images
1173

1274
## @TODO: Use Confetti on CTA forms
1375

0 commit comments

Comments
 (0)