Skip to content

Commit deef26b

Browse files
authored
Merge Full TCF in to window.Fides.experience after successful fetch (#5726)
1 parent f831741 commit deef26b

File tree

5 files changed

+111
-51
lines changed

5 files changed

+111
-51
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Changes can also be flagged with a GitHub label for tracking purposes. The URL o
2929
- Fixed `fides annotate dataset` command enters incorrect value on the `direction` field. [#5727](https://github.com/ethyca/fides/pull/5727)
3030
- Fixed Bigquery flakey tests. [#5713](https://github.com/ethyca/fides/pull/5713)
3131
- Fixed breadcrumb navigation issues in data catalog view [#5717](https://github.com/ethyca/fides/pull/5717)
32+
- Fixed `window.Fides.experience` of FidesJS to be a merged version of the minimal and full experience. [#5726](https://github.com/ethyca/fides/pull/5726)
3233

3334
## [2.54.0](https://github.com/ethyca/fides/compare/2.53.0...2.54.0)
3435

clients/fides-js/src/components/tcf/TcfOverlay.tsx

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import {
1111
PrivacyExperienceMinimal,
1212
ServingComponent,
1313
} from "../../lib/consent-types";
14-
import { isPrivacyExperience } from "../../lib/consent-utils";
14+
import {
15+
experienceIsValid,
16+
isPrivacyExperience,
17+
} from "../../lib/consent-utils";
1518
import { dispatchFidesEvent } from "../../lib/events";
1619
import { useNoticesServed } from "../../lib/hooks";
1720
import {
@@ -141,6 +144,7 @@ export const TcfOverlay = ({
141144
isGVLLangLoading = false;
142145
});
143146
}
147+
fidesDebugger("Fetching full TCF experience...");
144148
fetchExperience({
145149
userLocationString: fidesRegionString,
146150
fidesApiUrl: options.fidesApiUrl,
@@ -151,17 +155,29 @@ export const TcfOverlay = ({
151155
if (isPrivacyExperience(result)) {
152156
// include user preferences from the cookie
153157
const userPrefs = buildUserPrefs(result, cookie);
154-
const fullExperience: PrivacyExperience = { ...result, ...userPrefs };
155158

156-
setExperience(fullExperience);
157-
loadMessagesFromExperience(i18n, fullExperience, translationOverrides);
158-
if (!userlocale || bestLocale === defaultLocale) {
159-
// English (default) GVL translations are part of the full experience, so we load them here.
160-
loadGVLMessagesFromExperience(i18n, fullExperience);
161-
} else {
162-
setCurrentLocale(bestLocale);
163-
if (!isGVLLangLoading) {
164-
setIsI18nLoading(false);
159+
if (experienceIsValid(result)) {
160+
const fullExperience: PrivacyExperience = { ...result, ...userPrefs };
161+
window.Fides.experience = {
162+
...window.Fides.experience,
163+
...fullExperience,
164+
};
165+
window.Fides.experience.minimal_tcf = false;
166+
167+
setExperience(fullExperience);
168+
loadMessagesFromExperience(
169+
i18n,
170+
fullExperience,
171+
translationOverrides,
172+
);
173+
if (!userlocale || bestLocale === defaultLocale) {
174+
// English (default) GVL translations are part of the full experience, so we load them here.
175+
loadGVLMessagesFromExperience(i18n, fullExperience);
176+
} else {
177+
setCurrentLocale(bestLocale);
178+
if (!isGVLLangLoading) {
179+
setIsI18nLoading(false);
180+
}
165181
}
166182
}
167183
}

clients/privacy-center/cypress/e2e/consent-banner-tcf.cy.ts

Lines changed: 80 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
FidesCookie,
77
FidesEndpointPaths,
88
PrivacyExperience,
9+
PrivacyExperienceMinimal,
910
} from "fides-js";
1011
import { NoticeConsent } from "fides-js/src/lib/consent-types";
1112
import { FIDES_SEPARATOR } from "fides-js/src/lib/tcf/constants";
@@ -215,6 +216,49 @@ describe("Fides-js TCF", () => {
215216
});
216217
});
217218

219+
describe("Payload optimization", () => {
220+
beforeEach(() => {
221+
cy.getCookie(CONSENT_COOKIE_NAME).should("not.exist");
222+
stubTCFExperience({});
223+
});
224+
it("merges full experience with minimal after successful fetch", () => {
225+
cy.window().then((win) => {
226+
cy.fixture("consent/experience_tcf.json").then((payload) => {
227+
cy.wait("@getPrivacyExperience");
228+
expect(
229+
(win.Fides.experience as PrivacyExperienceMinimal)
230+
.tcf_purpose_consent_ids,
231+
).to.have.length(11);
232+
expect((win.Fides.experience as any).tcf_purpose_consents).to.not
233+
.exist;
234+
cy.waitUntilFidesInitialized().then(() => {
235+
const experience = payload.items[0];
236+
const updatedExperience = {
237+
...experience,
238+
tcf_purpose_consents: [],
239+
};
240+
stubTCFExperience({
241+
experienceFullOverride: updatedExperience,
242+
});
243+
cy.wait("@getPrivacyExperience");
244+
expect(
245+
(
246+
win.Fides.experience as PrivacyExperience &
247+
PrivacyExperienceMinimal
248+
).tcf_purpose_consent_ids,
249+
).to.have.length(11);
250+
expect(
251+
(
252+
win.Fides.experience as PrivacyExperience &
253+
PrivacyExperienceMinimal
254+
).tcf_purpose_consents,
255+
).to.exist.to.have.length(4);
256+
});
257+
});
258+
});
259+
});
260+
});
261+
218262
describe("initial layer", () => {
219263
beforeEach(() => {
220264
cy.getCookie(CONSENT_COOKIE_NAME).should("not.exist");
@@ -223,6 +267,7 @@ describe("Fides-js TCF", () => {
223267
fixture: "consent/notices_served_tcf.json",
224268
}).as("patchNoticesServed");
225269
});
270+
226271
it("can render purposes in the initial layer", () => {
227272
cy.get("div#fides-banner").within(() => {
228273
cy.contains(PURPOSE_2.name);
@@ -511,6 +556,7 @@ describe("Fides-js TCF", () => {
511556
beforeEach(() => {
512557
cy.getCookie(CONSENT_COOKIE_NAME).should("not.exist");
513558
stubTCFExperience({});
559+
cy.wait("@getPrivacyExperience");
514560
cy.intercept("PATCH", `${API_URL}${FidesEndpointPaths.NOTICES_SERVED}`, {
515561
fixture: "consent/notices_served_tcf.json",
516562
}).as("patchNoticesServed");
@@ -1141,44 +1187,42 @@ describe("Fides-js TCF", () => {
11411187

11421188
stubTCFExperience({
11431189
stubOptions: { apiOptions },
1144-
}).then((result) => {
1145-
const privacyExperience = result.response.body.items[0];
1146-
cy.waitUntilFidesInitialized().then(() => {
1147-
cy.get("div#fides-banner").within(() => {
1148-
cy.get("#fides-button-group").within(() => {
1149-
cy.get("button").contains("Manage preferences").click();
1150-
});
1190+
});
1191+
cy.waitUntilFidesInitialized().then(() => {
1192+
cy.get("div#fides-banner").within(() => {
1193+
cy.get("#fides-button-group").within(() => {
1194+
cy.get("button").contains("Manage preferences").click();
11511195
});
1152-
cy.getByTestId("consent-modal").within(() => {
1153-
cy.get("button").contains("Opt out of all").click();
1154-
cy.get("@FidesUpdated")
1155-
.should("have.been.calledOnce")
1156-
.its("lastCall.args.0.detail.extraDetails.consentMethod")
1157-
.then((consentMethod) => {
1158-
expect(consentMethod).to.eql(ConsentMethod.REJECT);
1159-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
1160-
expect(spyObject).to.be.called;
1161-
const spy = spyObject.getCalls();
1162-
const { args } = spy[0];
1163-
expect(args[0]).to.equal(ConsentMethod.REJECT);
1164-
expect(args[1]).to.be.a("object");
1165-
// the TC str is dynamically updated upon save preferences with diff timestamp, so we do a fuzzy match
1166-
expect(args[2]).to.contain("AA,1~");
1167-
expect(args[3]).to.be.a("object");
1168-
// timeout means API call not made, which is expected
1169-
cy.on("fail", (error) => {
1170-
if (error.message.indexOf("Timed out retrying") !== 0) {
1171-
throw error;
1172-
}
1173-
});
1174-
// check that preferences aren't sent to Fides API
1175-
cy.wait("@patchPrivacyPreference", {
1176-
requestTimeout: 100,
1177-
}).then((xhr) => {
1178-
assert.isNull(xhr?.response?.body);
1179-
});
1196+
});
1197+
cy.getByTestId("consent-modal").within(() => {
1198+
cy.get("button").contains("Opt out of all").click();
1199+
cy.get("@FidesUpdated")
1200+
.should("have.been.calledOnce")
1201+
.its("lastCall.args.0.detail.extraDetails.consentMethod")
1202+
.then((consentMethod) => {
1203+
expect(consentMethod).to.eql(ConsentMethod.REJECT);
1204+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
1205+
expect(spyObject).to.be.called;
1206+
const spy = spyObject.getCalls();
1207+
const { args } = spy[0];
1208+
expect(args[0]).to.equal(ConsentMethod.REJECT);
1209+
expect(args[1]).to.be.a("object");
1210+
// the TC str is dynamically updated upon save preferences with diff timestamp, so we do a fuzzy match
1211+
expect(args[2]).to.contain("AA,1~");
1212+
expect(args[3]).to.be.a("object");
1213+
// timeout means API call not made, which is expected
1214+
cy.on("fail", (error) => {
1215+
if (error.message.indexOf("Timed out retrying") !== 0) {
1216+
throw error;
1217+
}
11801218
});
1181-
});
1219+
// check that preferences aren't sent to Fides API
1220+
cy.wait("@patchPrivacyPreference", {
1221+
requestTimeout: 100,
1222+
}).then((xhr) => {
1223+
assert.isNull(xhr?.response?.body);
1224+
});
1225+
});
11821226
});
11831227
});
11841228
});

clients/privacy-center/cypress/e2e/consent-notices.cy.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,9 @@ describe("Privacy notice driven consent", () => {
474474
cy.wait("@getExperience");
475475

476476
cy.getByTestId("consent-item-pri_notice-advertising-000").click();
477+
cy.getByTestId("toggle-Weekly Newsletter").should("be.visible");
477478
cy.getByTestId("toggle-Weekly Newsletter").getToggle().check();
479+
cy.getByTestId("toggle-Monthly Newsletter").should("be.visible");
478480
cy.getByTestId("toggle-Monthly Newsletter").getToggle().check();
479481

480482
cy.getByTestId("save-btn").click();

clients/privacy-center/cypress/support/commands.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Cypress.Commands.add("getByTestId", (selector, ...args) =>
1212
cy.get(`[data-testid='${selector}']`, ...args),
1313
);
1414

15-
Cypress.Commands.add("getToggle", (...args) =>
15+
Cypress.Commands.add("getToggle", (_, ...args) =>
1616
cy.get(`input[type="checkbox"]`, ...args),
1717
);
1818

@@ -121,9 +121,6 @@ Cypress.Commands.add(
121121
visitOptions.qs = queryParams;
122122
}
123123
cy.visit("/fides-js-components-demo.html", visitOptions);
124-
if (options?.options?.tcfEnabled) {
125-
cy.wait("@getPrivacyExperience");
126-
}
127124
},
128125
);
129126

0 commit comments

Comments
 (0)