Skip to content

Commit

Permalink
Code coverage 7 (#2669)
Browse files Browse the repository at this point in the history
* About page -> TSX with coverage

* Adopters page -> TSX with coverage

Also adjusted Institutional Partnership test, which was affected by the mock of lazyload

* Layout coverage

* Code review
  • Loading branch information
RoyEJohnson authored Sep 23, 2024
1 parent c24de37 commit 7d6aadd
Show file tree
Hide file tree
Showing 11 changed files with 449 additions and 79 deletions.
20 changes: 11 additions & 9 deletions src/app/contexts/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ type LayoutParameters = {
const defaultLayoutParameters: LayoutParameters = {name: 'default'};

function useContextValue() {
const [layoutParameters, setLayoutParameters] = React.useReducer(
(state: LayoutParameters, newState: LayoutParameters) => {
if (newState === undefined) {
return defaultLayoutParameters;
const [layoutParameters, setLayoutParameters] = React.useState(defaultLayoutParameters);
const updateIfNotEqual = React.useCallback(
(newValue?: LayoutParameters) => {
if (newValue === undefined) {
setLayoutParameters(defaultLayoutParameters);
return;
}
if (deepEqual(state, newState)) {
return state;
if (deepEqual(layoutParameters, newValue)) {
return;
}
return newState;
setLayoutParameters(newValue);
},
defaultLayoutParameters
[layoutParameters]
);
const LoadableLayout = React.useMemo(
() =>
Expand All @@ -45,7 +47,7 @@ function useContextValue() {
[LoadableLayout, layoutParameters.data]
);

return {Layout, setLayoutParameters, layoutParameters};
return {Layout, setLayoutParameters: updateIfNotEqual, layoutParameters};
}

const {useContext, ContextProvider} = buildContext({useContextValue});
Expand Down
92 changes: 68 additions & 24 deletions src/app/pages/about/about.js → src/app/pages/about/about.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,22 @@ import './about.scss';

const slug = 'pages/about';

function translateCard(c) {
const imgEntry = c.find((v) => v.type === 'image');
const textEntry = c.find((v) => v.type === 'paragraph');
type ImageCard = {
type: 'image';
value: {
image: string;
link: string;
};
};
type TextCard = {
type: 'paragraph';
value: string;
};
type RawCard = [ImageCard, TextCard];

function translateCard(c: RawCard) {
const imgEntry = c.find((v) => v.type === 'image') as ImageCard;
const textEntry = c.find((v) => v.type === 'paragraph') as TextCard;

return {
image: imgEntry.value.image,
Expand All @@ -18,29 +31,61 @@ function translateCard(c) {
};
}

function Card({link, image, text}) {
function Card({
link,
image,
text
}: {
link: string;
image: string;
text: string;
}) {
const optimizedImage = useOptimizedImage(image);

return (
<a className="card" href={link}>
<img src={optimizedImage} role="presentation" />
<div className="content">
{text}
</div>
<div className="content">{text}</div>
</a>
);
}

function About({data: {
whoHeading, whoParagraph, whoImageUrl,
whatHeading, whatParagraph, whatCards,
whereHeading, whereParagraph, whereMapUrl: map, whereMapAlt
}}) {
type AboutData = {
whoHeading: string;
whoParagraph: string;
whoImageUrl: string;
whatHeading: string;
whatParagraph: string;
whatCards: RawCard[];
whereHeading: string;
whereParagraph: string;
whereMapUrl: string;
whereMapAlt: string;
};

function About({
data: {
whoHeading,
whoParagraph,
whoImageUrl,
whatHeading,
whatParagraph,
whatCards,
whereHeading,
whereParagraph,
whereMapUrl: map,
whereMapAlt
}
}: {
data: AboutData;
}) {
const cards = React.useMemo(
() => (whatCards || []).map(translateCard),
() => whatCards.map(translateCard),
[whatCards]
);
const mapAlt = whereMapAlt || 'animated map suggesting where our books are being adopted';
const mapAlt =
whereMapAlt ||
'animated map suggesting where our books are being adopted';
const maxDim = window.innerWidth < 1920 ? 1015 : null;
const optimizedWhoImage = useOptimizedImage(whoImageUrl, maxDim);

Expand All @@ -63,13 +108,14 @@ function About({data: {
<RawHTML html={whatParagraph} />
</div>
<div className="cards">
{cards.map(
({link, image, text}) =>
<Card
key={text}
link={link} image={image} text={text}
/>
)}
{cards.map(({link, image, text}) => (
<Card
key={text}
link={link}
image={image}
text={text}
/>
))}
</div>
</div>
</section>
Expand All @@ -92,7 +138,5 @@ function About({data: {
}

export default function AboutLoader() {
return (
<LoaderPage slug={slug} Child={About} doDocumentSetup />
);
return <LoaderPage slug={slug} Child={About} doDocumentSetup />;
}
31 changes: 0 additions & 31 deletions src/app/pages/adopters/adopters.js

This file was deleted.

30 changes: 30 additions & 0 deletions src/app/pages/adopters/adopters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import LoaderPage from '~/components/jsx-helpers/loader-page';
import './adopters.scss';

const slug = 'adopters';

type Data = {
name: string;
description: string;
website: string;
};

function Adopters({data}: {data: Data[]}) {
return (
<main className="adopters-page text-content">
<h1>Complete list of institutions that have adopted OpenStax</h1>
<ul className="adopters">
{data.map((adopter) => (
<li className="adopter" key={adopter.website}>
{adopter.name}
</li>
))}
</ul>
</main>
);
}

export default function AdoptersLoader() {
return <LoaderPage slug={slug} Child={Adopters} doDocumentSetup />;
}
8 changes: 8 additions & 0 deletions test/helpers/mock-lazyload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react';

jest.mock('react-lazyload', () => ({
__esModule: true,
default: ({children}: React.PropsWithChildren<object>) => {
return children;
}
}));
1 change: 1 addition & 0 deletions test/setupFile.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'settings';
import './helpers/fetch-mocker';
import './helpers/mock-lazyload';
import {LocalStorage} from 'node-localstorage';
import ReactModal from 'react-modal';

Expand Down
65 changes: 51 additions & 14 deletions test/src/contexts/layout.test.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,50 @@
import React from 'react';
import {render, screen} from '@testing-library/preact';
import useLayoutContext, { LayoutContextProvider } from '~/contexts/layout';
import {MemoryRouter} from 'react-router-dom';

function Component() {
const {Layout, setLayoutParameters} = useLayoutContext();

React.useEffect(
() => setLayoutParameters({name: 'landing', data: {title: 'title', layout: [
{
value: {
navLinks: [{
text: 'Landing page link',
target: {
type: 'href',
value: 'whatever'
() => {
setLayoutParameters({
name: 'landing',
data: {
title: 'title', layout: [
{
value: {
navLinks: [{
text: 'Landing page link',
target: {
type: 'href',
value: 'whatever'
}
}]
}
}]
}
}
]}}),
});
// Exercise the code that tests for equal setting
setTimeout(() => setLayoutParameters({
name: 'landing',
data: {
title: 'title', layout: [
{
value: {
navLinks: [{
text: 'Landing page link',
target: {
type: 'href',
value: 'whatever'
}
}]
}
}]
}
}), 5);
setTimeout(() => setLayoutParameters(undefined), 10);
},
[setLayoutParameters]
);

Expand All @@ -29,13 +55,24 @@ function Component() {
);
}

jest.useFakeTimers();
jest.mock('~/layouts/default/microsurvey-popup/microsurvey-popup', () => jest.fn());
jest.mock('~/layouts/default/header/header', () => jest.fn());
jest.mock('~/layouts/default/lower-sticky-note/lower-sticky-note', () => jest.fn());
jest.mock('~/layouts/default/welcome/welcome', () => jest.fn());
jest.mock('~/layouts/default/footer/footer', () => jest.fn());
jest.mock('~/layouts/default/takeover-dialog/takeover-dialog', () => jest.fn());

describe('layout-context', () => {
it('renders a landing page', async () => {
render(
<LayoutContextProvider>
<Component />
</LayoutContextProvider>
<MemoryRouter>
<LayoutContextProvider>
<Component />
</LayoutContextProvider>
</MemoryRouter>
);
await screen.findByText('Landing page link');
jest.runAllTimers();
await screen.findByText('No menus');
});
});
Loading

0 comments on commit 7d6aadd

Please sign in to comment.