Skip to content

Commit

Permalink
Fix Fides.shouldShouldShowExperience() to return false for modal-only…
Browse files Browse the repository at this point in the history
… experiences (#5281)
  • Loading branch information
NevilleS committed Sep 12, 2024
1 parent aa37211 commit 47934f2
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ The types of changes are:

### Fixed
- Fix wording in tooltip for Yotpo Reviews [#5274](https://github.com/ethyca/fides/pull/5274)
- Fix Fides.shouldShouldShowExperience() to return false for modal-only experiences [#5281](https://github.com/ethyca/fides/pull/5281)


## [2.44.0](https://github.com/ethyca/fides/compare/2.43.1...2.44.0)
Expand Down
6 changes: 5 additions & 1 deletion clients/fides-js/src/lib/consent-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,17 @@ export const shouldResurfaceConsent = (
cookie: FidesCookie,
savedConsent: NoticeConsent,
): boolean => {
// Always resurface consent for TCF unless the saved version_hash matches
if (experience.experience_config?.component === ComponentType.TCF_OVERLAY) {
if (experience.meta?.version_hash) {
return experience.meta.version_hash !== cookie.tcf_version_hash;
}
// Ensure we always resurface consent for TCF if for some reason experience does not have version_hash
return true;
}
// Never surface consent for modal-only experiences
if (experience.experience_config?.component === ComponentType.MODAL) {
return false;
}
// Do not surface consent for null or empty notices
if (!(experience as PrivacyExperience)?.privacy_notices?.length) {
return false;
Expand Down
5 changes: 5 additions & 0 deletions clients/fides-js/src/lib/cookie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ export const updateExperienceFromCookieConsentNotices = ({
cookie: FidesCookie;
debug?: boolean;
}): PrivacyExperience => {
// If the given experience has no notices, return immediately and do not mutate
// the experience object in any way
if (!experience.privacy_notices) {
return experience;
}
// DEFER (PROD-1568) - instead of updating experience here, push this logic into UI
const noticesWithConsent: PrivacyNoticeWithPreference[] | undefined =
experience.privacy_notices?.map((notice) => {
Expand Down
150 changes: 150 additions & 0 deletions clients/privacy-center/cypress/e2e/should-show-experience.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import {
CONSENT_COOKIE_NAME,
NoticeConsent,
PrivacyExperience,
} from "fides-js";

import { mockCookie } from "../support/mocks";
import { OVERRIDE, stubConfig, stubTCFExperience } from "../support/stubs";

describe("Fides.shouldShowExperience()", () => {
interface TestCaseOptions {
fixture:
| "experience_modal.json"
| "experience_banner_modal.json"
| "experience_tcf_minimal.json"
| "experience_none.json";
savedConsent: boolean;
expiredTcfVersionHash?: boolean;
shouldShowExperience: boolean;
}

const testCases: TestCaseOptions[] = [
{
fixture: "experience_modal.json",
savedConsent: false,
shouldShowExperience: false,
},
{
fixture: "experience_modal.json",
savedConsent: true,
shouldShowExperience: false,
},
{
fixture: "experience_banner_modal.json",
savedConsent: false,
shouldShowExperience: true,
},
{
fixture: "experience_banner_modal.json",
savedConsent: true,
shouldShowExperience: false,
},
{
fixture: "experience_tcf_minimal.json",
savedConsent: false,
shouldShowExperience: true,
},
{
fixture: "experience_tcf_minimal.json",
savedConsent: true,
shouldShowExperience: false,
},
{
fixture: "experience_tcf_minimal.json",
savedConsent: true,
expiredTcfVersionHash: true,
shouldShowExperience: true,
},
{
fixture: "experience_none.json",
savedConsent: false,
shouldShowExperience: false,
},
{
fixture: "experience_none.json",
savedConsent: true,
shouldShowExperience: false,
},
];

testCases.forEach(
({
fixture,
savedConsent,
expiredTcfVersionHash,
shouldShowExperience,
}) => {
describe(`when rendering ${fixture} and saved consent ${savedConsent ? "exists" : "does not exist"} ${expiredTcfVersionHash ? "(with expired tcf_version_hash)" : ""}`, () => {
it(`Fides.shouldShowExperience() returns ${shouldShowExperience}`, () => {
cy.fixture(`consent/${fixture}`).then((data) => {
let experience: PrivacyExperience = data.items[0] || OVERRIDE.EMPTY;
const tcfEnabled = /tcf/.test(fixture);

// If the test requires it, generate and save a prior consent cookie
if (savedConsent) {
// Mock an opt-out consent for each notice, plus an "example" other notice
const notices = [
...(experience.privacy_notices || []),
...[{ notice_key: "example" }],
];
const consent: NoticeConsent = Object.fromEntries(
notices.map((e) => [e.notice_key, false]),
);

// Mock a saved fides_string if tcf is enabled
const fides_string = tcfEnabled
? "CPzevcAPzevcAGXABBENATEIAAIAAAAAAAAAAAAAAAAA"
: undefined;

// Save a tcf_version_hash that matches the experience
let tcf_version_hash = experience.meta?.version_hash;

// Mock an "expired" hash, if the test demands it
if (expiredTcfVersionHash) {
tcf_version_hash = "1a2a3a";
}

// Save the mock cookie
const cookie = mockCookie({
consent,
fides_string,
tcf_version_hash,
});
cy.setCookie(CONSENT_COOKIE_NAME, JSON.stringify(cookie));
}

// Load the demo page with our stubbed config
cy.log("using experience = ", experience);
if (!tcfEnabled) {
stubConfig({ experience, options: { isOverlayEnabled: true } });
} else {
stubTCFExperience({});
}
});
cy.waitUntilFidesInitialized();

// Check that our test saved the consent cookie correctly
if (savedConsent) {
cy.getCookie(CONSENT_COOKIE_NAME).should("exist");
} else {
cy.getCookie(CONSENT_COOKIE_NAME).should("not.exist");
}

// Check if shouldShowExperience() returns the expected value
cy.window()
.its("Fides")
.invoke("shouldShowExperience")
.should("eql", shouldShowExperience);

// If shouldShowExperience() is true, the banner should show as well
if (shouldShowExperience) {
cy.get("div#fides-banner").should("be.visible");
} else {
cy.get("div#fides-banner").should("not.exist");
}
});
});
},
);
});
6 changes: 0 additions & 6 deletions clients/privacy-center/cypress/e2e/show-modal.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ describe("Fides.showModal", () => {
options: {
isOverlayEnabled: true,
},
experience: {
show_banner: false,
},
});
});

Expand Down Expand Up @@ -53,9 +50,6 @@ describe("Fides.showModal", () => {
options: {
isOverlayEnabled: false,
},
experience: {
show_banner: false,
},
});
});

Expand Down
121 changes: 121 additions & 0 deletions clients/privacy-center/cypress/fixtures/consent/experience_modal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
{
"items": [
{
"region": "us_ca",
"available_locales": ["en", "es", "fr-CA"],
"experience_config": {
"translations": [
{
"language": "en",
"accept_button_label": "Opt in to all",
"acknowledge_button_label": "OK",
"banner_description": "[banner] We use cookies and similar methods to recognize visitors and remember their preferences. We may also use them to measure ad campaign effectiveness, target ads, and analyze site traffic. Depending on your location, you may opt-in or opt out of the use of these technologies.",
"banner_title": "[banner] Manage your consent preferences",
"description": "We use cookies and similar methods to recognize visitors and remember their preferences. We may also use them to measure ad campaign effectiveness, target ads, and analyze site traffic. Depending on your location, you may opt-in or opt out of the use of these technologies.",
"modal_link_label": "Manage my consent preferences",
"is_default": true,
"privacy_policy_link_label": "Privacy Policy",
"privacy_policy_url": "https://privacy.example.com/",
"privacy_preferences_link_label": "Manage preferences",
"reject_button_label": "Opt out of all",
"save_button_label": "Save",
"title": "Manage your consent preferences",
"privacy_experience_config_history_id": "pri_exp-history-modal-en-000"
},
{
"language": "es",
"accept_button_label": "Participar en todo",
"acknowledge_button_label": "Aceptar",
"banner_description": "[banner] Usamos cookies y métodos similares para reconocer a los visitantes y recordar sus preferencias. También podemos usarlos para medir la eficacia de campañas publicitarias, dirigir anuncios y analizar el tráfico del sitio. En función de su ubicación, puede optar por participar o no en el uso de estas tecnologías.",
"banner_title": "[banner] Administrar sus preferencias de consentimiento",
"description": "Usamos cookies y métodos similares para reconocer a los visitantes y recordar sus preferencias. También podemos usarlos para medir la eficacia de campañas publicitarias, dirigir anuncios y analizar el tráfico del sitio. En función de su ubicación, puede optar por participar o no en el uso de estas tecnologías.",
"modal_link_label": "Administrar mis preferencias de consentimiento",
"is_default": false,
"privacy_policy_link_label": "Política de privacidad",
"privacy_policy_url": "https://privacy.example.com/",
"privacy_preferences_link_label": "Administrar preferencias",
"reject_button_label": "No participar en nada",
"save_button_label": "Guardar",
"title": "Administrar sus preferencias de consentimiento",
"privacy_experience_config_history_id": "pri_exp-history-modal-es-000"
},
{
"language": "fr-CA",
"accept_button_label": "Tout activer",
"acknowledge_button_label": "OK",
"banner_description": "[banner] Nous utilisons des témoins et des méthodes similaires pour reconnaitre les visiteurs et se souvenir de leurs préférences. Nous pouvons également les utiliser pour mesurer l’efficacité des campagnes de publicité, cibler les annonces et analyser le trafic du site. Selon votre emplacement, vous pouvez activer ou désactiver l’utilisation de ces technologies.",
"banner_title": "[banner] Gestion de vos préférences de consentement",
"description": "Nous utilisons des témoins et des méthodes similaires pour reconnaitre les visiteurs et se souvenir de leurs préférences. Nous pouvons également les utiliser pour mesurer l’efficacité des campagnes de publicité, cibler les annonces et analyser le trafic du site. Selon votre emplacement, vous pouvez activer ou désactiver l’utilisation de ces technologies.",
"modal_link_label": "Gérer mes préférences de consentement",
"is_default": false,
"privacy_policy_link_label": "Politique de confidentialité",
"privacy_preferences_link_label": "Gestion des préférences",
"reject_button_label": "Tout désactiver",
"save_button_label": "Sauvegarder",
"title": "Gestion de vos préférences de consentement",
"privacy_experience_config_history_id": "pri_exp-history-modal-fr-ca-000"
}
],
"language": "en",
"dismissable": true,
"show_layer1_notices": false,
"layer1_button_options": "opt_in_opt_out",
"allow_language_selection": true,
"auto_detect_language": true,
"disabled": false,
"id": "pri_exp-modal-000",
"component": "modal",
"created_at": "2024-01-01T12:00:00.000000+00:00",
"updated_at": "2024-01-01T12:00:00.000000+00:00"
},
"id": "pri_exp-003-exp_modal",
"created_at": "2024-01-01T12:00:00.000000+00:00",
"updated_at": "2024-01-01T12:00:00.000000+00:00",
"privacy_notices": [
{
"name": "Data Sales and Sharing",
"notice_key": "data_sales_and_sharing",
"internal_description": null,
"origin": null,
"consent_mechanism": "opt_out",
"data_uses": [
"marketing.advertising.first_party.targeted",
"marketing.advertising.third_party.targeted"
],
"enforcement_level": "frontend",
"disabled": false,
"has_gpc_flag": false,
"id": "pri_notice-data-sales-000",
"created_at": "2024-01-01T12:00:00.000000+00:00",
"updated_at": "2024-01-01T12:00:00.000000+00:00",
"default_preference": "opt_in",
"cookies": [],
"translations": [
{
"language": "en",
"title": "Data Sales and Sharing",
"description": "We may transfer or share your personal information to third parties in exchange for monetary or other valuable consideration or for the purposes of cross-contextual targeted advertising. You can learn more about what information is used for this purpose in our privacy notice.",
"privacy_notice_history_id": "pri_notice-history-data-sales-en-000"
},
{
"language": "es",
"title": "Venta e intercambio de datos",
"description": "Podemos transferir o compartir su información personal con terceros a cambio de una contraprestación monetaria u otro tipo de valor o con fines de publicidad dirigida en contextos cruzados. En nuestra política de privacidad encontrará más detalles sobre qué tipo de información se usa para este fin.",
"privacy_notice_history_id": "pri_notice-history-data-sales-es-000"
},
{
"language": "fr-CA",
"title": "Ventes et partage de données",
"description": "Nous pouvons transférer à ou partager vos informations personnelles avec des parties tierces en échange de contrepartie monétaire ou d’autres facteurs valables ou encore dans le but de publicité ciblée contextuelle croisée. Vous pouvez en apprendre plus sur l’information utilisée à ces fins dans notre avis de confidentialité.",
"privacy_notice_history_id": "pri_notice-history-data-sales-fr-ca-000"
}
]
}
],
"gvl": {}
}
],
"total": 1,
"page": 1,
"size": 50
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"items": [],
"total": 0,
"page": 1,
"size": 50
}

0 comments on commit 47934f2

Please sign in to comment.