Skip to content

Commit

Permalink
1171 cookie consent clean up (#1199)
Browse files Browse the repository at this point in the history
**Related Ticket:**
#1171

### Description of Changes

- Relocating cookie retrieval, validation, and creation functionality
from `layoutRoot` to `cookieConsentForm`
- Implementing `session item` to track when a session has begun for each
individual user and only run validation and retrieval functionality on
session start and when a response has not been recorded.
- Adjusting Banner content to accept markdown in config props.  

### Notes & Questions About Changes

### Validation / Testing
Clear out all cookies in your local machine to do so: open `dev tools`
-> navigate to `application tab`-> navigate to `cookies` in the left
panel -> right click `clear`
- After clearing your existing site cookies, navigate to any page. Click
on **Decline**. Navigate to another page and you should not see the
cookie consent form component.
- Clearing your existing site cookies again, navigate to any page. Click
on **Accept**. Navigate to another page and you should not see the
cookie consent form component.
- Clearing your existing site cookies again, navigate to any page. Click
on **X**. Navigate to another page and you should see the cookie consent
form component rerendered.
  • Loading branch information
snmln authored Nov 6, 2024
2 parents 572459e + 598ac2a commit d2bc0e5
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 158 deletions.
66 changes: 40 additions & 26 deletions app/scripts/components/common/banner/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React, { useState } from "react";
import { Icon } from "@trussworks/react-uswds";
import { USWDSBanner, USWDSBannerContent } from "$components/common/uswds/banner";
import React, { useState } from 'react';
import { Icon } from '@trussworks/react-uswds';
import {
USWDSBanner,
USWDSBannerContent
} from '$components/common/uswds/banner';

const BANNER_KEY = 'dismissedBannerUrl';

Expand All @@ -12,53 +15,64 @@ function hasExpired(expiryDatetime) {

enum BannerType {
info = 'info',
warning ='warning'
warning = 'warning'
}

const infoTypeFlag = BannerType.info;
interface BannerProps {
appTitle: string,
expires: Date,
url: string,
text: string,
type?: BannerType
appTitle: string;
expires: Date;
url: string;
text: string;
type?: BannerType;
}

export default function Banner({appTitle, expires, url, text, type = infoTypeFlag }: BannerProps) {
export default function Banner({
appTitle,
expires,
url,
text,
type = infoTypeFlag
}: BannerProps) {

const showBanner = localStorage.getItem(BANNER_KEY) !== url;
const [isOpen, setIsOpen] = useState(showBanner && !(hasExpired(expires)));
const [isOpen, setIsOpen] = useState(showBanner && !hasExpired(expires));

function onClose () {
localStorage.setItem(
BANNER_KEY,
url
);
function onClose() {
localStorage.setItem(BANNER_KEY, url);
setIsOpen(false);
}

return (
<div>
{isOpen &&
(<div className='position-relative'>
<USWDSBanner aria-label={appTitle} className={type !== infoTypeFlag? 'bg-secondary-lighter': ''}>
{isOpen && (
<div className='position-relative'>
<USWDSBanner
aria-label={appTitle}
className={type !== infoTypeFlag ? 'bg-secondary-lighter' : ''}
>
<a href={url} target='_blank' rel='noreferrer'>
<USWDSBannerContent className='padding-top-1 padding-bottom-1' isOpen={true}>
<p dangerouslySetInnerHTML={{ __html: text }} />
<USWDSBannerContent
className='padding-top-1 padding-bottom-1'
isOpen={true}
>
<div dangerouslySetInnerHTML={{ __html: text }} />

</USWDSBannerContent>
</a>
</USWDSBanner>
<div className='position-absolute top-0 right-0 margin-right-3 height-full display-flex'>
<button
<button
className='usa-button usa-button--unstyled'
type='button'
aria-label='Close Banner'
onClick={onClose}
>
<Icon.Close />
</button>
>
<Icon.Close />
</button>
</div>
</div>)}
</div>
)}
</div>
);
}
68 changes: 49 additions & 19 deletions app/scripts/components/common/cookie-consent/cookieConsent.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,49 @@ import React from 'react';
import '@testing-library/jest-dom';

import { render, screen, fireEvent } from '@testing-library/react';
import { COOKIE_CONSENT_KEY } from './utils';
import { CookieConsent } from './index';
import { MemoryRouter } from 'react-router-dom'; // For testing
import { createMemoryHistory } from 'history';

import * as utils from './utils';
import CookieConsent from './index';
const lodash = require('lodash');

describe('Cookie consent form should render with correct content.', () => {
const setDisplayCookieConsent = jest.fn();
const setGoogleTagManager = jest.fn();
const cookieData = {
title: 'Cookie Consent',
copy: '<p>We use cookies to enhance your browsing experience and to help us understand how our website is used. These cookies allow us to collect data on site usage and improve our services based on your interactions. To learn more about it, see our <a href="https://www.nasa.gov/privacy/#cookies">Privacy Policy</a></p>We use cookies to enhance your browsing experience and to help us understand how our website is used. These cookies allow us to collect data on site usage and improve our services based on your interactions. To learn more about it, see our [Privacy Policy](https://www.nasa.gov/privacy/#cookies)'
copy: '<p>We use cookies to enhance your browsing experience and to help us understand how our website is used. These cookies allow us to collect data on site usage and improve our services based on your interactions. To learn more about it, see our <a href="https://www.nasa.gov/privacy/#cookies">Privacy Policy</a></p>We use cookies to enhance your browsing experience and to help us understand how our website is used. These cookies allow us to collect data on site usage and improve our services based on your interactions. To learn more about it, see our [Privacy Policy](https://www.nasa.gov/privacy/#cookies)',
setDisplayCookieConsent,
setGoogleTagManager
};

const onFormInteraction = jest.fn();
beforeEach(() => {
render(
<CookieConsent {...cookieData} onFormInteraction={onFormInteraction} />
);

const history = createMemoryHistory({ initialEntries: ['/home'] });

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: () => ({
pathname: 'localhost:3000/example/path'
})
}));

lodash.debounce = jest.fn((fn) => fn);

afterEach(() => {
jest.clearAllMocks();

// Clear cookies after each test
document.cookie = `${utils.COOKIE_CONSENT_KEY}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
});

it('Renders correct content', () => {
render(
<MemoryRouter history={history}>
<CookieConsent {...cookieData} onFormInteraction={onFormInteraction} />
</MemoryRouter>
);
expect(
screen.getByRole('link', { name: 'Privacy Policy' })
).toHaveAttribute('href', 'https://www.nasa.gov/privacy/#cookies');
Expand All @@ -34,30 +62,32 @@ describe('Cookie consent form should render with correct content.', () => {
).toBeInTheDocument();
});

it('Check correct cookie initialization', () => {
const resultCookie = document.cookie;

expect(resultCookie).toBe(
`${COOKIE_CONSENT_KEY}={"responded":false,"answer":false}`
);
});

it('Check correct cookie content on Decline click', () => {
render(
<MemoryRouter history={history}>
<CookieConsent {...cookieData} onFormInteraction={onFormInteraction} />
</MemoryRouter>
);
const button = screen.getByRole('button', { name: 'Decline Cookies' });
fireEvent.click(button);
const resultCookie = document.cookie;
expect(resultCookie).toBe(
`${COOKIE_CONSENT_KEY}={"responded":true,"answer":false}`
`${utils.COOKIE_CONSENT_KEY}={"responded":true,"answer":false}`
);
});

it('Check correct cookie content on Accept click', () => {
const button = screen.getByRole('button', { name: 'Accept Cookies' });
fireEvent.click(button);
render(
<MemoryRouter history={history}>
<CookieConsent {...cookieData} onFormInteraction={onFormInteraction} />
</MemoryRouter>
);
const acceptButton = screen.getByRole('button', { name: 'Accept Cookies' });
fireEvent.click(acceptButton);
const resultCookie = document.cookie;

expect(resultCookie).toBe(
`${COOKIE_CONSENT_KEY}={"responded":true,"answer":true}`
`${utils.COOKIE_CONSENT_KEY}={"responded":true,"answer":true}`
);
});
});
Loading

0 comments on commit d2bc0e5

Please sign in to comment.