Skip to content

Commit aeca068

Browse files
committed
test: Add CSP violation detection test
- Listens for console CSP warnings and blocked requests - Catches img-src/script-src/connect-src misconfigurations - All 7 build-validation tests pass
1 parent 80403a3 commit aeca068

2 files changed

Lines changed: 55 additions & 0 deletions

File tree

changelogs/CHANGELOG-csp-test.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# CSP Violation Test
2+
3+
- Added `no CSP violations on page load` test to `build-validation.spec.js`
4+
- Test listens for console warnings containing "Content Security Policy" and `net::ERR_BLOCKED_BY_CSP` request failures
5+
- Would have caught the shields.io badge block before deployment
6+
7+
---
8+
9+
## Summary
10+
Added a Playwright test to detect CSP violations at load time, closing the test coverage gap that let the shields.io badge block slip through.
11+
12+
---
13+
14+
## 1. CSP Violation Detection Test
15+
**Files:** `tests/dev/build-validation.spec.js`
16+
**What:** New test registers `console` and `requestfailed` listeners before page reload, collects any CSP-related warnings or blocked requests during a 5-second observation window, then asserts no violations occurred.
17+
**Impact:** Any future CSP misconfiguration (missing domain in `img-src`, `script-src`, `connect-src`, etc.) will be caught automatically by the test suite.
18+
19+
---
20+
21+
## Files Changed (1 total)
22+
23+
| File | Lines Changed | Type |
24+
|------|:---:|------|
25+
| `tests/dev/build-validation.spec.js` | +28 | Test |

tests/dev/build-validation.spec.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,36 @@ test.describe('Development Build Validation', () => {
6565
expect(csp).toContain('default-src');
6666
});
6767

68+
test('no CSP violations on page load', async ({ page }) => {
69+
/** @type {string[]} */
70+
const cspViolations = [];
71+
72+
// CSP blocks surface as console warnings (not JS errors)
73+
page.on('console', msg => {
74+
if (msg.type() === 'warning' || msg.type() === 'error') {
75+
const text = msg.text();
76+
if (text.includes('Content Security Policy') || text.includes('CSP')) {
77+
cspViolations.push(text);
78+
}
79+
}
80+
});
81+
82+
// Also catch network requests blocked by CSP
83+
page.on('requestfailed', req => {
84+
const failure = req.failure();
85+
if (failure && failure.errorText.includes('net::ERR_BLOCKED_BY_CSP')) {
86+
cspViolations.push(`CSP blocked: ${req.url()}`);
87+
}
88+
});
89+
90+
await page.reload();
91+
await page.waitForSelector('#markdown-editor', { state: 'visible' });
92+
await page.waitForFunction(() => window.MDView && window.MDView.currentViewMode === 'split');
93+
await page.waitForTimeout(5000);
94+
95+
expect(cspViolations, 'CSP violations detected — update img-src / script-src / connect-src in index.html').toEqual([]);
96+
});
97+
6898
test('vendor globals are loaded', async ({ page }) => {
6999
const globals = await page.evaluate(() => ({
70100
marked: typeof window.marked,

0 commit comments

Comments
 (0)