Files

641 lines
17 KiB
JavaScript

import assert from "node:assert/strict";
import { createConsentEngine } from "../../core/consent.js";
import { isStoragePayload } from "../../core/storage.js";
import {
isValidCategoriesObject
} from "../../core/categories.js";
import {
resolveJurisdiction,
isValidResolution
} from "../../jurisdiction/resolver.js";
import {
createIntegratedConsentEngine
} from "../../integration/index.js";
/* -------------------------------------------------------------------------- */
/* Browser-like storage environment */
/* -------------------------------------------------------------------------- */
let jar = new Map();
let blockWrites = false;
globalThis.location = { protocol: "http:" };
globalThis.document = {};
Object.defineProperty(globalThis.document, "cookie", {
configurable: true,
get() {
return [...jar.entries()]
.map(([key, value]) => `${key}=${value}`)
.join("; ");
},
set(value) {
if (blockWrites) {
return;
}
const parts = value.split(";").map((item) => item.trim());
const [name, raw = ""] = parts[0].split("=");
const maxAge = parts.find(
(item) => /^Max-Age=/i.test(item)
);
if (maxAge && maxAge.toLowerCase() === "max-age=0") {
jar.delete(name);
return;
}
jar.set(name, raw);
}
});
function clearEnvironment() {
jar.clear();
blockWrites = false;
}
function make(options = {}) {
return createConsentEngine({
policyVersion: "2026-01",
jurisdiction: "global",
storage: {
name: "cc_adversarial",
duration: 180,
path: "/",
sameSite: "Lax"
},
...options
});
}
let passed = 0;
function test(name, fn) {
clearEnvironment();
try {
fn();
passed += 1;
console.log(`PASS ${name}`);
} catch (error) {
console.error(`FAIL ${name}`);
throw error;
}
}
/* -------------------------------------------------------------------------- */
/* Input boundary */
/* -------------------------------------------------------------------------- */
test("null configuration falls back safely", () => {
const consent = createConsentEngine(null);
consent.initialize();
assert.equal(consent.getState().jurisdiction, "global");
});
test("array configuration falls back safely", () => {
const consent = createConsentEngine([]);
consent.initialize();
assert.equal(consent.getState().jurisdiction, "global");
});
test("invalid storage object does not corrupt defaults", () => {
const consent = createConsentEngine({
storage: "invalid"
});
consent.initialize();
assert.equal(consent.getState().jurisdiction, "global");
});
test("invalid storage duration does not corrupt initialization", () => {
const consent = make({
storage: {
duration: "invalid"
}
});
consent.initialize();
assert.equal(consent.getState().hasDecision, false);
});
/* -------------------------------------------------------------------------- */
/* Consent operation boundaries */
/* -------------------------------------------------------------------------- */
test("empty consent payload does not create a decision", () => {
const consent = make();
consent.initialize();
const state = consent.setConsent({});
assert.equal(state.hasDecision, false);
assert.equal(state.categories.analytics, "unknown");
assert.equal(state.categories.marketing, "unknown");
});
test("null consent payload is rejected", () => {
const consent = make();
consent.initialize();
assert.throws(
() => consent.setConsent(null),
TypeError
);
});
test("array consent payload is rejected", () => {
const consent = make();
consent.initialize();
assert.throws(
() => consent.setConsent([]),
TypeError
);
});
test("unknown consent property is ignored without changing state", () => {
const consent = make();
consent.initialize();
const before = consent.getState();
const after = consent.setConsent({
unknownCategory: "granted"
});
assert.deepEqual(after.categories, before.categories);
assert.equal(after.hasDecision, before.hasDecision);
assert.equal(after.jurisdiction, before.jurisdiction);
assert.equal(after.timestamp, before.timestamp);
});
test("necessary cannot be changed to unknown", () => {
const consent = make();
consent.initialize();
assert.throws(
() => consent.setConsent({
necessary: "unknown"
}),
TypeError
);
});
test("revoke before acceptance remains deterministic", () => {
const consent = make();
consent.initialize();
const first = consent.revoke();
const second = consent.revoke();
assert.deepEqual(second.categories, first.categories);
assert.equal(second.hasDecision, true);
});
test("reset before any decision remains deterministic", () => {
const consent = make();
consent.initialize();
const first = consent.reset();
const second = consent.reset();
assert.equal(first.hasDecision, false);
assert.equal(second.hasDecision, false);
assert.deepEqual(second.categories, first.categories);
});
/* -------------------------------------------------------------------------- */
/* Operation sequences */
/* -------------------------------------------------------------------------- */
test("accept then reject produces the expected final state", () => {
const consent = make();
consent.initialize();
consent.acceptAll();
const state = consent.rejectAll();
assert.equal(state.hasDecision, true);
assert.equal(state.categories.necessary, "granted");
assert.equal(state.categories.preferences, "denied");
assert.equal(state.categories.analytics, "denied");
assert.equal(state.categories.marketing, "denied");
});
test("reject then accept produces the expected final state", () => {
const consent = make();
consent.initialize();
consent.rejectAll();
const state = consent.acceptAll();
assert.equal(state.hasDecision, true);
assert.equal(state.categories.necessary, "granted");
assert.equal(state.categories.preferences, "granted");
assert.equal(state.categories.analytics, "granted");
assert.equal(state.categories.marketing, "granted");
});
test("reset after acceptance removes the decision", () => {
const consent = make();
consent.initialize();
consent.acceptAll();
const state = consent.reset();
assert.equal(state.hasDecision, false);
assert.equal(state.categories.necessary, "granted");
assert.equal(state.categories.preferences, "unknown");
assert.equal(state.categories.analytics, "unknown");
assert.equal(state.categories.marketing, "unknown");
});
test("revoke followed by reset returns to undecided state", () => {
const consent = make();
consent.initialize();
consent.acceptAll();
consent.revoke();
const state = consent.reset();
assert.equal(state.hasDecision, false);
assert.equal(state.categories.preferences, "unknown");
assert.equal(state.categories.analytics, "unknown");
assert.equal(state.categories.marketing, "unknown");
});
/* -------------------------------------------------------------------------- */
/* Deep isolation */
/* -------------------------------------------------------------------------- */
test("returned state nested mutation cannot alter internal state", () => {
const consent = make();
consent.initialize();
consent.acceptAll();
const state = consent.getState();
state.categories.preferences = "denied";
state.categories.analytics = "unknown";
const current = consent.getState();
assert.equal(current.categories.preferences, "granted");
assert.equal(current.categories.analytics, "granted");
});
test("two engines remain isolated after independent transitions", () => {
const first = make({
jurisdiction: "us-ma"
});
const second = make({
jurisdiction: "eu"
});
first.initialize();
second.initialize();
first.acceptAll();
assert.equal(first.getState().jurisdiction, "us-ma");
assert.equal(second.getState().jurisdiction, "eu");
assert.equal(first.getState().hasDecision, true);
assert.equal(second.getState().hasDecision, false);
});
/* -------------------------------------------------------------------------- */
/* Storage envelope adversarial cases */
/* -------------------------------------------------------------------------- */
test("storage payload rejects NaN timestamp", () => {
assert.equal(
isStoragePayload({
engineVersion: "1.0.1",
policyVersion: "2026-01",
timestamp: NaN,
categories: {
necessary: "granted",
preferences: "unknown",
analytics: "unknown",
marketing: "unknown"
},
jurisdiction: "global",
gpc: false
}),
false
);
});
test("storage payload rejects infinite timestamp", () => {
assert.equal(
isStoragePayload({
engineVersion: "1.0.1",
policyVersion: "2026-01",
timestamp: Infinity,
categories: {
necessary: "granted",
preferences: "unknown",
analytics: "unknown",
marketing: "unknown"
},
jurisdiction: "global",
gpc: false
}),
false
);
});
test("storage payload rejects empty engine version", () => {
assert.equal(
isStoragePayload({
engineVersion: "",
policyVersion: "2026-01",
timestamp: Date.now(),
categories: {
necessary: "granted",
preferences: "unknown",
analytics: "unknown",
marketing: "unknown"
},
jurisdiction: "global",
gpc: false
}),
false
);
});
test("storage payload rejects non-boolean GPC", () => {
assert.equal(
isStoragePayload({
engineVersion: "1.0.1",
policyVersion: "2026-01",
timestamp: Date.now(),
categories: {
necessary: "granted",
preferences: "unknown",
analytics: "unknown",
marketing: "unknown"
},
jurisdiction: "global",
gpc: "true"
}),
false
);
});
test("storage payload rejects array categories", () => {
assert.equal(
isStoragePayload({
engineVersion: "1.0.1",
policyVersion: "2026-01",
timestamp: Date.now(),
categories: [],
jurisdiction: "global",
gpc: false
}),
false
);
});
test("storage payload rejects missing jurisdiction", () => {
assert.equal(
isStoragePayload({
engineVersion: "1.0.1",
policyVersion: "2026-01",
timestamp: Date.now(),
categories: {
necessary: "granted",
preferences: "unknown",
analytics: "unknown",
marketing: "unknown"
},
gpc: false
}),
false
);
});
/* -------------------------------------------------------------------------- */
/* Category contract */
/* -------------------------------------------------------------------------- */
test("category contract rejects null", () => {
assert.equal(
isValidCategoriesObject(null),
false
);
});
test("category contract rejects arrays", () => {
assert.equal(
isValidCategoriesObject([]),
false
);
});
test("category contract rejects unknown consent value", () => {
assert.equal(
isValidCategoriesObject({
necessary: "granted",
preferences: "unknown",
analytics: "invalid",
marketing: "unknown"
}),
false
);
});
/* -------------------------------------------------------------------------- */
/* Jurisdiction adversarial cases */
/* -------------------------------------------------------------------------- */
test("jurisdiction resolver rejects null input", () => {
assert.throws(
() => resolveJurisdiction(null),
TypeError
);
});
test("jurisdiction resolver rejects array input", () => {
assert.throws(
() => resolveJurisdiction([]),
TypeError
);
});
test("fixed jurisdiction trims surrounding whitespace", () => {
const result = resolveJurisdiction({
mode: "fixed",
jurisdiction: " us-ma "
});
assert.equal(result.jurisdiction.id, "us-ma");
assert.equal(isValidResolution(result), true);
});
test("fixed jurisdiction rejects whitespace-only value", () => {
assert.throws(
() => resolveJurisdiction({
mode: "fixed",
jurisdiction: " "
}),
TypeError
);
});
test("invalid signal source is ignored during auto resolution", () => {
const result = resolveJurisdiction({
mode: "auto",
request: {
jurisdiction: "us-ma",
source: "invalid-source"
}
});
assert.equal(result.source, "fallback");
assert.equal(result.jurisdiction.id, "global");
});
test("valid server signal defeats lower-trust browser signal", () => {
const result = resolveJurisdiction({
mode: "auto",
request: {
jurisdiction: "us-ma",
source: "server"
},
visitor: {
jurisdiction: "eu",
source: "browser"
}
});
assert.equal(result.jurisdiction.id, "us-ma");
assert.equal(result.source, "server");
});
test("explicit fixed mode defeats conflicting request signals", () => {
const result = resolveJurisdiction({
mode: "fixed",
jurisdiction: "eu",
request: {
jurisdiction: "us-ma",
source: "server"
}
});
assert.equal(result.jurisdiction.id, "eu");
assert.equal(result.source, "site-config");
});
/* -------------------------------------------------------------------------- */
/* Integration boundary */
/* -------------------------------------------------------------------------- */
test("resolved jurisdiction cannot be overridden by Core jurisdiction option", () => {
const engine = createIntegratedConsentEngine({
jurisdiction: {
mode: "fixed",
jurisdiction: "eu"
},
core: {
jurisdiction: "us-ma"
}
});
engine.initialize();
assert.equal(
engine.getState().jurisdiction,
"eu"
);
assert.equal(
engine.getJurisdictionContext().resolution.jurisdiction.id,
"eu"
);
});
test("integration rejects invalid jurisdiction before Core creation", () => {
assert.throws(
() => createIntegratedConsentEngine({
jurisdiction: {
mode: "fixed",
jurisdiction: "unknown"
}
}),
RangeError
);
});
/* -------------------------------------------------------------------------- */
/* GPC boundary */
/* -------------------------------------------------------------------------- */
test("GPC remains state information under adversarial consent sequence", () => {
const consent = make();
consent.initialize();
consent.setGpc(true);
const state = consent.getState();
assert.equal(state.gpc, true);
assert.equal(state.categories.necessary, "granted");
assert.equal(state.categories.preferences, "unknown");
assert.equal(state.categories.analytics, "unknown");
assert.equal(state.categories.marketing, "unknown");
});
test("explicit acceptance remains explicit after GPC activation", () => {
const consent = make();
consent.initialize();
consent.setGpc(true);
consent.acceptAll();
const state = consent.getState();
assert.equal(state.gpc, true);
assert.equal(state.hasDecision, true);
assert.equal(state.categories.preferences, "granted");
assert.equal(state.categories.analytics, "granted");
assert.equal(state.categories.marketing, "granted");
});
console.log();
console.log(`${passed} adversarial tests passed.`);