Skip to content

Commit 40ceda0

Browse files
committed
Set title and description; test coverage
Also removed a couple of unused imports from latest-blog-posts
1 parent 75902b9 commit 40ceda0

File tree

3 files changed

+81
-17
lines changed

3 files changed

+81
-17
lines changed

src/app/pages/footer-page/footer-page.tsx

+36-16
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,31 @@ import React from 'react';
22
import RawHTML from '~/components/jsx-helpers/raw-html';
33
import usePageData from '~/helpers/use-page-data';
44
import {useLocation} from 'react-router-dom';
5+
import useDocumentHead from '~/helpers/use-document-head';
56
import './footer-page.scss';
67

7-
const specialSlugFromPath = {
8+
const specialSlugFromPath: Record<string, string> = {
89
'/privacy': '/privacy-policy'
910
};
1011

11-
export default function FooterPage() {
12-
const {pathname} = useLocation();
13-
const slugEnd = specialSlugFromPath[pathname] || pathname;
14-
const slug = `pages${slugEnd}`;
15-
const data = usePageData(slug);
16-
17-
React.useLayoutEffect(
18-
() => window.scrollTo(0, 0),
19-
[pathname]
20-
);
12+
type PageData = {
13+
introHeading: string;
14+
title: string;
15+
meta: {
16+
searchDescription: string;
17+
};
18+
} & {
19+
[contentFieldName: string]: string;
20+
}
2121

22-
if (!data) {
23-
return null;
24-
}
22+
function FooterPage({data}: {data: PageData}) {
23+
useDocumentHead({
24+
title: data.title,
25+
description: data.meta.searchDescription
26+
});
2527

26-
const contentFieldName = Reflect.ownKeys(data)
27-
.find((k) => k.match(/Content$/));
28+
const contentFieldName = Object.keys(data)
29+
.find((k) => k.match(/Content$/)) as string;
2830
const {introHeading: heading, [contentFieldName]: content} = data;
2931

3032
return (
@@ -37,3 +39,21 @@ export default function FooterPage() {
3739
</div>
3840
);
3941
}
42+
43+
export default function LoadFooterPage() {
44+
const {pathname} = useLocation();
45+
const slugEnd = specialSlugFromPath[pathname] ?? pathname;
46+
const slug = `pages${slugEnd}`;
47+
const data = usePageData<PageData>(slug);
48+
49+
React.useLayoutEffect(
50+
() => window.scrollTo(0, 0),
51+
[pathname]
52+
);
53+
54+
if (!data) {
55+
return null;
56+
}
57+
58+
return <FooterPage data={data} />;
59+
}

test/src/pages/blog/latest-blog-posts.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import {render, screen} from '@testing-library/preact';
33
import {describe, it, expect} from '@jest/globals';
4-
import {BrowserRouter, MemoryRouter, Routes, Route} from 'react-router-dom';
4+
import {BrowserRouter} from 'react-router-dom';
55
import {BlogContextProvider} from '~/pages/blog/blog-context';
66

77
import LatestBlogPosts from '~/pages/blog/latest-blog-posts/latest-blog-posts';

test/src/pages/footer-page.test.tsx

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React from 'react';
2+
import {render, screen} from '@testing-library/preact';
3+
import {MemoryRouter} from 'react-router-dom';
4+
import * as UPD from '~/helpers/use-page-data';
5+
import FooterPage from '~/pages/footer-page/footer-page';
6+
7+
const mockUsePageData = jest.spyOn(UPD, 'default');
8+
9+
// @ts-expect-error does not exist on
10+
const {routerFuture} = global;
11+
12+
window.scrollTo = jest.fn();
13+
14+
describe('footer-page', () => {
15+
const saveWarn = console.warn;
16+
17+
it('renders', () => {
18+
mockUsePageData.mockReturnValue({
19+
introHeading: 'heading',
20+
title: 'docTitle',
21+
meta: {
22+
searchDescription: 'description in head'
23+
},
24+
pageContent: 'the html for the page'
25+
});
26+
console.warn = jest.fn();
27+
28+
render(
29+
<MemoryRouter initialEntries={['/aslug']} future={routerFuture}>
30+
<FooterPage />
31+
</MemoryRouter>);
32+
expect((screen.getByRole('heading', {level: 1})).textContent).toBe('heading');
33+
expect(document.head.querySelector('title')?.textContent).toBe('docTitle - OpenStax');
34+
console.warn = saveWarn;
35+
});
36+
it('renders nothing until page data is received', async () => {
37+
mockUsePageData.mockReturnValue(null);
38+
render(
39+
<MemoryRouter initialEntries={['/aslug']} future={routerFuture}>
40+
<FooterPage />
41+
</MemoryRouter>);
42+
expect(document.body.textContent).toBe('');
43+
});
44+
});

0 commit comments

Comments
 (0)