@financial-times/privacy-us-privacy 0.3.10 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/main.d.ts +3 -3
- package/dist/cjs/main.js +6 -4
- package/dist/esm/main.d.ts +3 -3
- package/dist/esm/main.js +5 -3
- package/package.json +5 -5
- package/src/main.ts +7 -4
- package/src/test/main.test.ts +50 -15
- package/tsconfig.json +3 -1
package/dist/cjs/main.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const NO_PRIVACY_COOKIE = "no-privacy-cookie";
|
|
2
2
|
declare global {
|
|
3
3
|
interface Window {
|
|
4
|
-
__uspapi
|
|
4
|
+
__uspapi?: (command: string, version: number, callback?: Function) => Promise<unknown>;
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
7
|
export declare function getUsPrivacyCookie(): string | null;
|
|
@@ -13,12 +13,12 @@ export declare function __uspapi(command: string, version: number, callback?: Fu
|
|
|
13
13
|
/**
|
|
14
14
|
* Expose a javascript function on the global `window` object that can be called
|
|
15
15
|
* by third party scripts to determine if the current user has opted out of CCPA
|
|
16
|
-
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/
|
|
16
|
+
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/HEAD/CCPA/USP%20API.md
|
|
17
17
|
*/
|
|
18
18
|
export declare function setUSPrivacy(): void;
|
|
19
19
|
/**
|
|
20
20
|
* Set a cookie based on the IAB US Privacy spec
|
|
21
|
-
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/
|
|
21
|
+
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/HEAD/CCPA/US%20Privacy%20String.md
|
|
22
22
|
*
|
|
23
23
|
* @param consent - Does the user have consent for CCPA
|
|
24
24
|
* @param domain - An optional explicit domain for the cookie
|
package/dist/cjs/main.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/ban-types */
|
|
2
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
exports.setUSPrivacyCookie = exports.setUSPrivacy = exports.__uspapi = exports.getUsPrivacyForTracking = exports.getUsPrivacyCookie = exports.NO_PRIVACY_COOKIE = void 0;
|
|
4
5
|
const privacy_legislation_client_1 = require("@financial-times/privacy-legislation-client");
|
|
@@ -40,7 +41,7 @@ async function __uspapi(command, version, callback) {
|
|
|
40
41
|
}
|
|
41
42
|
// No cookie, assume user hasn't ever visited the CCPA page
|
|
42
43
|
else {
|
|
43
|
-
const { legislation } = await privacy_legislation_client_1.fetchLegislation();
|
|
44
|
+
const { legislation } = await (0, privacy_legislation_client_1.fetchLegislation)();
|
|
44
45
|
if (legislation.has("ccpa")) {
|
|
45
46
|
callback({
|
|
46
47
|
version,
|
|
@@ -66,7 +67,7 @@ exports.__uspapi = __uspapi;
|
|
|
66
67
|
/**
|
|
67
68
|
* Expose a javascript function on the global `window` object that can be called
|
|
68
69
|
* by third party scripts to determine if the current user has opted out of CCPA
|
|
69
|
-
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/
|
|
70
|
+
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/HEAD/CCPA/USP%20API.md
|
|
70
71
|
*/
|
|
71
72
|
function setUSPrivacy() {
|
|
72
73
|
if (typeof window.__uspapi === "function") {
|
|
@@ -77,7 +78,7 @@ function setUSPrivacy() {
|
|
|
77
78
|
exports.setUSPrivacy = setUSPrivacy;
|
|
78
79
|
/**
|
|
79
80
|
* Set a cookie based on the IAB US Privacy spec
|
|
80
|
-
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/
|
|
81
|
+
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/HEAD/CCPA/US%20Privacy%20String.md
|
|
81
82
|
*
|
|
82
83
|
* @param consent - Does the user have consent for CCPA
|
|
83
84
|
* @param domain - An optional explicit domain for the cookie
|
|
@@ -87,6 +88,7 @@ function setUSPrivacyCookie(consent, domain) {
|
|
|
87
88
|
// and we are not trying to make it this work for every possible subdomain yet
|
|
88
89
|
domain = domain || (document.location.hostname || "").replace("www.", "");
|
|
89
90
|
const uspString = `1Y${consent ? "N" : "Y"}N`;
|
|
90
|
-
|
|
91
|
+
const maxAge = 60 * 60 * 24 * 365 * 5;
|
|
92
|
+
document.cookie = `usprivacy=${uspString};max-age=${maxAge};path=/;domain=${domain}`;
|
|
91
93
|
}
|
|
92
94
|
exports.setUSPrivacyCookie = setUSPrivacyCookie;
|
package/dist/esm/main.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const NO_PRIVACY_COOKIE = "no-privacy-cookie";
|
|
2
2
|
declare global {
|
|
3
3
|
interface Window {
|
|
4
|
-
__uspapi
|
|
4
|
+
__uspapi?: (command: string, version: number, callback?: Function) => Promise<unknown>;
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
7
|
export declare function getUsPrivacyCookie(): string | null;
|
|
@@ -13,12 +13,12 @@ export declare function __uspapi(command: string, version: number, callback?: Fu
|
|
|
13
13
|
/**
|
|
14
14
|
* Expose a javascript function on the global `window` object that can be called
|
|
15
15
|
* by third party scripts to determine if the current user has opted out of CCPA
|
|
16
|
-
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/
|
|
16
|
+
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/HEAD/CCPA/USP%20API.md
|
|
17
17
|
*/
|
|
18
18
|
export declare function setUSPrivacy(): void;
|
|
19
19
|
/**
|
|
20
20
|
* Set a cookie based on the IAB US Privacy spec
|
|
21
|
-
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/
|
|
21
|
+
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/HEAD/CCPA/US%20Privacy%20String.md
|
|
22
22
|
*
|
|
23
23
|
* @param consent - Does the user have consent for CCPA
|
|
24
24
|
* @param domain - An optional explicit domain for the cookie
|
package/dist/esm/main.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/ban-types */
|
|
1
2
|
import { fetchLegislation } from "@financial-times/privacy-legislation-client";
|
|
2
3
|
export const NO_PRIVACY_COOKIE = "no-privacy-cookie";
|
|
3
4
|
export function getUsPrivacyCookie() {
|
|
@@ -60,7 +61,7 @@ export async function __uspapi(command, version, callback) {
|
|
|
60
61
|
/**
|
|
61
62
|
* Expose a javascript function on the global `window` object that can be called
|
|
62
63
|
* by third party scripts to determine if the current user has opted out of CCPA
|
|
63
|
-
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/
|
|
64
|
+
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/HEAD/CCPA/USP%20API.md
|
|
64
65
|
*/
|
|
65
66
|
export function setUSPrivacy() {
|
|
66
67
|
if (typeof window.__uspapi === "function") {
|
|
@@ -70,7 +71,7 @@ export function setUSPrivacy() {
|
|
|
70
71
|
}
|
|
71
72
|
/**
|
|
72
73
|
* Set a cookie based on the IAB US Privacy spec
|
|
73
|
-
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/
|
|
74
|
+
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/HEAD/CCPA/US%20Privacy%20String.md
|
|
74
75
|
*
|
|
75
76
|
* @param consent - Does the user have consent for CCPA
|
|
76
77
|
* @param domain - An optional explicit domain for the cookie
|
|
@@ -80,5 +81,6 @@ export function setUSPrivacyCookie(consent, domain) {
|
|
|
80
81
|
// and we are not trying to make it this work for every possible subdomain yet
|
|
81
82
|
domain = domain || (document.location.hostname || "").replace("www.", "");
|
|
82
83
|
const uspString = `1Y${consent ? "N" : "Y"}N`;
|
|
83
|
-
|
|
84
|
+
const maxAge = 60 * 60 * 24 * 365 * 5;
|
|
85
|
+
document.cookie = `usprivacy=${uspString};max-age=${maxAge};path=/;domain=${domain}`;
|
|
84
86
|
}
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/privacy-us-privacy",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"main": "dist/cjs/main.js",
|
|
6
6
|
"module": "dist/esm/main.js",
|
|
7
7
|
"types": "dist/cjs/main.d.ts",
|
|
8
8
|
"private": false,
|
|
9
9
|
"devDependencies": {
|
|
10
|
-
"@types/js-cookie": "^
|
|
11
|
-
"js-cookie": "^
|
|
10
|
+
"@types/js-cookie": "^3.0.3",
|
|
11
|
+
"js-cookie": "^3.0.5",
|
|
12
12
|
"npm-run-all": "4.1.5"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@financial-times/privacy-legislation-client": "
|
|
15
|
+
"@financial-times/privacy-legislation-client": "file:../legislation-client"
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
18
|
"test": "jest",
|
|
@@ -22,4 +22,4 @@
|
|
|
22
22
|
"prebuild": "npm run clean",
|
|
23
23
|
"build": "run-p build:*"
|
|
24
24
|
}
|
|
25
|
-
}
|
|
25
|
+
}
|
package/src/main.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/ban-types */
|
|
2
|
+
|
|
1
3
|
import { fetchLegislation } from "@financial-times/privacy-legislation-client";
|
|
2
4
|
|
|
3
5
|
export const NO_PRIVACY_COOKIE = "no-privacy-cookie";
|
|
4
6
|
|
|
5
7
|
declare global {
|
|
6
8
|
interface Window {
|
|
7
|
-
__uspapi
|
|
9
|
+
__uspapi?: (command: string, version: number, callback?: Function) => Promise<unknown>;
|
|
8
10
|
}
|
|
9
11
|
}
|
|
10
12
|
|
|
@@ -86,7 +88,7 @@ export async function __uspapi(
|
|
|
86
88
|
/**
|
|
87
89
|
* Expose a javascript function on the global `window` object that can be called
|
|
88
90
|
* by third party scripts to determine if the current user has opted out of CCPA
|
|
89
|
-
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/
|
|
91
|
+
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/HEAD/CCPA/USP%20API.md
|
|
90
92
|
*/
|
|
91
93
|
export function setUSPrivacy(): void {
|
|
92
94
|
if (typeof window.__uspapi === "function") {
|
|
@@ -97,7 +99,7 @@ export function setUSPrivacy(): void {
|
|
|
97
99
|
|
|
98
100
|
/**
|
|
99
101
|
* Set a cookie based on the IAB US Privacy spec
|
|
100
|
-
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/
|
|
102
|
+
* https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/HEAD/CCPA/US%20Privacy%20String.md
|
|
101
103
|
*
|
|
102
104
|
* @param consent - Does the user have consent for CCPA
|
|
103
105
|
* @param domain - An optional explicit domain for the cookie
|
|
@@ -107,5 +109,6 @@ export function setUSPrivacyCookie(consent: boolean, domain?: string): void {
|
|
|
107
109
|
// and we are not trying to make it this work for every possible subdomain yet
|
|
108
110
|
domain = domain || (document.location.hostname || "").replace("www.", "");
|
|
109
111
|
const uspString = `1Y${consent ? "N" : "Y"}N`;
|
|
110
|
-
|
|
112
|
+
const maxAge = 60 * 60 * 24 * 365 * 5;
|
|
113
|
+
document.cookie = `usprivacy=${uspString};max-age=${maxAge};path=/;domain=${domain}`;
|
|
111
114
|
}
|
package/src/test/main.test.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @jest-environment jsdom
|
|
3
3
|
*/
|
|
4
|
+
|
|
5
|
+
import type { RegionalCompliance } from "../../../legislation-client/src/main";
|
|
6
|
+
|
|
4
7
|
import {
|
|
5
8
|
setUSPrivacy,
|
|
6
9
|
setUSPrivacyCookie,
|
|
@@ -11,19 +14,19 @@ import {
|
|
|
11
14
|
import * as legislationClient from "@financial-times/privacy-legislation-client";
|
|
12
15
|
import Cookies from "js-cookie";
|
|
13
16
|
|
|
14
|
-
const mockFetchLegislationCcpa = (): Promise<
|
|
17
|
+
const mockFetchLegislationCcpa = (): Promise<RegionalCompliance> =>
|
|
15
18
|
Promise.resolve({
|
|
16
19
|
region: "CA",
|
|
17
20
|
legislation: new Set(["ccpa"]),
|
|
18
21
|
});
|
|
19
22
|
|
|
20
|
-
const mockFetchLegislationNotCcpa = (): Promise<
|
|
23
|
+
const mockFetchLegislationNotCcpa = (): Promise<RegionalCompliance> =>
|
|
21
24
|
Promise.resolve({
|
|
22
25
|
region: "GB",
|
|
23
26
|
legislation: new Set(["gdpr"]),
|
|
24
27
|
});
|
|
25
28
|
|
|
26
|
-
describe("
|
|
29
|
+
describe("US Privacy", () => {
|
|
27
30
|
beforeEach(() => {
|
|
28
31
|
jest.spyOn(console, "error").mockImplementation((arg) => arg);
|
|
29
32
|
});
|
|
@@ -32,19 +35,19 @@ describe("Us Privacy", () => {
|
|
|
32
35
|
jest.resetAllMocks();
|
|
33
36
|
});
|
|
34
37
|
|
|
35
|
-
it("should not overwrite an existing window.__uspapi() function", async () => {
|
|
36
|
-
window.__uspapi = (): Promise<
|
|
38
|
+
it("should not overwrite an existing window.__uspapi?.() function", async () => {
|
|
39
|
+
window.__uspapi = (): Promise<string> => Promise.resolve("just testing");
|
|
37
40
|
await setUSPrivacy();
|
|
38
|
-
expect(await window.__uspapi("test command", 1)).toEqual("just testing");
|
|
41
|
+
expect(await window.__uspapi?.("test command", 1)).toEqual("just testing");
|
|
39
42
|
delete window.__uspapi;
|
|
40
43
|
});
|
|
41
44
|
|
|
42
|
-
describe("window.__uspapi()", () => {
|
|
45
|
+
describe("window.__uspapi?.()", () => {
|
|
43
46
|
test("should console.error and return if called with command != `getUSPData`", () => {
|
|
44
47
|
jest.spyOn(legislationClient, "fetchLegislation");
|
|
45
48
|
const cb = jest.fn();
|
|
46
49
|
setUSPrivacy();
|
|
47
|
-
window.__uspapi("fake-command", 1, cb);
|
|
50
|
+
window.__uspapi?.("fake-command", 1, cb);
|
|
48
51
|
expect(console.error).toBeCalled();
|
|
49
52
|
expect(legislationClient.fetchLegislation).not.toBeCalled();
|
|
50
53
|
expect(cb).not.toBeCalled();
|
|
@@ -54,7 +57,7 @@ describe("Us Privacy", () => {
|
|
|
54
57
|
jest.spyOn(legislationClient, "fetchLegislation");
|
|
55
58
|
const cb = jest.fn();
|
|
56
59
|
setUSPrivacy();
|
|
57
|
-
window.__uspapi("getUSPData", 2, cb);
|
|
60
|
+
window.__uspapi?.("getUSPData", 2, cb);
|
|
58
61
|
expect(console.error).toBeCalled();
|
|
59
62
|
expect(legislationClient.fetchLegislation).not.toBeCalled();
|
|
60
63
|
expect(cb).not.toBeCalled();
|
|
@@ -63,7 +66,7 @@ describe("Us Privacy", () => {
|
|
|
63
66
|
test("should console.error if callback is not defined", () => {
|
|
64
67
|
jest.spyOn(legislationClient, "fetchLegislation");
|
|
65
68
|
setUSPrivacy();
|
|
66
|
-
window.__uspapi("getUSPData", 1);
|
|
69
|
+
window.__uspapi?.("getUSPData", 1);
|
|
67
70
|
expect(console.error).toBeCalled();
|
|
68
71
|
expect(legislationClient.fetchLegislation).not.toBeCalled();
|
|
69
72
|
});
|
|
@@ -75,7 +78,7 @@ describe("Us Privacy", () => {
|
|
|
75
78
|
});
|
|
76
79
|
const cb = jest.fn();
|
|
77
80
|
setUSPrivacy();
|
|
78
|
-
window.__uspapi("getUSPData", 1, cb);
|
|
81
|
+
window.__uspapi?.("getUSPData", 1, cb);
|
|
79
82
|
expect(cb).toBeCalledWith(undefined, false);
|
|
80
83
|
});
|
|
81
84
|
});
|
|
@@ -89,7 +92,7 @@ describe("Us Privacy", () => {
|
|
|
89
92
|
Cookies.set("usprivacy", "fake-value");
|
|
90
93
|
const cb = jest.fn();
|
|
91
94
|
setUSPrivacy();
|
|
92
|
-
await window.__uspapi("getUSPData", 1, cb);
|
|
95
|
+
await window.__uspapi?.("getUSPData", 1, cb);
|
|
93
96
|
expect(cb).toBeCalledWith(
|
|
94
97
|
{
|
|
95
98
|
version: 1,
|
|
@@ -108,7 +111,7 @@ describe("Us Privacy", () => {
|
|
|
108
111
|
Cookies.remove("usprivacy");
|
|
109
112
|
const cb = jest.fn();
|
|
110
113
|
setUSPrivacy();
|
|
111
|
-
await window.__uspapi("getUSPData", 1, cb);
|
|
114
|
+
await window.__uspapi?.("getUSPData", 1, cb);
|
|
112
115
|
expect(cb).toBeCalledWith(
|
|
113
116
|
{
|
|
114
117
|
version: 1,
|
|
@@ -129,7 +132,7 @@ describe("Us Privacy", () => {
|
|
|
129
132
|
const cb = jest.fn();
|
|
130
133
|
Cookies.set("usprivacy", "fake-value");
|
|
131
134
|
setUSPrivacy();
|
|
132
|
-
await window.__uspapi("getUSPData", 1, cb);
|
|
135
|
+
await window.__uspapi?.("getUSPData", 1, cb);
|
|
133
136
|
expect(cb).toBeCalledWith(
|
|
134
137
|
{
|
|
135
138
|
version: 1,
|
|
@@ -148,7 +151,7 @@ describe("Us Privacy", () => {
|
|
|
148
151
|
const cb = jest.fn();
|
|
149
152
|
Cookies.remove("usprivacy");
|
|
150
153
|
setUSPrivacy();
|
|
151
|
-
await window.__uspapi("getUSPData", 1, cb);
|
|
154
|
+
await window.__uspapi?.("getUSPData", 1, cb);
|
|
152
155
|
expect(cb).toBeCalledWith(
|
|
153
156
|
{
|
|
154
157
|
version: 1,
|
|
@@ -191,5 +194,37 @@ describe("Us Privacy", () => {
|
|
|
191
194
|
expect(getUsPrivacyForTracking()).toEqual(NO_PRIVACY_COOKIE);
|
|
192
195
|
});
|
|
193
196
|
});
|
|
197
|
+
|
|
198
|
+
describe("when providing an explicit cookie domain", () => {
|
|
199
|
+
let setCookieSpy: jest.SpyInstance;
|
|
200
|
+
|
|
201
|
+
beforeAll(() => {
|
|
202
|
+
setCookieSpy = jest.spyOn(document, "cookie", "set");
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
afterAll(() => {
|
|
206
|
+
setCookieSpy.mockRestore();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe("User has given CCPA consent (opted in)", () => {
|
|
210
|
+
test("should set the `usprivacy` cookie to `1YNN` under the specified domain", () => {
|
|
211
|
+
setUSPrivacyCookie(true, ".ftadviser.com");
|
|
212
|
+
expect(setCookieSpy).toHaveBeenCalledWith(
|
|
213
|
+
// max-age should be 31536000 seconds (1 year)
|
|
214
|
+
"usprivacy=1YNN;max-age=157680000;path=/;domain=.ftadviser.com"
|
|
215
|
+
);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe("User has NOT given CCPA consent (opted out)", () => {
|
|
220
|
+
test("should set the `usprivacy` cookie to `1YYN` under the specified domain", () => {
|
|
221
|
+
setUSPrivacyCookie(false, ".ftadviser.com");
|
|
222
|
+
// max-age should be 31536000 seconds (1 year)
|
|
223
|
+
expect(setCookieSpy).toHaveBeenCalledWith(
|
|
224
|
+
"usprivacy=1YYN;max-age=157680000;path=/;domain=.ftadviser.com"
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
});
|
|
194
229
|
});
|
|
195
230
|
});
|