Skip to content

Commit 63c3584

Browse files
authored
Fix article count on landing pages to count recursively (#59423)
1 parent 7204116 commit 63c3584

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

src/landings/components/ProductArticlesList.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ActionList } from '@primer/react'
22

33
import { ProductTreeNode, useMainContext } from '@/frame/components/context/MainContext'
44
import { Link } from '@/frame/components/Link'
5+
import { countArticles } from '@/landings/lib/count-articles'
56
import clsx from 'clsx'
67
import styles from './ProductArticlesList.module.scss'
78

@@ -44,7 +45,7 @@ const ProductTreeNodeList = ({ treeNode }: { treeNode: ProductTreeNode }) => {
4445
{childNode.title}
4546
{childNode.childPages.length > 0 ? (
4647
<small className="color-fg-muted d-inline-block">
47-
&nbsp;&bull; {childNode.childPages.length} articles
48+
&nbsp;&bull; {countArticles(childNode)} articles
4849
</small>
4950
) : null}
5051
</ActionList.LinkItem>

src/landings/lib/count-articles.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { ProductTreeNode } from '@/frame/components/context/MainContext'
2+
3+
// Recursively counts all leaf articles (nodes without children) under a given node
4+
export const countArticles = (node: ProductTreeNode): number => {
5+
if (node.childPages.length === 0) {
6+
return 1
7+
}
8+
return node.childPages.reduce((sum, child) => sum + countArticles(child), 0)
9+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { describe, expect, test } from 'vitest'
2+
3+
import { countArticles } from '@/landings/lib/count-articles'
4+
import type { ProductTreeNode } from '@/frame/components/context/MainContext'
5+
6+
// Helper to create a minimal ProductTreeNode for testing
7+
const createNode = (childPages: ProductTreeNode[] = []): ProductTreeNode => ({
8+
title: 'Test',
9+
href: '/test',
10+
childPages,
11+
})
12+
13+
describe('countArticles', () => {
14+
test('returns 1 for a leaf node (no children)', () => {
15+
const leaf = createNode()
16+
expect(countArticles(leaf)).toBe(1)
17+
})
18+
19+
test('counts direct children when all are leaf nodes', () => {
20+
const node = createNode([createNode(), createNode(), createNode()])
21+
expect(countArticles(node)).toBe(3)
22+
})
23+
24+
test('counts all nested leaf articles recursively', () => {
25+
// Structure: parent -> 2 sections -> each with 3 articles = 6 total
26+
const section1 = createNode([createNode(), createNode(), createNode()])
27+
const section2 = createNode([createNode(), createNode(), createNode()])
28+
const parent = createNode([section1, section2])
29+
30+
expect(countArticles(parent)).toBe(6)
31+
})
32+
33+
test('handles deeply nested structure', () => {
34+
// 3 levels deep: parent -> section -> subsection -> 2 articles
35+
const subsection = createNode([createNode(), createNode()])
36+
const section = createNode([subsection])
37+
const parent = createNode([section])
38+
39+
expect(countArticles(parent)).toBe(2)
40+
})
41+
42+
test('handles mixed depth structure', () => {
43+
// parent -> section with 2 articles + section with subsection with 3 articles = 5 total
44+
const section1 = createNode([createNode(), createNode()])
45+
const subsection = createNode([createNode(), createNode(), createNode()])
46+
const section2 = createNode([subsection])
47+
const parent = createNode([section1, section2])
48+
49+
expect(countArticles(parent)).toBe(5)
50+
})
51+
})

0 commit comments

Comments
 (0)