From 662ec26825fb47edcc4c61baea5728a99043a8f8 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela <90895835+vishvamsinh28@users.noreply.github.com> Date: Mon, 7 Oct 2024 18:41:56 +0530 Subject: [PATCH] feat: add test for build docs script (#3137) Co-authored-by: Ansh Goyal --- scripts/build-docs.js | 208 ++++++++++++----------- tests/build-docs/addDocButtons.test.js | 91 ++++++++++ tests/build-docs/buildNavTree.test.js | 133 +++++++++++++++ tests/build-docs/convertDocPosts.test.js | 62 +++++++ tests/fixtures/addDocButtonsData.js | 41 +++++ tests/fixtures/buildNavTreeData.js | 45 +++++ tests/fixtures/convertDocPostData.js | 31 ++++ 7 files changed, 516 insertions(+), 95 deletions(-) create mode 100644 tests/build-docs/addDocButtons.test.js create mode 100644 tests/build-docs/buildNavTree.test.js create mode 100644 tests/build-docs/convertDocPosts.test.js create mode 100644 tests/fixtures/addDocButtonsData.js create mode 100644 tests/fixtures/buildNavTreeData.js create mode 100644 tests/fixtures/convertDocPostData.js diff --git a/scripts/build-docs.js b/scripts/build-docs.js index a51971cc2488..ac47b6751cee 100644 --- a/scripts/build-docs.js +++ b/scripts/build-docs.js @@ -1,61 +1,65 @@ const sortBy = require('lodash/sortBy') function buildNavTree(navItems) { + try { const tree = { 'welcome': { item: { title: 'Welcome', weight: 0, isRootSection: true, isSection: true, rootSectionId: 'welcome', sectionWeight: 0, slug: '/docs' }, children: {} } } - + //first we make sure that list of items lists main section items and then sub sections, documents last - const sortedItems = sortBy(navItems, ['isRootSection', 'weight', 'isSection']); - + const sortedItems = sortBy(navItems, ['isRootSection', 'weight', 'isSection']); + sortedItems.forEach(item => { //identify main sections if (item.isRootSection) { tree[item.rootSectionId] = { item, children: {} } } - + //identify subsections if (item.parent) { - tree[item.parent].children[item.sectionId] = { item, children: [] } + if (!tree[item.parent]) { + throw new Error(`Parent section ${item.parent} not found for item ${item.title}`); + } + tree[item.parent].children[item.sectionId] = { item, children: [] }; } - + if (!item.isSection) { if (item.sectionId) { - let section = tree[item.rootSectionId].children[item.sectionId]; + let section = tree[item.rootSectionId]?.children[item.sectionId]; if (!section) { - tree[item.rootSectionId].children[item.sectionId] = { item, children: [] } + tree[item.rootSectionId].children[item.sectionId] = { item, children: [] }; } - tree[item.rootSectionId].children[item.sectionId].children.push(item) + tree[item.rootSectionId].children[item.sectionId].children.push(item); } else { tree[item.rootSectionId].children[item.title] = { item }; } } - }) - + }); + for (const [rootKey, rootValue] of Object.entries(tree)) { const allChildren = rootValue.children; const allChildrenKeys = Object.keys(allChildren); - + rootValue.children = allChildrenKeys .sort((prev, next) => { return allChildren[prev].item.weight - allChildren[next].item.weight; - }).reduce( - (obj, key) => { - obj[key] = allChildren[key]; - return obj; - }, - {} - ); - + }) + .reduce((obj, key) => { + obj[key] = allChildren[key]; + return obj; + }, {}); + //handling subsections if (allChildrenKeys.length > 1) { for (const key of allChildrenKeys) { - allChildren[key].children?.sort((prev, next) => { - return prev.weight - next.weight; - }); - + if (allChildren[key].children) { + allChildren[key].children.sort((prev, next) => { + return prev.weight - next.weight; + }); + } + // point in slug for specification subgroup to the latest specification version if (rootKey === 'reference' && key === 'specification') { allChildren[key].item.href = allChildren[key].children.find(c => c.isPrerelease === undefined).slug; @@ -63,17 +67,22 @@ function buildNavTree(navItems) { } } } - + return tree; + + } catch (err) { + throw new Error(`Failed to build navigation tree: ${err.message}`); + } } - // A recursion function, works on the logic of Depth First Search to traverse all the root and child posts of the - // DocTree to get sequential order of the Doc Posts +// A recursion function, works on the logic of Depth First Search to traverse all the root and child posts of the +// DocTree to get sequential order of the Doc Posts const convertDocPosts = (docObject) => { + try { let docsArray = [] // certain entries in the DocPosts are either a parent to many posts or itself a post. - docsArray.push(docObject?.item || docObject) - if(docObject.children){ + docsArray.push(docObject?.item || docObject) + if (docObject.children) { let children = docObject.children Object.keys(children).forEach((child) => { let docChildArray = convertDocPosts(children[child]) @@ -81,84 +90,93 @@ const convertDocPosts = (docObject) => { }) } return docsArray + } + catch (err) { + throw new Error('Error in convertDocPosts:', err); + } } - -function addDocButtons(docPosts, treePosts){ + +function addDocButtons(docPosts, treePosts) { let structuredPosts = []; let rootSections = []; - // Traversing the whole DocTree and storing each post inside them in sequential order - Object.keys(treePosts).forEach((rootElement) => { - structuredPosts.push(treePosts[rootElement].item) - if(treePosts[rootElement].children){ - let children = treePosts[rootElement].children - Object.keys(children).forEach((child) => { - let docChildArray = convertDocPosts(children[child]) - structuredPosts = [...structuredPosts, ...docChildArray] - }) - } - }) - // Appending the content of welcome page pf Docs from the posts.json - structuredPosts[0] = docPosts.filter(p => p.slug === '/docs')[0] - - // Traversing the strucutredPosts in order to add `nextPage` and `prevPage` details for each page - let countDocPages = structuredPosts.length - structuredPosts = structuredPosts.map((post, index) => { - // post item specifying the root Section or sub-section in the docs are excluded as - // they doesn't comprise any Doc Page or content to be shown in website. - if(post?.isRootSection || post?.isSection || index==0){ - if(post?.isRootSection || index==0) - rootSections.push(post.title) - return post - } + try { + // Traversing the whole DocTree and storing each post inside them in sequential order + Object.keys(treePosts).forEach((rootElement) => { + structuredPosts.push(treePosts[rootElement].item); + if (treePosts[rootElement].children) { + let children = treePosts[rootElement].children; + Object.keys(children).forEach((child) => { + let docChildArray = convertDocPosts(children[child]); + structuredPosts = [...structuredPosts, ...docChildArray]; + }); + } + }); - let nextPage = {}, prevPage = {} - let docPost = post; - - // checks whether the next page for the current docPost item exists or not - if(index+1 p.slug === '/docs')[0]; + + // Traversing the structuredPosts in order to add `nextPage` and `prevPage` details for each page + let countDocPages = structuredPosts.length; + structuredPosts = structuredPosts.map((post, index) => { + // post item specifying the root Section or sub-section in the docs are excluded as + // they doesn't comprise any Doc Page or content to be shown in website. + if (post?.isRootSection || post?.isSection || index == 0) { + if (post?.isRootSection || index == 0) + rootSections.push(post.title) + return post } - docPost = {...docPost, nextPage} - } - // checks whether the previous page for the current docPost item exists or not - if(index>0){ - // checks whether the previous item inside structuredPosts is a rootElement or a sectionElement - // if yes, it goes again to a next previous item in structuredPosts to link the prevPage - if(!structuredPosts[index-1]?.isRootElement && !structuredPosts[index-1]?.isSection){ - prevPage = { - title: structuredPosts[index-1].title, - href: structuredPosts[index-1].slug + let nextPage = {}, prevPage = {} + let docPost = post; + + // checks whether the next page for the current docPost item exists or not + if (index + 1 < countDocPages) { + // checks whether the next item inside structuredPosts is a rootElement or a sectionElement + // if yes, it goes again to a next to next item in structuredPosts to link the nextPage + if (!structuredPosts[index + 1].isRootElement && !structuredPosts[index + 1].isSection) { + nextPage = { + title: structuredPosts[index + 1].title, + href: structuredPosts[index + 1].slug + } + } else { + nextPage = { + title: `${structuredPosts[index + 1].title} - ${structuredPosts[index + 2].title}`, + href: structuredPosts[index + 2].slug + } } - docPost = {...docPost, prevPage} - }else{ - // additonal check for the first page of Docs so that it doesn't give any Segementation fault - if(index-2>=0){ + docPost = { ...docPost, nextPage } + } + + // checks whether the previous page for the current docPost item exists or not + if (index > 0) { + // checks whether the previous item inside structuredPosts is a rootElement or a sectionElement + // if yes, it goes again to a next previous item in structuredPosts to link the prevPage + if (!structuredPosts[index - 1]?.isRootElement && !structuredPosts[index - 1]?.isSection) { prevPage = { - title: `${structuredPosts[index-1]?.isRootSection ? rootSections[rootSections.length - 2] : rootSections[rootSections.length - 1]} - ${structuredPosts[index-2].title}`, - href: structuredPosts[index-2].slug + title: structuredPosts[index - 1].title, + href: structuredPosts[index - 1].slug + } + docPost = { ...docPost, prevPage } + } else { + // additonal check for the first page of Docs so that it doesn't give any Segementation fault + if (index - 2 >= 0) { + prevPage = { + title: `${structuredPosts[index - 1]?.isRootSection ? rootSections[rootSections.length - 2] : rootSections[rootSections.length - 1]} - ${structuredPosts[index - 2].title}`, + href: structuredPosts[index - 2].slug + }; + docPost = { ...docPost, prevPage }; } - docPost = {...docPost, prevPage} } } - } - return docPost - }) - return structuredPosts -} + return docPost; + }); + } catch (err) { + throw new Error("An error occurred while adding doc buttons:", err); + } + return structuredPosts; +} -module.exports = {buildNavTree, addDocButtons, convertDocPosts} \ No newline at end of file +module.exports = { buildNavTree, addDocButtons, convertDocPosts } \ No newline at end of file diff --git a/tests/build-docs/addDocButtons.test.js b/tests/build-docs/addDocButtons.test.js new file mode 100644 index 000000000000..b867d8389549 --- /dev/null +++ b/tests/build-docs/addDocButtons.test.js @@ -0,0 +1,91 @@ +const { addDocButtons } = require("../../scripts/build-docs"); +const { docPosts, treePosts, mockDocPosts, mockTreePosts, invalidTreePosts } = require("../fixtures/addDocButtonsData"); + +describe('addDocButtons', () => { + it('should add next and previous page information', () => { + const expectedFirstItem = { + title: 'Welcome', + slug: '/docs', + content: 'Welcome content' + }; + + const expectedSecondItem = { + isRootSection: true, + title: 'Section 1' + }; + + const expectedThirdItem = { + title: 'Page 1', + slug: '/docs/section1/page1', + nextPage: { + title: 'Page 2', + href: '/docs/section1/page2' + }, + prevPage: { + title: 'Section 1', + href: undefined + } + }; + + const expectedFourthItem = { + title: 'Page 2', + slug: '/docs/section1/page2', + prevPage: { + title: 'Page 1', + href: '/docs/section1/page1' + } + }; + + const result = addDocButtons(docPosts, treePosts); + + expect(result).toHaveLength(4); + expect(result[0]).toEqual(expectedFirstItem); + expect(result[1]).toEqual(expectedSecondItem); + expect(result[2]).toEqual(expectedThirdItem); + expect(result[3]).toEqual(expectedFourthItem); + }); + + it('should set nextPage correctly when next item is a root element', () => { + const result = addDocButtons(mockDocPosts, mockTreePosts); + + expect(result[1].nextPage).toBeDefined(); + expect(result[1].nextPage.title).toBe('Root 2 - Child 2'); + expect(result[1].nextPage.href).toBe('/docs/root2/child2'); + }); + + it('should throw an error if treePosts is missing', () => { + let error; + + try { + addDocButtons(docPosts, undefined); + } catch (err) { + error = err + expect(err.message).toContain("An error occurred while adding doc buttons:"); + } + expect(error).toBeDefined() + }); + + it('should throw an error if docPosts is missing', () => { + let error; + + try { + addDocButtons(undefined, treePosts); + } catch (err) { + error = err + expect(err.message).toContain("An error occurred while adding doc buttons:"); + } + expect(error).toBeDefined() + }); + + it('should handle invalid data structure in treePosts', () => { + let error; + + try { + addDocButtons(docPosts, invalidTreePosts); + } catch (err) { + error = err; + expect(err.message).toContain("An error occurred while adding doc buttons:"); + } + expect(error).toBeDefined() + }); +}); diff --git a/tests/build-docs/buildNavTree.test.js b/tests/build-docs/buildNavTree.test.js new file mode 100644 index 000000000000..992011be949c --- /dev/null +++ b/tests/build-docs/buildNavTree.test.js @@ -0,0 +1,133 @@ +const { buildNavTree } = require('../../scripts/build-docs'); + +const { + basicNavItems, + sectionNavItems, + orphanNavItems, + missingFieldsNavItems, + invalidParentNavItems, + multipleSubsectionsNavItems +} = require('../fixtures/buildNavTreeData') + +describe('buildNavTree', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should create a tree structure from nav items', () => { + + const result = buildNavTree(basicNavItems); + + expect(result['welcome'].item).toEqual( + expect.objectContaining({ + title: 'Welcome', + slug: '/docs' + }) + ); + + expect(result['getting-started'].item).toEqual( + expect.objectContaining({ + title: 'Getting Started', + slug: '/docs/getting-started' + }) + ); + + expect(result['getting-started'].children).toHaveProperty('installation'); + expect(result['getting-started'].children).toHaveProperty('configuration'); + + expect(result['reference'].item).toEqual( + expect.objectContaining({ + title: 'Reference', + slug: '/docs/reference' + }) + ); + + expect(result['reference'].children.api.item).toEqual( + expect.objectContaining({ + title: 'API', + slug: '/docs/reference/api' + }) + ); + + expect(result['reference'].children.specification.item.slug).toBe('/docs/reference/specification'); + expect(result['reference'].children.specification.children[0].slug).toBe('/docs/reference/specification/v3.0'); + + }); + + it('should handle items without sectionId', () => { + + const result = buildNavTree(sectionNavItems); + + expect(result['root'].item).toEqual( + expect.objectContaining({ + title: 'Root', + slug: '/docs' + }) + ); + + expect(result['root'].children).toHaveProperty('Item without sectionId'); + expect(result['root'].children['Item without sectionId'].item).toEqual( + expect.objectContaining({ + title: 'Item without sectionId', + slug: '/docs/item' + }) + ); + }); + + it('should throw and catch an error if a parent section is missing', () => { + let error; + + try { + buildNavTree(orphanNavItems); + } catch (err) { + error = err; + expect(err.message).toContain('Parent section non-existent-parent not found for item Orphaned Subsection'); + } + expect(error).toBeDefined() + }); + + it('should handle items with missing required fields gracefully', () => { + let error; + + try { + buildNavTree(missingFieldsNavItems); + } catch (err) { + error = err; + expect(err.message).toContain('Failed to build navigation tree'); + } + expect(error).toBeDefined(); + }); + + it('should throw an error when parent references are invalid', () => { + let error; + + try { + buildNavTree(invalidParentNavItems); + } catch (err) { + error = err; + expect(err.message).toContain('Parent section non-existent-parent not found for item Child with invalid parent'); + } + expect(error).toBeDefined(); + }); + + it('should sort children within subsections based on weight', () => { + const result = buildNavTree(multipleSubsectionsNavItems); + + const apiChildren = result['reference'].children.api.children; + expect(apiChildren[0].title).toBe('Authentication'); + expect(apiChildren[1].title).toBe('Endpoints'); + expect(apiChildren[2].title).toBe('Rate Limiting'); + + const specChildren = result['reference'].children.specification.children; + expect(specChildren[0].title).toBe('v1.0'); + expect(specChildren[1].title).toBe('v2.0'); + expect(specChildren[2].title).toBe('v3.0'); + + expect(apiChildren[0].weight).toBeLessThan(apiChildren[1].weight); + expect(apiChildren[1].weight).toBeLessThan(apiChildren[2].weight); + + expect(specChildren[0].weight).toBeLessThan(specChildren[1].weight); + expect(specChildren[1].weight).toBeLessThan(specChildren[2].weight); + }); + +}); diff --git a/tests/build-docs/convertDocPosts.test.js b/tests/build-docs/convertDocPosts.test.js new file mode 100644 index 000000000000..6cc397ed98b2 --- /dev/null +++ b/tests/build-docs/convertDocPosts.test.js @@ -0,0 +1,62 @@ +const { convertDocPosts } = require('../../scripts/build-docs'); +const { + docObject, + emptyDocObject, + singlePostDocObject, + nestedChildrenDocObject + } = require('../fixtures/convertDocPostData'); + +describe('convertDocPosts', () => { + it('should convert a doc object to an array', () => { + const result = convertDocPosts(docObject); + expect(result).toHaveLength(3); + expect(result[0].title).toBe('Root'); + expect(result[1].title).toBe('Child 1'); + expect(result[2].title).toBe('Child 2'); + }); + + it('should return an array with an empty object for an empty doc object', () => { + const result = convertDocPosts(emptyDocObject); + expect(result).toEqual([{}]); + }); + + it('should handle a doc object with no children', () => { + const result = convertDocPosts(singlePostDocObject); + expect(result).toHaveLength(1); + expect(result[0].title).toBe('Single Post'); + }); + + it('should handle nested children', () => { + const result = convertDocPosts(nestedChildrenDocObject); + expect(result).toHaveLength(4); + expect(result[0].title).toBe('Root'); + expect(result[1].title).toBe('Child 1'); + expect(result[2].title).toBe('Grandchild 1'); + expect(result[3].title).toBe('Child 2'); + }); + + it('should throw an error if docObject is undefined', () => { + let error; + + try { + convertDocPosts(undefined); + } catch (err) { + error = err; + expect(err.message).toContain('Error in convertDocPosts:'); + } + expect(error).toBeDefined(); + }); + + it('should throw an error if docObject is null', () => { + let error; + + try { + convertDocPosts(null); + } catch (err) { + error = err; + expect(err.message).toContain('Error in convertDocPosts:'); + } + expect(error).toBeDefined(); + }); + +}); diff --git a/tests/fixtures/addDocButtonsData.js b/tests/fixtures/addDocButtonsData.js new file mode 100644 index 000000000000..8b2f437fc9b9 --- /dev/null +++ b/tests/fixtures/addDocButtonsData.js @@ -0,0 +1,41 @@ +const docPosts = [ + { title: 'Welcome', slug: '/docs', content: 'Welcome content' }, +]; + +const treePosts = { + welcome: { + item: { title: 'Welcome', isRootSection: true, slug: '/docs' }, + children: {}, + }, + section1: { + item: { title: 'Section 1', isRootSection: true }, + children: { + page1: { item: { title: 'Page 1', slug: '/docs/section1/page1' } }, + page2: { item: { title: 'Page 2', slug: '/docs/section1/page2' } }, + }, + }, +}; + +const mockDocPosts = [ + { slug: '/docs', title: 'Welcome to Docs' }, + { slug: '/docs/page1', title: 'Page 1' }, +]; + +const mockTreePosts = { + root1: { + item: { title: 'Root 1', isRootSection: true }, + children: { + child1: { item: { title: 'Child 1', slug: '/docs/root1/child1' } }, + }, + }, + root2: { + item: { title: 'Root 2', isRootElement: true }, + children: { + child2: { item: { title: 'Child 2', slug: '/docs/root2/child2' } }, + }, + }, +}; + +const invalidTreePosts = ['tree1','tree2','tree3','tree4']; + +module.exports = { docPosts, treePosts, mockDocPosts, mockTreePosts, invalidTreePosts }; diff --git a/tests/fixtures/buildNavTreeData.js b/tests/fixtures/buildNavTreeData.js new file mode 100644 index 000000000000..99638901f810 --- /dev/null +++ b/tests/fixtures/buildNavTreeData.js @@ -0,0 +1,45 @@ +module.exports = { + basicNavItems: [ + { title: 'Welcome', weight: 0, isRootSection: true, isSection: true, rootSectionId: 'welcome', sectionWeight: 0, slug: '/docs' }, + { title: 'Getting Started', weight: 1, isRootSection: true, isSection: true, rootSectionId: 'getting-started', sectionWeight: 1, slug: '/docs/getting-started' }, + { title: 'Installation', weight: 0, isSection: false, rootSectionId: 'getting-started', sectionId: 'installation', slug: '/docs/getting-started/installation' }, + { title: 'Configuration', weight: 1, isSection: false, rootSectionId: 'getting-started', sectionId: 'configuration', slug: '/docs/getting-started/configuration' }, + { title: 'Reference', weight: 2, isRootSection: true, isSection: true, rootSectionId: 'reference', sectionWeight: 2, slug: '/docs/reference' }, + { title: 'API', weight: 0, isSection: true, rootSectionId: 'reference', sectionId: 'api', parent: 'reference', slug: '/docs/reference/api' }, + { title: 'Endpoints', weight: 0, isSection: false, rootSectionId: 'reference', sectionId: 'api', slug: '/docs/reference/api/endpoints' }, + { title: 'Specification', weight: 1, isSection: true, rootSectionId: 'reference', sectionId: 'specification', parent: 'reference', slug: '/docs/reference/specification' }, + { title: 'v1.0', weight: 0, isSection: false, rootSectionId: 'reference', sectionId: 'specification', slug: '/docs/reference/specification/v1.0', isPrerelease: false }, + { title: 'v2.0', weight: 1, isSection: false, rootSectionId: 'reference', sectionId: 'specification', slug: '/docs/reference/specification/v2.0', isPrerelease: true }, + { title: 'v3.0', weight: 2, isSection: false, rootSectionId: 'reference', sectionId: 'specification', slug: '/docs/reference/specification/v3.0' } + ], + + sectionNavItems: [ + { title: 'Root', weight: 0, isRootSection: true, isSection: true, rootSectionId: 'root', sectionWeight: 0, slug: '/docs' }, + { title: 'Item without sectionId', weight: 1, isSection: false, rootSectionId: 'root', slug: '/docs/item' }, + ], + + orphanNavItems: [ + { title: 'Orphaned Subsection', weight: 0, isSection: true, rootSectionId: 'root', sectionId: 'orphan', parent: 'non-existent-parent', slug: '/docs/orphaned' } + ], + + missingFieldsNavItems: [ + { title: 'Incomplete Item', weight: 0, isSection: false, rootSectionId: 'incomplete', slug: '/docs/incomplete' }, + ], + + invalidParentNavItems: [ + { title: 'Valid Root', weight: 0, isRootSection: true, isSection: true, rootSectionId: 'valid-root', sectionWeight: 0, slug: '/docs/valid-root' }, + { title: 'Child with invalid parent', weight: 1, isSection: true, rootSectionId: 'valid-root', sectionId: 'child-invalid', parent: 'non-existent-parent', slug: '/docs/valid-root/child-invalid' }, + ], + + multipleSubsectionsNavItems: [ + { title: 'Reference', weight: 0, isRootSection: true, isSection: true, rootSectionId: 'reference', sectionWeight: 0, slug: '/docs/reference' }, + { title: 'API', weight: 0, isSection: true, rootSectionId: 'reference', sectionId: 'api', parent: 'reference', slug: '/docs/reference/api' }, + { title: 'Endpoints', weight: 2, isSection: false, rootSectionId: 'reference', sectionId: 'api', slug: '/docs/reference/api/endpoints' }, + { title: 'Authentication', weight: 1, isSection: false, rootSectionId: 'reference', sectionId: 'api', slug: '/docs/reference/api/authentication' }, + { title: 'Rate Limiting', weight: 3, isSection: false, rootSectionId: 'reference', sectionId: 'api', slug: '/docs/reference/api/rate-limiting' }, + { title: 'Specification', weight: 1, isSection: true, rootSectionId: 'reference', sectionId: 'specification', parent: 'reference', slug: '/docs/reference/specification' }, + { title: 'v1.0', weight: 10, isSection: false, rootSectionId: 'reference', sectionId: 'specification', slug: '/docs/reference/specification/v1.0' }, + { title: 'v2.0', weight: 20, isSection: false, rootSectionId: 'reference', sectionId: 'specification', slug: '/docs/reference/specification/v2.0' }, + { title: 'v3.0', weight: 30, isSection: false, rootSectionId: 'reference', sectionId: 'specification', slug: '/docs/reference/specification/v3.0' } + ] +}; \ No newline at end of file diff --git a/tests/fixtures/convertDocPostData.js b/tests/fixtures/convertDocPostData.js new file mode 100644 index 000000000000..cf1d8217d6c8 --- /dev/null +++ b/tests/fixtures/convertDocPostData.js @@ -0,0 +1,31 @@ +const docObject = { + item: { title: 'Root', slug: '/root' }, + children: { + child1: { item: { title: 'Child 1', slug: '/child1' } }, + child2: { item: { title: 'Child 2', slug: '/child2' } }, + }, + }; + +const emptyDocObject = {}; + +const singlePostDocObject = { item: { title: 'Single Post', slug: '/single' } }; + +const nestedChildrenDocObject = { + item: { title: 'Root', slug: '/root' }, + children: { + child1: { + item: { title: 'Child 1', slug: '/child1' }, + children: { + grandchild1: { item: { title: 'Grandchild 1', slug: '/grandchild1' } }, + }, + }, + child2: { item: { title: 'Child 2', slug: '/child2' } }, + }, +}; + +module.exports = { + docObject, + emptyDocObject, + singlePostDocObject, + nestedChildrenDocObject +};