Skip to content

Commit 1037e7a

Browse files
authored
consent handling: Refactor and various fixes (#172)
1 parent 35d21a5 commit 1037e7a

File tree

7 files changed

+383
-116
lines changed

7 files changed

+383
-116
lines changed

lib/core/network.test.js

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ describe("buildRequest", () => {
2020
expect([...url.searchParams.entries()]).toEqual([
2121
["query", "string"],
2222
["osdk", `web-${buildInfo.version}`],
23-
["reg", "can"],
2423
["gpp", "gpp"],
2524
["gpp_sid", "1,2"],
2625
["cookies", "yes"],

lib/core/network.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,20 @@ function buildRequest(path: string, config: ResolvedConfig, init?: RequestInit):
88
const url = new URL(`${site}${path}`, `https://${host}`);
99
url.searchParams.set("osdk", `web-${buildInfo.version}`);
1010

11-
if (config.consent.reg) {
12-
url.searchParams.set("reg", config.consent.reg);
13-
}
14-
15-
if (config.consent.gpp) {
11+
if (typeof config.consent.gpp !== "undefined") {
1612
url.searchParams.set("gpp", config.consent.gpp);
1713
}
1814

19-
if (config.consent.gppSectionIDs) {
15+
if (typeof config.consent.gppSectionIDs !== "undefined") {
2016
url.searchParams.set("gpp_sid", config.consent.gppSectionIDs.join(","));
2117
}
2218

23-
if (config.consent.tcf) {
24-
url.searchParams.set("tcf", config.consent.tcf);
19+
if (typeof config.consent.gdpr !== "undefined") {
20+
url.searchParams.set("gdpr_consent", config.consent.gdpr);
21+
}
22+
23+
if (typeof config.consent.gdprApplies !== "undefined") {
24+
url.searchParams.set("gdpr", Number(config.consent.gdprApplies).toString());
2525
}
2626

2727
if (cookies) {

lib/core/regs/consent.test.js

+79-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getConsent } from "./consent";
1+
import { getConsent, applicableReg } from "./consent";
22
import * as gpp from "./gpp";
33

44
const allowAll = {
@@ -15,6 +15,75 @@ const denyAll = {
1515
measureAdvertisingPerformance: false,
1616
};
1717

18+
describe("applicableReg", () => {
19+
it("returns gdpr when cmp indicates gdpr applies", () => {
20+
expect(applicableReg("can", { gdprApplies: true })).toBe("gdpr");
21+
expect(applicableReg("us", { gdprApplies: true })).toBe("gdpr");
22+
expect(applicableReg(null, { gdprApplies: true })).toBe("gdpr");
23+
24+
expect(applicableReg("can", { gppSectionIDs: [2] })).toBe("gdpr");
25+
expect(applicableReg("us", { gppSectionIDs: [2] })).toBe("gdpr");
26+
expect(applicableReg(null, { gppSectionIDs: [2] })).toBe("gdpr");
27+
});
28+
29+
it("returns can when cmp indicates can applies", () => {
30+
expect(applicableReg("gdpr", { gppSectionIDs: [5] })).toBe("can");
31+
expect(applicableReg("us", { gppSectionIDs: [5] })).toBe("can");
32+
expect(applicableReg(null, { gppSectionIDs: [5] })).toBe("can");
33+
});
34+
35+
it("returns us when cmp indicates us applies", () => {
36+
expect(applicableReg("gdpr", { gppSectionIDs: [7] })).toBe("us");
37+
expect(applicableReg("can", { gppSectionIDs: [7] })).toBe("us");
38+
expect(applicableReg(null, { gppSectionIDs: [7] })).toBe("us");
39+
});
40+
41+
it("returns unknown when cmp indicates detected regulation does not apply", () => {
42+
expect(applicableReg("gdpr", { gdprApplies: false })).toBe(null);
43+
expect(applicableReg("gdpr", { gppSectionIDs: [999] })).toBe(null);
44+
expect(applicableReg("gdpr", { gppSectionIDs: [-1] })).toBe(null);
45+
46+
expect(applicableReg("can", { gppSectionIDs: [999] })).toBe(null);
47+
expect(applicableReg("can", { gppSectionIDs: [-1] })).toBe(null);
48+
49+
expect(applicableReg("us", { gppSectionIDs: [999] })).toBe(null);
50+
expect(applicableReg("us", { gppSectionIDs: [-1] })).toBe(null);
51+
});
52+
53+
it("prefers tcf signaling over gpp", () => {
54+
expect(applicableReg("gdpr", { gdprApplies: true, gppSectionIDs: [8] })).toBe("gdpr");
55+
expect(applicableReg("can", { gdprApplies: true, gppSectionIDs: [5] })).toBe("gdpr");
56+
expect(applicableReg("us", { gdprApplies: true, gppSectionIDs: [-1] })).toBe("gdpr");
57+
expect(applicableReg("gdpr", { gdprApplies: false, gppSectionIDs: [8] })).toBe(null);
58+
expect(applicableReg("can", { gdprApplies: false, gppSectionIDs: [5] })).toBe("can");
59+
expect(applicableReg("us", { gdprApplies: false, gppSectionIDs: [-1] })).toBe("us");
60+
61+
// presence of gdprData may resolve to gdpr only if it was detected as well
62+
expect(applicableReg("gdpr", { gdprData: {} })).toBe("gdpr");
63+
expect(applicableReg(null, { gdprData: {} })).toBe(null);
64+
expect(applicableReg("can", { gdprData: {} })).toBe("can");
65+
});
66+
67+
it("infers gdpr>can>us when using gpp", () => {
68+
expect(applicableReg(null, { gppSectionIDs: [2, 5, 7, 8] })).toBe("gdpr");
69+
expect(applicableReg(null, { gppSectionIDs: [5, 7, 8] })).toBe("can");
70+
expect(applicableReg(null, { gppSectionIDs: [7, 8] })).toBe("us");
71+
expect(applicableReg(null, { gppSectionIDs: [8] })).toBe("us");
72+
expect(applicableReg(null, { gppSectionIDs: [] })).toBe(null);
73+
});
74+
75+
it("returns reg until cmp knows", () => {
76+
expect(applicableReg("gdpr", {})).toBe("gdpr");
77+
expect(applicableReg("gdpr", { gppSectionIDs: [0] })).toBe("gdpr");
78+
79+
expect(applicableReg("can", {})).toBe("can");
80+
expect(applicableReg("can", { gppSectionIDs: [0] })).toBe("can");
81+
82+
expect(applicableReg("us", {})).toBe("us");
83+
expect(applicableReg("us", { gppSectionIDs: [0] })).toBe("us");
84+
});
85+
});
86+
1887
describe("getConsent", () => {
1988
afterEach(() => {
2089
Object.defineProperties(window, {
@@ -64,7 +133,7 @@ describe("getConsent", () => {
64133
// Simulate event indicating that gdpr doesn't apply
65134
signal(tcfData({ gdprApplies: false, tcString: "doesntapply" }));
66135
expect(consent.deviceAccess).toBe(true);
67-
expect(consent.tcf).toBeUndefined();
136+
expect(consent.gdpr).toBe("doesntapply");
68137

69138
// Simulate event where no consent is granted
70139
signal(
@@ -74,7 +143,7 @@ describe("getConsent", () => {
74143
})
75144
);
76145
expect(consent.deviceAccess).toBe(false);
77-
expect(consent.tcf).toBe("noconsent");
146+
expect(consent.gdpr).toBe("noconsent");
78147

79148
// Simulate event where purpose 1 consent is granted to the publisher
80149
signal(
@@ -84,7 +153,7 @@ describe("getConsent", () => {
84153
})
85154
);
86155
expect(consent.deviceAccess).toBe(true);
87-
expect(consent.tcf).toBe("purpose1");
156+
expect(consent.gdpr).toBe("purpose1");
88157

89158
// Simulate removing consent
90159
signal(
@@ -94,7 +163,7 @@ describe("getConsent", () => {
94163
})
95164
);
96165
expect(consent.deviceAccess).toBe(false);
97-
expect(consent.tcf).toBe("revoked");
166+
expect(consent.gdpr).toBe("revoked");
98167
});
99168

100169
it("updates consent based on gpp signals for gdpr", () => {
@@ -105,11 +174,11 @@ describe("getConsent", () => {
105174
expect(consent.deviceAccess).toBe(false);
106175
expect(consent.reg).toBe("gdpr");
107176

108-
// Simulate gpp ready event indicating no applicable sections
109-
signal({ applicableSections: [-1], gppString: "ignored" });
110-
expect(consent.deviceAccess).toBe(true);
177+
// Simulate gpp ready event indicating applicable sections unknown
178+
signal({ applicableSections: [0], gppString: "ignored" });
179+
expect(consent.deviceAccess).toBe(false);
111180
expect(consent.gpp).toBe("ignored");
112-
expect(consent.gppSectionIDs).toEqual([-1]);
181+
expect(consent.gppSectionIDs).toEqual([0]);
113182

114183
// Section tcfeuv2 applies but nothing in parsed sections
115184
signal({ parsedSections: {}, applicableSections: [gpp.tcfeuv2.SectionID], gppString: "noparsedsections" });
@@ -247,7 +316,7 @@ describe("getConsent", () => {
247316
);
248317

249318
expect(consent.deviceAccess).toBe(true);
250-
expect(consent.tcf).toBe("granted");
319+
expect(consent.gdpr).toBe("granted");
251320
expect(consent.gpp).toBe("revoked");
252321
});
253322

0 commit comments

Comments
 (0)