Save consent without reloading the page

consent.js posts the consent form in the background, the server answers
204 with the cookie, and the script swaps in the embeds and the legal line
from a fresh copy of the page. Embed hosts are in frame-src from the start,
the content address still only after consent. Without JavaScript the form
keeps working with a reload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5.5 committed 2026-10-12 13:56:16 +02:00
1 parent 6390c00876
commit 6fa303f901
8 files changed
+198 -24

No files matched your search

+10 -5
View File
@@ -69,7 +69,8 @@ try {
const queries = Number(response.headers()['x-kant-queries'] ?? -1);
const html = (await response.text()).length;
const styles = [...transferred.values()].filter(entry => entry.type === 'text/css').reduce((sum, entry) => sum + entry.length, 0);
const scripts = [...transferred.values()].filter(entry => entry.type.includes('javascript')).length;
// consent.js zählt nicht: nur solange eine Einwilligung offen ist (ADR 115).
const scripts = [...transferred.entries()].filter(([url, entry]) => entry.type.includes('javascript') && !url.includes('/assets/consent.js')).length;
const requests = transferred.size;
// Bilder gehören zum Inhalt: eine bebilderte Startseite lädt zu Recht mehr Dateien als eine
// Textseite. Gedeckelt wird deshalb das Beiwerk (Stile, Schriften, Skripte) und das
@@ -114,7 +115,9 @@ try {
assert.equal(await page.locator('h1').count(), 1);
// Strukturierte Daten stehen zwar in einem script-Element, führen aber nichts aus. Gezählt
// wird, was laufen kann - und das nur, wenn die Seite es in ihrer eigenen Richtlinie erlaubt.
const laufend = await page.locator('script:not([type="application/ld+json"])').count();
// consent.js zählt nicht mit: Es steht nur auf der Seite, solange eine Einwilligung offen ist,
// und nach der Entscheidung nicht mehr (ADR 115).
const laufend = await page.locator('script:not([type="application/ld+json"]):not([src^="/assets/consent.js"])').count();
const darfSkripte = !/script-src 'none'/.test(response.headers()['content-security-policy'] ?? '');
assert.ok(darfSkripte ? laufend <= 3 : 0 === laufend, `${path}: ${laufend} Skript(e), erlaubt ${darfSkripte ? 3 : 0}`);
// Einblendungen zu Ende spielen, bevor gemessen wird: mitten in einer Einblendung ist ein
@@ -162,7 +165,8 @@ try {
const hinweis = page.locator('.consent-bar button[value="none"]');
if (await hinweis.count()) {
await hinweis.click();
await page.waitForLoadState('domcontentloaded');
// Mit consent.js ohne Neuladen (ADR 115): warten, bis der Hinweis weg ist.
await page.locator('.consent-bar').waitFor({ state: 'detached' });
}
await page.keyboard.press('Tab');
assert.equal(await page.locator(':focus').innerText(), 'Zum Inhalt springen');
@@ -171,7 +175,8 @@ try {
// Weiter mit der Tastatur: der erste Verweis im Inhalt muss anklickbar sein und tatsächlich
// woandershin führen. Vorher standen hier die Linktexte der Demo - gegen jede andere
// Installation lief die Prüfung damit ins Leere statt etwas zu prüfen.
const ersterLink = page.locator('main a[href^="/"]').first();
// Ein PDF zum Herunterladen ist keine Seite mit Überschrift; es zählt hier nicht mit.
const ersterLink = page.locator('main a[href^="/"]:not([href$=".pdf"])').first();
const ziel = await ersterLink.getAttribute('href');
await ersterLink.click();
assert.equal(new URL(page.url()).pathname, ziel.split('#')[0] || '/');
@@ -189,7 +194,7 @@ try {
await noJs.waitForLoadState('domcontentloaded');
}
assert.equal(await noJs.locator('h1').count(), 1);
const ohneJs = noJs.locator('main a[href^="/"]').first();
const ohneJs = noJs.locator('main a[href^="/"]:not([href$=".pdf"])').first();
const zielOhneJs = await ohneJs.getAttribute('href');
await ohneJs.click();
assert.equal(new URL(noJs.url()).pathname, zielOhneJs.split('#')[0] || '/');