diff --git a/src/app/content/components/ContentWarning.spec.tsx b/src/app/content/components/ContentWarning.spec.tsx index edb93b435e..57889aec04 100644 --- a/src/app/content/components/ContentWarning.spec.tsx +++ b/src/app/content/components/ContentWarning.spec.tsx @@ -1,28 +1,74 @@ -import React from 'react'; -import { renderToDom } from '../../../test/reactutils'; -import ContentWarning from './ContentWarning'; -import { act } from 'react-dom/test-utils'; -import ReactTestUtils from 'react-dom/test-utils'; import { book as archiveBook } from '../../../test/mocks/archiveLoader'; +import type rendererType from 'react-test-renderer'; +import type { ComponentType } from 'react'; import { mockCmsBook } from '../../../test/mocks/osWebLoader'; +import { reactAndFriends, resetModules } from '../../../test/utils'; import { formatBookData } from '../utils'; + const dummyBook = { ...formatBookData(archiveBook, mockCmsBook), content_warning_text: 'some warning text', }; describe('ContentWarning', () => { - it('renders warning modal', async() => { - renderToDom(); + let React: ReturnType['React']; // tslint:disable-line:variable-name + let ContentWarningDynamic: ComponentType; // tslint:disable-line:variable-name + + describe('in browser', () => { + let renderToDom: ReturnType['renderToDom']; + let ReactDOMTestUtils: ReturnType['ReactDOMTestUtils']; // tslint:disable-line:variable-name + + beforeEach(() => { + resetModules(); + jest.doMock('react', () => { + const react = (jest as any).requireActual('react'); + return { ...react, useEffect: react.useLayoutEffect }; + }); + + ({React, renderToDom, ReactDOMTestUtils} = reactAndFriends()); + + ContentWarningDynamic = require('./ContentWarning').default; + }); + + it('renders warning modal and hides it after clicking', async() => { + renderToDom(); + + const b = document!.querySelector('button'); + + expect(b).toBeTruthy(); + // Exercises the when-focus-is-already-in-the-modal branch + b!.focus(); + + ReactDOMTestUtils.act(() => ReactDOMTestUtils.Simulate.click(b!)); + + expect(document!.querySelector('button')).toBeFalsy(); + }); + }); + + describe('outside the browser', () => { + const windowBackup = window; + const documentBackup = document; + + let renderer: typeof rendererType; + + beforeEach(() => { + delete (global as any).window; + delete (global as any).document; + resetModules(); + ({React, renderer} = reactAndFriends()); + + ContentWarningDynamic = require('./ContentWarning').default; + }); - const root = document?.body; - const b = root?.querySelector('button'); + afterEach(() => { + (global as any).window = windowBackup; + (global as any).document = documentBackup; + }); - expect(b).toBeTruthy(); - // Exercises the when-focus-is-already-in-the-modal branch - b!.focus(); - act(() => ReactTestUtils.Simulate.click(b!)); - expect(root?.querySelector('button')).toBeFalsy(); + it('mounts and unmounts without a dom', () => { + const component = renderer.create(); + expect(() => component.unmount()).not.toThrow(); + }); }); }); diff --git a/src/app/content/components/ContentWarning.tsx b/src/app/content/components/ContentWarning.tsx index 59491f713c..1cd6333e01 100644 --- a/src/app/content/components/ContentWarning.tsx +++ b/src/app/content/components/ContentWarning.tsx @@ -70,24 +70,26 @@ function WarningDivWithTrap({ const useDismiss = (book: Book) => { const cookieKey = `content-warning-${book.id}`; - const [dismissed, setDismissed] = React.useState(Cookies.get(cookieKey) || 'false'); + const [isShown, setIsShown] = React.useState(false); React.useEffect(() => { - setDismissed(Cookies.get(cookieKey) || 'false'); + if (typeof window !== 'undefined') { + setIsShown(Cookies.get(cookieKey) !== 'true'); + } }, [cookieKey]); const dismiss = React.useCallback(() => { Cookies.set(cookieKey, 'true', { expires: 28 }); - setDismissed('true'); + setIsShown(false); }, [cookieKey]); - return tuple(dismissed === 'true', dismiss); + return tuple(isShown, dismiss); }; export default function ContentWarning({ book }: { book: Book }) { - const [dismissed, dismiss] = useDismiss(book); + const [isShown, dismiss] = useDismiss(book); - if (!hasOSWebData(book) || !book.content_warning_text || dismissed) { + if (!hasOSWebData(book) || !book.content_warning_text || !isShown) { return null; } diff --git a/src/test/utils.ts b/src/test/utils.ts index b6394113f3..45735a69c6 100644 --- a/src/test/utils.ts +++ b/src/test/utils.ts @@ -19,6 +19,7 @@ export const reactAndFriends = () => { Provider: require('react-redux').Provider, React: require('react'), ReactDOM: require('react-dom') as typeof import ('react-dom'), + ReactDOMTestUtils: require('react-dom/test-utils') as typeof import ('react-dom/test-utils'), Services: require('../app/context/Services'), TestContainer: require('./TestContainer').default, _jestStyledComponents: require('jest-styled-components'),