Skip to content

Commit cb08235

Browse files
authored
Merge pull request #39 from Q42/maintenance/unit-tests
Unit tests
2 parents 42ef3cd + 1aaf9b5 commit cb08235

File tree

7 files changed

+1525
-267
lines changed

7 files changed

+1525
-267
lines changed

package-lock.json

Lines changed: 1304 additions & 257 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
"scripts": {
6969
"build": "run-s clean && plugin-kit verify-package --silent && pkg-utils build --strict && pkg-utils --strict",
7070
"clean": "rimraf dist",
71+
"test": "TZ=UTC vitest run",
72+
"test:watch": "TZ=UTC vitest",
7173
"format": "prettier --write --cache --ignore-unknown .",
7274
"link-watch": "plugin-kit link-watch",
7375
"lint": "eslint ./src/** --ext=.ts,.tsx --max-warnings 0",
@@ -94,6 +96,7 @@
9496
"@types/styled-components": "^5.1.28",
9597
"@typescript-eslint/eslint-plugin": "^6.13.2",
9698
"@typescript-eslint/parser": "^6.13.2",
99+
"@vitejs/plugin-react": "^4.3.1",
97100
"eslint": "^8.55.0",
98101
"eslint-config-prettier": "^9.1.0",
99102
"eslint-config-sanity": "^7.0.1",
@@ -108,7 +111,8 @@
108111
"react-is": "^18.2.0",
109112
"rimraf": "^5.0.5",
110113
"sanity": "^3.21.1",
111-
"typescript": "^5.3.3"
114+
"typescript": "^5.3.3",
115+
"vitest": "^2.0.2"
112116
},
113117
"peerDependencies": {
114118
"react": "^18",

src/components/PageTreeViewItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export const PageTreeViewItem = ({
110110
onClick={onItemClick}>
111111
<Flex align="center" gap={3}>
112112
<UrlText isDisabled={isDisabled} textOverflow="ellipsis">
113-
{parentPath ? page.slug?.current : getRootPageSlug(page, config)}
113+
{parentPath ? page.slug?.current : getRootPageSlug(page, config) ?? '/'}
114114
</UrlText>
115115
{!isDisabled && (isHovered || hasActionOpen) && (
116116
<PageTreeViewItemActions

src/helpers/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ export const getLanguageFieldName = (config: PageTreeConfig) =>
44
config.documentInternationalization?.languageFieldName ?? 'language';
55

66
export const getRootPageSlug = (page: RawPageMetadata, config: PageTreeConfig) => {
7-
if (!config.documentInternationalization) return '/';
7+
if (!config.documentInternationalization) return;
88

99
const language = page[getLanguageFieldName(config)];
1010
if (typeof language != 'string') {
1111
throw new Error(`Language field is not a string: ${language}`);
1212
}
13-
return `${language}`;
13+
return language;
1414
};

src/helpers/page-tree.test.ts

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { NestedPageTreeItem, PageTreeConfig, RawPageMetadata } from '../types';
4+
import { findPageTreeItemById, flatMapPageTree, getAllPageMetadata, mapRawPageMetadatasToPageTree } from './page-tree';
5+
6+
const config: PageTreeConfig = {
7+
apiVersion: '2023-01-01',
8+
rootSchemaType: 'homePage',
9+
pageSchemaTypes: ['homePage', 'contentPage'],
10+
titleFieldName: 'title',
11+
baseUrl: 'https://example.com',
12+
documentInternationalization: {
13+
supportedLanguages: ['en', 'nl'],
14+
},
15+
};
16+
17+
const rawHomePage: RawPageMetadata = {
18+
_id: 'home',
19+
_type: 'homePage',
20+
_updatedAt: '2023-01-01T00:00:00Z',
21+
language: 'en',
22+
};
23+
24+
const rawParentContentPage: RawPageMetadata = {
25+
_id: 'parent',
26+
_type: 'contentPage',
27+
_updatedAt: '2023-01-01T00:00:00Z',
28+
parent: { _ref: 'home', _type: 'reference' },
29+
slug: { current: 'parent' },
30+
language: 'en',
31+
};
32+
33+
const rawChildContentPage: RawPageMetadata = {
34+
_id: 'child',
35+
_type: 'contentPage',
36+
_updatedAt: '2023-01-01T00:00:00Z',
37+
parent: { _ref: 'parent', _type: 'reference' },
38+
slug: { current: 'child' },
39+
language: 'en',
40+
};
41+
42+
const rawPages: RawPageMetadata[] = [rawHomePage, rawParentContentPage, rawChildContentPage];
43+
44+
const pageTree: NestedPageTreeItem[] = [
45+
{
46+
...rawHomePage,
47+
isDraft: false,
48+
isPublished: true,
49+
path: '/en',
50+
children: [
51+
{
52+
...rawParentContentPage,
53+
isDraft: false,
54+
isPublished: true,
55+
path: '/en/parent',
56+
children: [
57+
{
58+
...rawChildContentPage,
59+
isDraft: false,
60+
isPublished: true,
61+
path: '/en/parent/child',
62+
children: [],
63+
},
64+
],
65+
},
66+
],
67+
},
68+
];
69+
70+
describe('Page tree helpers', () => {
71+
describe('getAllPageMetadata', () => {
72+
it('should return all page metadata from a page tree', () => {
73+
expect(getAllPageMetadata(config, rawPages)).toStrictEqual([
74+
{
75+
_id: rawHomePage._id,
76+
_updatedAt: rawHomePage._updatedAt,
77+
type: rawHomePage._type,
78+
path: '/en',
79+
},
80+
{
81+
_id: rawParentContentPage._id,
82+
_updatedAt: rawParentContentPage._updatedAt,
83+
type: rawParentContentPage._type,
84+
path: '/en/parent',
85+
},
86+
{
87+
_id: rawChildContentPage._id,
88+
_updatedAt: rawChildContentPage._updatedAt,
89+
type: rawChildContentPage._type,
90+
path: '/en/parent/child',
91+
},
92+
]);
93+
});
94+
});
95+
96+
describe('mapRawPageMetadatasToPageTree', () => {
97+
it('should map an array raw page metadata to a nested page tree correctly', () => {
98+
expect(mapRawPageMetadatasToPageTree(config, rawPages)).toStrictEqual(pageTree);
99+
});
100+
101+
it('should omit invalid pages from page tree', () => {
102+
expect(
103+
mapRawPageMetadatasToPageTree(config, [
104+
{
105+
_id: 'missing-parent',
106+
_type: 'contentPage',
107+
_updatedAt: '2023-01-01T00:00:00Z',
108+
language: 'en',
109+
slug: { current: 'slug' },
110+
},
111+
{
112+
_id: 'missing-slug',
113+
_type: 'contentPage',
114+
_updatedAt: '2023-01-01T00:00:00Z',
115+
language: 'en',
116+
parent: { _ref: 'home', _type: 'reference' },
117+
},
118+
]),
119+
).toStrictEqual([]);
120+
});
121+
122+
it('should omit published pages that have a draft version', () => {
123+
expect(
124+
mapRawPageMetadatasToPageTree(config, [
125+
{
126+
_id: 'home',
127+
_type: 'homePage',
128+
_updatedAt: '2023-01-01T00:00:00Z',
129+
language: 'en',
130+
},
131+
{
132+
_id: 'drafts.home',
133+
_type: 'homePage',
134+
_updatedAt: '2023-01-01T00:00:00Z',
135+
language: 'en',
136+
},
137+
]),
138+
).toStrictEqual([
139+
{
140+
...rawHomePage,
141+
isDraft: true,
142+
isPublished: true,
143+
path: '/en',
144+
children: [],
145+
},
146+
]);
147+
});
148+
});
149+
150+
describe('flatMapPageTree', () => {
151+
it('should flatten a nested page tree correctly', () => {
152+
expect(flatMapPageTree(pageTree)).toStrictEqual([
153+
{
154+
...rawHomePage,
155+
isDraft: false,
156+
isPublished: true,
157+
path: '/en',
158+
},
159+
{
160+
...rawParentContentPage,
161+
isDraft: false,
162+
isPublished: true,
163+
path: '/en/parent',
164+
},
165+
{
166+
...rawChildContentPage,
167+
isDraft: false,
168+
isPublished: true,
169+
path: '/en/parent/child',
170+
},
171+
]);
172+
});
173+
});
174+
175+
describe('findPageTreeItemById', () => {
176+
it('should find a page from a page tree by the given page id', () => {
177+
expect(findPageTreeItemById(pageTree, 'child')).toStrictEqual({
178+
...rawChildContentPage,
179+
isDraft: false,
180+
isPublished: true,
181+
path: '/en/parent/child',
182+
children: [],
183+
});
184+
});
185+
186+
it('should return undefined if the page id is not found', () => {
187+
expect(findPageTreeItemById(pageTree, 'missing')).toBeUndefined();
188+
});
189+
});
190+
});

src/helpers/page-tree.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ export const DRAFTS_PREFIX = 'drafts.';
1616
/**
1717
* Maps array of raw page metadata objects to page metadata object array containing resolved id, path and type.
1818
*/
19-
export const getAllPageMetadata = (config: PageTreeConfig, pagesInfo: RawPageMetadata[]): PageMetadata[] => {
20-
const pageTree = mapRawPageMetadatasToPageTree(config, pagesInfo);
19+
export const getAllPageMetadata = (config: PageTreeConfig, pages: RawPageMetadata[]): PageMetadata[] => {
20+
const pageTree = mapRawPageMetadatasToPageTree(config, pages);
2121
const flatPageTree = flatMapPageTree(pageTree);
2222

2323
return flatPageTree.map(page => ({
@@ -49,7 +49,7 @@ export const mapRawPageMetadatasToPageTree = (
4949
config: PageTreeConfig,
5050
pages: RawPageMetadata[],
5151
): NestedPageTreeItem[] => {
52-
const pagesWithPublishedState = getPublishedAndDraftRawPageMetdadata(config, pages);
52+
const pagesWithPublishedState = getPublishedAndDraftRawPageMetadata(config, pages);
5353

5454
const orderedPages = orderBy(mapPageTreeItems(config, pagesWithPublishedState), 'path');
5555
const { documentInternationalization } = config;
@@ -90,7 +90,7 @@ const mapPageTreeItems = (
9090
return getChildPages(parentId).map(page => {
9191
const pagePath = parentPath
9292
? `${parentPath === '/' ? '' : parentPath}/${page.slug?.current}`
93-
: getRootPageSlug(page, config);
93+
: `/${getRootPageSlug(page, config) ?? ''}`;
9494
const children = orderBy(mapPageTreeItems(config, pagesWithPublishedState, page._id, pagePath), 'path');
9595

9696
return {
@@ -104,7 +104,7 @@ const mapPageTreeItems = (
104104
/**
105105
* Provides draft and published status. Filters out duplicate pages with the same id and invalid pages.
106106
*/
107-
const getPublishedAndDraftRawPageMetdadata = (
107+
const getPublishedAndDraftRawPageMetadata = (
108108
config: PageTreeConfig,
109109
pages: RawPageMetadata[],
110110
): RawPageMetadataWithPublishedState[] => {
@@ -134,7 +134,7 @@ const getPublishedAndDraftRawPageMetdadata = (
134134
};
135135

136136
const isValidPage = (config: PageTreeConfig, page: RawPageMetadata): boolean => {
137-
if (page.parent === null || page.slug === null) {
137+
if (!page.parent || !page.slug) {
138138
if (page._type !== config.rootSchemaType) {
139139
return false;
140140
}

vitest.config.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import react from '@vitejs/plugin-react';
2+
import path from 'path';
3+
import { defineConfig, UserConfig } from 'vitest/config';
4+
5+
// https://vitejs.dev/config/
6+
export default defineConfig({
7+
plugins: [react()] as UserConfig['plugins'],
8+
test: {
9+
include: ['src/**/*.test.ts'],
10+
environment: 'jsdom',
11+
},
12+
resolve: {
13+
alias: {
14+
'@': path.resolve(__dirname, './src'),
15+
},
16+
},
17+
});

0 commit comments

Comments
 (0)