Add GDPR compliant cookie banner and update footer/privacy policy to include GA and Clarity; added e2e and unit tests for cookie handling; updated snapshots
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful

This commit is contained in:
2026-03-12 15:04:49 -03:00
parent 4ad45d5625
commit a5989b03b1
28 changed files with 607 additions and 9 deletions

View File

@@ -0,0 +1,119 @@
/**
* @vitest-environment jsdom
*/
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
const __dirname = dirname(fileURLToPath(import.meta.url));
const SCRIPT_PATH = join(__dirname, '../../static/assets/js/cookie-consent.js');
function createBannerDOM() {
const banner = document.createElement('div');
banner.id = 'cookie-banner';
const acceptBtn = document.createElement('button');
acceptBtn.type = 'button';
acceptBtn.dataset.consent = 'accept';
const rejectBtn = document.createElement('button');
rejectBtn.type = 'button';
rejectBtn.dataset.consent = 'reject';
banner.appendChild(acceptBtn);
banner.appendChild(rejectBtn);
document.body.appendChild(banner);
return { banner, acceptBtn, rejectBtn };
}
describe('cookie-consent.js', () => {
const STORAGE_KEY = 'mifi-ventures-cookie-consent';
let dom: ReturnType<typeof createBannerDOM>;
beforeEach(() => {
// Ensure a fresh DOM and storage for each test
document.body.innerHTML = '';
window.localStorage.clear();
dom = createBannerDOM();
const code = readFileSync(SCRIPT_PATH, 'utf8');
// eslint-disable-next-line no-eval
eval(code);
document.dispatchEvent(new Event('DOMContentLoaded'));
});
afterEach(() => {
dom.banner.remove();
vi.restoreAllMocks();
window.localStorage.clear();
});
it('shows banner when no preference is stored', () => {
expect(dom.banner.classList.contains('is-visible')).toBe(true);
});
it('hides banner and loads analytics when preference is "accept"', () => {
document.body.innerHTML = '';
window.localStorage.setItem(STORAGE_KEY, 'accept');
dom = createBannerDOM();
const appendChildSpy = vi.spyOn(document.head, 'appendChild');
const code = readFileSync(SCRIPT_PATH, 'utf8');
// eslint-disable-next-line no-eval
eval(code);
document.dispatchEvent(new Event('DOMContentLoaded'));
expect(dom.banner.classList.contains('is-visible')).toBe(false);
expect(appendChildSpy).toHaveBeenCalled();
const urls = appendChildSpy.mock.calls
.map((args) => (args[0] as HTMLScriptElement).src)
.filter(Boolean);
expect(urls.some((src) => src.includes('googletagmanager.com'))).toBe(true);
});
it('hides banner when preference is "reject" and does not load analytics', () => {
document.body.innerHTML = '';
window.localStorage.setItem(STORAGE_KEY, 'reject');
dom = createBannerDOM();
const appendChildSpy = vi.spyOn(document.head, 'appendChild');
const code = readFileSync(SCRIPT_PATH, 'utf8');
// eslint-disable-next-line no-eval
eval(code);
document.dispatchEvent(new Event('DOMContentLoaded'));
expect(dom.banner.classList.contains('is-visible')).toBe(false);
const urls = appendChildSpy.mock.calls
.map((args) => (args[0] as HTMLScriptElement).src)
.filter(Boolean);
expect(urls.some((src) => src.includes('googletagmanager.com'))).toBe(false);
});
it('stores "accept" in localStorage, hides banner, and loads analytics on accept click', () => {
const appendChildSpy = vi.spyOn(document.head, 'appendChild');
dom.acceptBtn.click();
expect(window.localStorage.getItem(STORAGE_KEY)).toBe('accept');
expect(dom.banner.classList.contains('is-visible')).toBe(false);
expect(appendChildSpy).toHaveBeenCalled();
});
it('stores "reject" in localStorage and hides banner on reject click', () => {
const appendChildSpy = vi.spyOn(document.head, 'appendChild');
dom.rejectBtn.click();
expect(window.localStorage.getItem(STORAGE_KEY)).toBe('reject');
expect(dom.banner.classList.contains('is-visible')).toBe(false);
const urls = appendChildSpy.mock.calls
.map((args) => (args[0] as HTMLScriptElement).src)
.filter(Boolean);
expect(urls.some((src) => src.includes('googletagmanager.com'))).toBe(false);
});
});