chore: import upstream snapshot with attribution
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Has been cancelled
Test and Publish Multi-arch Docker Image / test (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Has been cancelled
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Has been cancelled
Validate Renovate Config / Validate Renovate Configuration (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:24:08 +08:00
commit 0d3cb498a3
5438 changed files with 1316560 additions and 0 deletions
+275
View File
@@ -0,0 +1,275 @@
import * as fs from 'fs';
import * as path from 'path';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
/**
* Tests for the cookie consent banner (site/static/js/consent.js).
* We load and evaluate the IIFE in a jsdom environment, then verify
* DOM state, cookie behavior, and script injection.
*/
const CONSENT_JS = fs.readFileSync(path.resolve(__dirname, '../../static/js/consent.js'), 'utf-8');
function setCookie(name: string, value: string) {
document.cookie = `${name}=${value};path=/`;
}
function getCookie(name: string): string | null {
const m = document.cookie.match(new RegExp(`(^| )${name}=([^;]+)`));
return m ? m[2] : null;
}
function clearCookies() {
document.cookie.split(';').forEach((c) => {
const name = c.split('=')[0].trim();
if (name) {
document.cookie = `${name}=;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT`;
}
});
}
function runConsent() {
// eslint-disable-next-line no-eval
const fn = new Function(CONSENT_JS);
fn();
}
describe('consent.js', () => {
beforeEach(() => {
clearCookies();
document.body.innerHTML = '';
document.head.querySelectorAll('#cc-styles').forEach((el) => el.remove());
document.querySelectorAll('script[src]').forEach((el) => el.remove());
(window as any).__pf_scripts_loaded = false;
(window as any).__pf_manage_cookies = undefined;
// Stub location.hash
Object.defineProperty(window, 'location', {
writable: true,
value: {
...window.location,
hash: '',
pathname: '/',
search: '',
href: 'http://localhost/',
reload: vi.fn(),
},
});
});
afterEach(() => {
vi.restoreAllMocks();
});
describe('EU visitor without prior consent', () => {
it('loads scripts when no pf_country cookie (defaults to non-EU)', () => {
runConsent();
expect(document.getElementById('cc-banner')).toBeNull();
expect((window as any).__pf_scripts_loaded).toBe(true);
});
it('shows banner for EU country code', () => {
setCookie('pf_country', 'DE');
runConsent();
expect(document.getElementById('cc-banner')).not.toBeNull();
});
it('shows banner for UK', () => {
setCookie('pf_country', 'GB');
runConsent();
expect(document.getElementById('cc-banner')).not.toBeNull();
});
it('shows banner for Switzerland', () => {
setCookie('pf_country', 'CH');
runConsent();
expect(document.getElementById('cc-banner')).not.toBeNull();
});
});
describe('non-EU visitor', () => {
it('does not show banner for US', () => {
setCookie('pf_country', 'US');
runConsent();
expect(document.getElementById('cc-banner')).toBeNull();
});
it('does not show banner for Japan', () => {
setCookie('pf_country', 'JP');
runConsent();
expect(document.getElementById('cc-banner')).toBeNull();
});
it('loads scripts immediately', () => {
setCookie('pf_country', 'US');
runConsent();
expect((window as any).__pf_scripts_loaded).toBe(true);
const gtagScript = document.querySelector('script[src*="googletagmanager"]');
expect(gtagScript).not.toBeNull();
});
it('does not load scripts when #manage-cookies hash is present', () => {
setCookie('pf_country', 'US');
(window as any).location.hash = '#manage-cookies';
runConsent();
expect((window as any).__pf_scripts_loaded).toBe(false);
expect(document.getElementById('cc-banner')).not.toBeNull();
});
});
describe('accept flow', () => {
it('sets pf_consent=1 and loads scripts on accept', () => {
setCookie('pf_country', 'DE');
runConsent();
const acceptBtn = document.getElementById('cc-accept')!;
acceptBtn.click();
expect(getCookie('pf_consent')).toBe('1');
expect(document.getElementById('cc-banner')).toBeNull();
expect((window as any).__pf_scripts_loaded).toBe(true);
});
});
describe('decline flow', () => {
it('sets pf_consent=0 and does not load scripts on decline', () => {
setCookie('pf_country', 'FR');
runConsent();
const declineBtn = document.getElementById('cc-decline')!;
declineBtn.click();
expect(getCookie('pf_consent')).toBe('0');
expect(document.getElementById('cc-banner')).toBeNull();
expect((window as any).__pf_scripts_loaded).toBe(false);
});
});
describe('returning visitor with prior consent', () => {
it('loads scripts immediately when pf_consent=1', () => {
setCookie('pf_country', 'DE');
setCookie('pf_consent', '1');
runConsent();
expect(document.getElementById('cc-banner')).toBeNull();
expect((window as any).__pf_scripts_loaded).toBe(true);
});
it('does nothing when pf_consent=0', () => {
setCookie('pf_country', 'DE');
setCookie('pf_consent', '0');
runConsent();
expect(document.getElementById('cc-banner')).toBeNull();
expect((window as any).__pf_scripts_loaded).toBe(false);
});
});
describe('withdraw consent', () => {
it('exposes __pf_manage_cookies global', () => {
setCookie('pf_country', 'DE');
runConsent();
expect(typeof (window as any).__pf_manage_cookies).toBe('function');
});
it('reopens banner when __pf_manage_cookies is called', () => {
setCookie('pf_country', 'DE');
setCookie('pf_consent', '1');
runConsent();
expect(document.getElementById('cc-banner')).toBeNull();
(window as any).__pf_manage_cookies();
expect(document.getElementById('cc-banner')).not.toBeNull();
});
it('reloads page when declining after scripts were loaded', () => {
setCookie('pf_country', 'DE');
runConsent();
// Accept first
document.getElementById('cc-accept')!.click();
expect((window as any).__pf_scripts_loaded).toBe(true);
// Reopen and decline
(window as any).__pf_manage_cookies();
document.getElementById('cc-decline')!.click();
expect(window.location.reload).toHaveBeenCalled();
});
it('does not reload when declining on first visit (no scripts loaded)', () => {
setCookie('pf_country', 'DE');
runConsent();
document.getElementById('cc-decline')!.click();
expect(window.location.reload).not.toHaveBeenCalled();
});
});
describe('script loading', () => {
it('only loads scripts once even if loadScripts called multiple times', () => {
setCookie('pf_country', 'US');
runConsent();
const scriptCount = document.querySelectorAll('script[src*="scripts.js"]').length;
expect(scriptCount).toBe(1);
});
it('injects both gtag.js and scripts.js', () => {
setCookie('pf_country', 'US');
runConsent();
expect(document.querySelector('script[src*="googletagmanager"]')).not.toBeNull();
expect(document.querySelector('script[src*="scripts.js"]')).not.toBeNull();
});
});
describe('EU country coverage', () => {
const euCountries = [
'AT',
'BE',
'BG',
'HR',
'CY',
'CZ',
'DK',
'EE',
'FI',
'FR',
'DE',
'GR',
'HU',
'IE',
'IT',
'LV',
'LT',
'LU',
'MT',
'NL',
'PL',
'PT',
'RO',
'SK',
'SI',
'ES',
'SE',
'IS',
'LI',
'NO', // EEA
'GB', // UK
'CH', // Switzerland
];
it.each(euCountries)('shows banner for %s', (country) => {
setCookie('pf_country', country);
runConsent();
expect(document.getElementById('cc-banner')).not.toBeNull();
// Cleanup for next iteration
document.getElementById('cc-banner')?.remove();
clearCookies();
(window as any).__pf_scripts_loaded = false;
(window as any).__pf_manage_cookies = undefined;
});
});
});
+77
View File
@@ -0,0 +1,77 @@
import { describe, expect, it, vi } from 'vitest';
import { onRequest } from '../../functions/_middleware';
function makeContext(opts: { contentType?: string; cfCountry?: string; cookies?: string }) {
const responseHeaders = new Headers();
if (opts.contentType) {
responseHeaders.set('Content-Type', opts.contentType);
}
const response = new Response('', { headers: responseHeaders });
const requestHeaders = new Headers();
if (opts.cfCountry) {
requestHeaders.set('CF-IPCountry', opts.cfCountry);
}
if (opts.cookies) {
requestHeaders.set('Cookie', opts.cookies);
}
return {
request: new Request('https://example.com/', { headers: requestHeaders }),
next: vi.fn().mockResolvedValue(response),
};
}
describe('_middleware', () => {
it('sets pf_country cookie on HTML responses', async () => {
const ctx = makeContext({ contentType: 'text/html; charset=utf-8', cfCountry: 'DE' });
const res = await onRequest(ctx);
const setCookie = res.headers.get('Set-Cookie');
expect(setCookie).toContain('pf_country=DE');
expect(setCookie).toContain('Secure');
expect(setCookie).toContain('SameSite=Lax');
expect(setCookie).toContain('Max-Age=86400');
});
it('does not set cookie on non-HTML responses', async () => {
const ctx = makeContext({ contentType: 'application/javascript', cfCountry: 'DE' });
const res = await onRequest(ctx);
expect(res.headers.get('Set-Cookie')).toBeNull();
});
it('does not set cookie on CSS responses', async () => {
const ctx = makeContext({ contentType: 'text/css', cfCountry: 'DE' });
const res = await onRequest(ctx);
expect(res.headers.get('Set-Cookie')).toBeNull();
});
it('does not set cookie on image responses', async () => {
const ctx = makeContext({ contentType: 'image/png', cfCountry: 'US' });
const res = await onRequest(ctx);
expect(res.headers.get('Set-Cookie')).toBeNull();
});
it('does not set cookie when CF-IPCountry header is missing', async () => {
const ctx = makeContext({ contentType: 'text/html' });
const res = await onRequest(ctx);
expect(res.headers.get('Set-Cookie')).toBeNull();
});
it('always refreshes country cookie to handle travel/VPN', async () => {
const ctx = makeContext({
contentType: 'text/html',
cfCountry: 'FR',
cookies: 'pf_country=US',
});
const res = await onRequest(ctx);
const setCookie = res.headers.get('Set-Cookie');
expect(setCookie).toContain('pf_country=FR');
});
it('passes through response from next()', async () => {
const ctx = makeContext({ contentType: 'text/html', cfCountry: 'GB' });
const res = await onRequest(ctx);
expect(ctx.next).toHaveBeenCalledOnce();
expect(res).toBeInstanceOf(Response);
});
});