@actuate-media/cms-admin 0.65.0 → 0.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/AdminRoot.d.ts.map +1 -1
  3. package/dist/AdminRoot.js +7 -4
  4. package/dist/AdminRoot.js.map +1 -1
  5. package/dist/__tests__/components/inspector-pane.test.d.ts +2 -0
  6. package/dist/__tests__/components/inspector-pane.test.d.ts.map +1 -0
  7. package/dist/__tests__/components/inspector-pane.test.js +31 -0
  8. package/dist/__tests__/components/inspector-pane.test.js.map +1 -0
  9. package/dist/__tests__/lib/pages-tree.test.d.ts +2 -0
  10. package/dist/__tests__/lib/pages-tree.test.d.ts.map +1 -0
  11. package/dist/__tests__/lib/pages-tree.test.js +173 -0
  12. package/dist/__tests__/lib/pages-tree.test.js.map +1 -0
  13. package/dist/__tests__/views/dashboard.test.js +7 -3
  14. package/dist/__tests__/views/dashboard.test.js.map +1 -1
  15. package/dist/__tests__/views/media-seo-audit.render.test.d.ts +2 -0
  16. package/dist/__tests__/views/media-seo-audit.render.test.d.ts.map +1 -0
  17. package/dist/__tests__/views/media-seo-audit.render.test.js +102 -0
  18. package/dist/__tests__/views/media-seo-audit.render.test.js.map +1 -0
  19. package/dist/__tests__/views/onboarding-block.render.test.d.ts +2 -0
  20. package/dist/__tests__/views/onboarding-block.render.test.d.ts.map +1 -0
  21. package/dist/__tests__/views/onboarding-block.render.test.js +146 -0
  22. package/dist/__tests__/views/onboarding-block.render.test.js.map +1 -0
  23. package/dist/__tests__/views/pages-list-view.test.js +77 -1
  24. package/dist/__tests__/views/pages-list-view.test.js.map +1 -1
  25. package/dist/actuate-admin.css +1 -1
  26. package/dist/components/script-tags/ScriptTagEditorPane.d.ts +26 -0
  27. package/dist/components/script-tags/ScriptTagEditorPane.d.ts.map +1 -0
  28. package/dist/components/script-tags/ScriptTagEditorPane.js +160 -0
  29. package/dist/components/script-tags/ScriptTagEditorPane.js.map +1 -0
  30. package/dist/components/ui/InspectorPane.d.ts +51 -0
  31. package/dist/components/ui/InspectorPane.d.ts.map +1 -0
  32. package/dist/components/ui/InspectorPane.js +42 -0
  33. package/dist/components/ui/InspectorPane.js.map +1 -0
  34. package/dist/components/ui/RowActions.d.ts +19 -0
  35. package/dist/components/ui/RowActions.d.ts.map +1 -0
  36. package/dist/components/ui/RowActions.js +16 -0
  37. package/dist/components/ui/RowActions.js.map +1 -0
  38. package/dist/components/ui/index.d.ts +4 -0
  39. package/dist/components/ui/index.d.ts.map +1 -1
  40. package/dist/components/ui/index.js +2 -0
  41. package/dist/components/ui/index.js.map +1 -1
  42. package/dist/layout/Header.js +1 -1
  43. package/dist/layout/Header.js.map +1 -1
  44. package/dist/layout/Layout.js +8 -38
  45. package/dist/layout/Layout.js.map +1 -1
  46. package/dist/lib/page-editor-service.d.ts +11 -2
  47. package/dist/lib/page-editor-service.d.ts.map +1 -1
  48. package/dist/lib/page-editor-service.js +8 -2
  49. package/dist/lib/page-editor-service.js.map +1 -1
  50. package/dist/lib/pages-service.d.ts +9 -0
  51. package/dist/lib/pages-service.d.ts.map +1 -1
  52. package/dist/lib/pages-service.js +14 -0
  53. package/dist/lib/pages-service.js.map +1 -1
  54. package/dist/lib/pages-tree.d.ts +44 -0
  55. package/dist/lib/pages-tree.d.ts.map +1 -0
  56. package/dist/lib/pages-tree.js +106 -0
  57. package/dist/lib/pages-tree.js.map +1 -0
  58. package/dist/lib/posts-service.d.ts +11 -0
  59. package/dist/lib/posts-service.d.ts.map +1 -1
  60. package/dist/lib/posts-service.js +13 -0
  61. package/dist/lib/posts-service.js.map +1 -1
  62. package/dist/lib/seo-service.d.ts +3 -0
  63. package/dist/lib/seo-service.d.ts.map +1 -1
  64. package/dist/lib/seo-service.js.map +1 -1
  65. package/dist/views/Dashboard.d.ts.map +1 -1
  66. package/dist/views/Dashboard.js +40 -3
  67. package/dist/views/Dashboard.js.map +1 -1
  68. package/dist/views/MediaBrowser.d.ts.map +1 -1
  69. package/dist/views/MediaBrowser.js +55 -2
  70. package/dist/views/MediaBrowser.js.map +1 -1
  71. package/dist/views/MediaSeoAudit.d.ts +25 -0
  72. package/dist/views/MediaSeoAudit.d.ts.map +1 -0
  73. package/dist/views/MediaSeoAudit.js +97 -0
  74. package/dist/views/MediaSeoAudit.js.map +1 -0
  75. package/dist/views/Pages/PagesListView.d.ts.map +1 -1
  76. package/dist/views/Pages/PagesListView.js +145 -16
  77. package/dist/views/Pages/PagesListView.js.map +1 -1
  78. package/dist/views/Pages/PagesTreeTable.d.ts +35 -0
  79. package/dist/views/Pages/PagesTreeTable.d.ts.map +1 -0
  80. package/dist/views/Pages/PagesTreeTable.js +28 -0
  81. package/dist/views/Pages/PagesTreeTable.js.map +1 -0
  82. package/dist/views/Posts/PostsListView.d.ts.map +1 -1
  83. package/dist/views/Posts/PostsListView.js +66 -9
  84. package/dist/views/Posts/PostsListView.js.map +1 -1
  85. package/dist/views/ScriptTags.d.ts +5 -1
  86. package/dist/views/ScriptTags.d.ts.map +1 -1
  87. package/dist/views/ScriptTags.js +32 -7
  88. package/dist/views/ScriptTags.js.map +1 -1
  89. package/dist/views/dashboard/OnboardingBlock.d.ts +29 -0
  90. package/dist/views/dashboard/OnboardingBlock.d.ts.map +1 -0
  91. package/dist/views/dashboard/OnboardingBlock.js +71 -0
  92. package/dist/views/dashboard/OnboardingBlock.js.map +1 -0
  93. package/dist/views/page-editor/PageSectionEditor.d.ts +7 -1
  94. package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
  95. package/dist/views/page-editor/PageSectionEditor.js +3 -3
  96. package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
  97. package/dist/views/page-editor/PageSettingsModal.d.ts +1 -1
  98. package/dist/views/page-editor/PageSettingsModal.d.ts.map +1 -1
  99. package/dist/views/page-editor/PageSettingsModal.js +42 -3
  100. package/dist/views/page-editor/PageSettingsModal.js.map +1 -1
  101. package/dist/views/seo/TechnicalTab.d.ts.map +1 -1
  102. package/dist/views/seo/TechnicalTab.js +15 -0
  103. package/dist/views/seo/TechnicalTab.js.map +1 -1
  104. package/package.json +3 -3
  105. package/src/AdminRoot.tsx +7 -3
  106. package/src/__tests__/components/inspector-pane.test.tsx +64 -0
  107. package/src/__tests__/lib/pages-tree.test.ts +197 -0
  108. package/src/__tests__/views/dashboard.test.tsx +7 -3
  109. package/src/__tests__/views/media-seo-audit.render.test.tsx +117 -0
  110. package/src/__tests__/views/onboarding-block.render.test.tsx +193 -0
  111. package/src/__tests__/views/pages-list-view.test.tsx +93 -1
  112. package/src/components/script-tags/ScriptTagEditorPane.tsx +474 -0
  113. package/src/components/ui/InspectorPane.tsx +129 -0
  114. package/src/components/ui/RowActions.tsx +50 -0
  115. package/src/components/ui/index.ts +12 -0
  116. package/src/layout/Header.tsx +2 -2
  117. package/src/layout/Layout.tsx +8 -80
  118. package/src/lib/page-editor-service.ts +16 -2
  119. package/src/lib/pages-service.ts +18 -0
  120. package/src/lib/pages-tree.ts +145 -0
  121. package/src/lib/posts-service.ts +26 -0
  122. package/src/lib/seo-service.ts +3 -0
  123. package/src/views/Dashboard.tsx +286 -214
  124. package/src/views/MediaBrowser.tsx +673 -512
  125. package/src/views/MediaSeoAudit.tsx +320 -0
  126. package/src/views/Pages/PagesListView.tsx +459 -185
  127. package/src/views/Pages/PagesTreeTable.tsx +339 -0
  128. package/src/views/Posts/PostsListView.tsx +135 -10
  129. package/src/views/ScriptTags.tsx +204 -129
  130. package/src/views/dashboard/OnboardingBlock.tsx +233 -0
  131. package/src/views/page-editor/PageSectionEditor.tsx +9 -2
  132. package/src/views/page-editor/PageSettingsModal.tsx +75 -2
  133. package/src/views/seo/TechnicalTab.tsx +15 -0
  134. package/dist/views/ScriptTagEditor.d.ts +0 -6
  135. package/dist/views/ScriptTagEditor.d.ts.map +0 -1
  136. package/dist/views/ScriptTagEditor.js +0 -111
  137. package/dist/views/ScriptTagEditor.js.map +0 -1
  138. package/src/views/ScriptTagEditor.tsx +0 -353
@@ -1 +1 @@
1
- {"version":3,"file":"TechnicalTab.js","sourceRoot":"","sources":["../../../src/views/seo/TechnicalTab.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TechnicalTab.js","sourceRoot":"","sources":["../../../src/views/seo/TechnicalTab.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actuate-media/cms-admin",
3
- "version": "0.65.0",
3
+ "version": "0.67.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/actuate-media/actuatecms.git",
@@ -95,8 +95,8 @@
95
95
  "tailwindcss": "^4.0.0",
96
96
  "typescript": "^5.7.0",
97
97
  "vitest": "^4.1.0",
98
- "@actuate-media/component-blocks": "0.2.1",
99
- "@actuate-media/cms-core": "0.85.3"
98
+ "@actuate-media/cms-core": "0.87.0",
99
+ "@actuate-media/component-blocks": "0.2.1"
100
100
  },
101
101
  "scripts": {
102
102
  "build": "tsc --project tsconfig.json && npx @tailwindcss/cli -i src/styles/build-input.css -o dist/actuate-admin.css --minify",
package/src/AdminRoot.tsx CHANGED
@@ -26,7 +26,6 @@ import { FormSubmissions } from './views/FormSubmissions.js'
26
26
  import { FormEntries } from './views/FormEntries.js'
27
27
  import { SEO } from './views/SEO.js'
28
28
  import { ScriptTags } from './views/ScriptTags.js'
29
- import { ScriptTagEditor } from './views/ScriptTagEditor.js'
30
29
  import { SetupWizard } from './views/SetupWizard.js'
31
30
  import { Login } from './views/Login.js'
32
31
  import { HiddenLoginNotFound } from './views/HiddenLoginNotFound.js'
@@ -432,8 +431,13 @@ function AdminShell({
432
431
  return <PageTagManager onNavigate={navigate} />
433
432
  }
434
433
  if (matchRoute('/pages/new')) {
434
+ // "Add sub-page" in the Pages tree view arrives with the parent id
435
+ // in the query string (`/pages/new?parent=<id>`); matchRoute ignores
436
+ // the query so it's parsed here and preselected in the editor.
437
+ const newPageQuery = new URLSearchParams(currentPath.split('?')[1] ?? '')
435
438
  return (
436
439
  <PageSectionEditor
440
+ initialParentId={newPageQuery.get('parent')}
437
441
  config={config}
438
442
  session={session}
439
443
  onNavigate={navigate}
@@ -509,11 +513,11 @@ function AdminShell({
509
513
  }
510
514
 
511
515
  if (matchRoute('/script-tags/new')) {
512
- return <ScriptTagEditor onNavigate={navigate} />
516
+ return <ScriptTags onNavigate={navigate} initialNew />
513
517
  }
514
518
  const scriptTagEdit = matchRoute('/script-tags/:id')
515
519
  if (scriptTagEdit?.id) {
516
- return <ScriptTagEditor tagId={scriptTagEdit.id} onNavigate={navigate} />
520
+ return <ScriptTags onNavigate={navigate} initialSelectedId={scriptTagEdit.id} />
517
521
  }
518
522
  if (matchRoute('/script-tags')) {
519
523
  return <ScriptTags onNavigate={navigate} />
@@ -0,0 +1,64 @@
1
+ // @vitest-environment happy-dom
2
+ import { describe, expect, it, vi } from 'vitest'
3
+ import { render, screen } from '@testing-library/react'
4
+ import {
5
+ InspectorPane,
6
+ InspectorPaneBody,
7
+ InspectorPaneFooter,
8
+ InspectorPaneHeader,
9
+ InspectorPaneSection,
10
+ SplitPaneLayout,
11
+ SplitPaneList,
12
+ } from '../../components/ui/InspectorPane.js'
13
+
14
+ function Pane({ open }: { open: boolean }) {
15
+ return (
16
+ <SplitPaneLayout>
17
+ <SplitPaneList>
18
+ <table aria-label="Rows" />
19
+ </SplitPaneList>
20
+ <InspectorPane open={open} width={420} aria-label="Row editor">
21
+ <InspectorPaneHeader onClose={() => {}}>
22
+ <span>Editing</span>
23
+ </InspectorPaneHeader>
24
+ <InspectorPaneBody>
25
+ <InspectorPaneSection title="Details">content</InspectorPaneSection>
26
+ </InspectorPaneBody>
27
+ <InspectorPaneFooter>
28
+ <button type="button">Save</button>
29
+ </InspectorPaneFooter>
30
+ </InspectorPane>
31
+ </SplitPaneLayout>
32
+ )
33
+ }
34
+
35
+ describe('InspectorPane', () => {
36
+ it('renders pane content with a labelled region when open', () => {
37
+ render(<Pane open />)
38
+ expect(screen.getByRole('region', { name: 'Row editor' })).toBeTruthy()
39
+ expect(screen.getByText('Editing')).toBeTruthy()
40
+ expect(screen.getByText('Details')).toBeTruthy()
41
+ expect(screen.getByRole('button', { name: 'Save' })).toBeTruthy()
42
+ })
43
+
44
+ it('collapses to zero width and hides content when closed', () => {
45
+ const { container } = render(<Pane open={false} />)
46
+ const shell = container.querySelector('[aria-hidden="true"]') as HTMLElement
47
+ expect(shell).toBeTruthy()
48
+ expect(shell.style.width).toBe('0px')
49
+ expect(screen.queryByText('Editing')).toBeNull()
50
+ })
51
+
52
+ it('close button in the header fires onClose with an accessible label', () => {
53
+ const onClose = vi.fn()
54
+ render(
55
+ <InspectorPane open width={400} aria-label="Detail">
56
+ <InspectorPaneHeader onClose={onClose} closeLabel="Close detail">
57
+ <span>Title</span>
58
+ </InspectorPaneHeader>
59
+ </InspectorPane>,
60
+ )
61
+ screen.getByRole('button', { name: 'Close detail' }).click()
62
+ expect(onClose).toHaveBeenCalledTimes(1)
63
+ })
64
+ })
@@ -0,0 +1,197 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ buildPageTree,
4
+ defaultExpandedIds,
5
+ flattenPageTree,
6
+ type PageTreeNode,
7
+ } from '../../lib/pages-tree.js'
8
+ import type { Page } from '../../lib/pages-service.js'
9
+
10
+ /**
11
+ * Unit coverage for the Pages tree hierarchy resolution. Pure functions —
12
+ * locked independent of the REST layer and the view. The contract:
13
+ * explicit `parentPageId` wins, path-prefix derivation fills the gaps,
14
+ * and no input (orphans, cycles, duplicates) can lose or duplicate a page.
15
+ */
16
+
17
+ function page(partial: Partial<Page> & Pick<Page, 'id' | 'title' | 'path'>): Page {
18
+ return {
19
+ id: partial.id,
20
+ title: partial.title,
21
+ path: partial.path,
22
+ slug: partial.slug ?? partial.path.split('/').filter(Boolean).pop() ?? '',
23
+ parentPageId: partial.parentPageId ?? null,
24
+ tags: [],
25
+ primaryTagId: null,
26
+ authorId: 'u1',
27
+ authorName: 'Maria K.',
28
+ authorInitials: 'MK',
29
+ status: partial.status ?? 'PUBLISHED',
30
+ publishDate: null,
31
+ scheduledDate: null,
32
+ lastModified: '2026-05-01',
33
+ seoScore: null,
34
+ seoTitle: null,
35
+ seoDescription: null,
36
+ templateId: partial.templateId ?? null,
37
+ isHomepage: partial.path === '/',
38
+ isSystemPage: false,
39
+ createdAt: '2026-01-01',
40
+ updatedAt: '2026-05-01',
41
+ }
42
+ }
43
+
44
+ function titles(nodes: PageTreeNode[]): string[] {
45
+ return nodes.map((n) => n.page.title)
46
+ }
47
+
48
+ function countNodes(nodes: PageTreeNode[]): number {
49
+ return nodes.reduce((n, node) => n + 1 + countNodes(node.children), 0)
50
+ }
51
+
52
+ describe('buildPageTree', () => {
53
+ it('nests children under explicit parentPageId parents', () => {
54
+ const roots = buildPageTree([
55
+ page({ id: 'about', title: 'About Us', path: '/about' }),
56
+ page({ id: 'team', title: 'Our Team', path: '/team-page', parentPageId: 'about' }),
57
+ ])
58
+ expect(titles(roots)).toEqual(['About Us'])
59
+ expect(titles(roots[0]!.children)).toEqual(['Our Team'])
60
+ })
61
+
62
+ it('derives parents from path prefixes when parentPageId is null', () => {
63
+ const roots = buildPageTree([
64
+ page({ id: 'home', title: 'Home', path: '/' }),
65
+ page({ id: 'about', title: 'About Us', path: '/about' }),
66
+ page({ id: 'team', title: 'Our Team', path: '/about/team' }),
67
+ page({ id: 'story', title: 'Our Story', path: '/about/story' }),
68
+ page({ id: 'contact', title: 'Contact', path: '/contact' }),
69
+ ])
70
+ expect(titles(roots)).toEqual(['About Us', 'Contact', 'Home'])
71
+ const about = roots[0]!
72
+ expect(titles(about.children)).toEqual(['Our Story', 'Our Team'])
73
+ })
74
+
75
+ it('skips missing intermediate path levels to the longest existing prefix', () => {
76
+ const roots = buildPageTree([
77
+ page({ id: 'svc', title: 'Services', path: '/services' }),
78
+ // No "/services/web" page exists — attaches to "/services".
79
+ page({ id: 'design', title: 'Web Design', path: '/services/web/design' }),
80
+ ])
81
+ expect(titles(roots)).toEqual(['Services'])
82
+ expect(titles(roots[0]!.children)).toEqual(['Web Design'])
83
+ })
84
+
85
+ it('never derives the homepage ("/") as a path parent', () => {
86
+ const roots = buildPageTree([
87
+ page({ id: 'home', title: 'Home', path: '/' }),
88
+ page({ id: 'blog', title: 'Blog', path: '/blog' }),
89
+ ])
90
+ expect(titles(roots)).toEqual(['Blog', 'Home'])
91
+ })
92
+
93
+ it('prefers explicit parentPageId over the path prefix', () => {
94
+ const roots = buildPageTree([
95
+ page({ id: 'about', title: 'About', path: '/about' }),
96
+ page({ id: 'lp', title: 'Landing', path: '/lp' }),
97
+ // Path says "/about/…" but the explicit link says "lp" — link wins.
98
+ page({ id: 'x', title: 'Campaign', path: '/about/campaign', parentPageId: 'lp' }),
99
+ ])
100
+ const lp = roots.find((n) => n.page.id === 'lp')!
101
+ expect(titles(lp.children)).toEqual(['Campaign'])
102
+ expect(roots.find((n) => n.page.id === 'about')!.children).toHaveLength(0)
103
+ })
104
+
105
+ it('treats orphans (parent not in the set) as roots', () => {
106
+ const roots = buildPageTree([
107
+ page({ id: 'a', title: 'A', path: '/a', parentPageId: 'missing' }),
108
+ page({ id: 'b', title: 'B', path: '/b' }),
109
+ ])
110
+ expect(titles(roots)).toEqual(['A', 'B'])
111
+ })
112
+
113
+ it('breaks parentPageId cycles to the root without losing pages', () => {
114
+ const roots = buildPageTree([
115
+ page({ id: 'a', title: 'A', path: '/x-a', parentPageId: 'b' }),
116
+ page({ id: 'b', title: 'B', path: '/x-b', parentPageId: 'a' }),
117
+ page({ id: 'c', title: 'C', path: '/x-c' }),
118
+ ])
119
+ expect(countNodes(roots)).toBe(3)
120
+ // One of the cycle members must have been rooted.
121
+ const rootIds = roots.map((n) => n.page.id)
122
+ expect(rootIds).toContain('c')
123
+ expect(rootIds.some((id) => id === 'a' || id === 'b')).toBe(true)
124
+ })
125
+
126
+ it('ignores a self-referencing parentPageId', () => {
127
+ const roots = buildPageTree([page({ id: 'a', title: 'A', path: '/a', parentPageId: 'a' })])
128
+ expect(titles(roots)).toEqual(['A'])
129
+ })
130
+
131
+ it('orders siblings by title then path, at every depth', () => {
132
+ const roots = buildPageTree([
133
+ page({ id: 'svc', title: 'Services', path: '/services' }),
134
+ page({ id: 's2', title: 'Web Design', path: '/services/web-design' }),
135
+ page({ id: 's1', title: 'CMS Solutions', path: '/services/cms' }),
136
+ page({ id: 's3', title: 'SEO Services', path: '/services/seo' }),
137
+ page({ id: 'blog', title: 'Blog', path: '/blog' }),
138
+ ])
139
+ expect(titles(roots)).toEqual(['Blog', 'Services'])
140
+ expect(titles(roots.find((n) => n.page.id === 'svc')!.children)).toEqual([
141
+ 'CMS Solutions',
142
+ 'SEO Services',
143
+ 'Web Design',
144
+ ])
145
+ })
146
+
147
+ it('keeps every page exactly once on messy input', () => {
148
+ const pages = [
149
+ page({ id: 'home', title: 'Home', path: '/' }),
150
+ page({ id: 'dup1', title: 'Dup A', path: '/dup' }),
151
+ page({ id: 'dup2', title: 'Dup B', path: '/dup' }),
152
+ page({ id: 'kid', title: 'Kid', path: '/dup/kid' }),
153
+ page({ id: 'cyc1', title: 'Cyc 1', path: '/c1', parentPageId: 'cyc2' }),
154
+ page({ id: 'cyc2', title: 'Cyc 2', path: '/c2', parentPageId: 'cyc1' }),
155
+ page({ id: 'orph', title: 'Orphan', path: '/orphan', parentPageId: 'gone' }),
156
+ ]
157
+ const roots = buildPageTree(pages)
158
+ expect(countNodes(roots)).toBe(pages.length)
159
+ // "/dup/kid" attaches to the first page seen with path "/dup".
160
+ expect(roots.some((n) => n.page.id === 'dup1' && n.children.length === 1)).toBe(true)
161
+ })
162
+ })
163
+
164
+ describe('flattenPageTree', () => {
165
+ const roots = buildPageTree([
166
+ page({ id: 'about', title: 'About Us', path: '/about' }),
167
+ page({ id: 'team', title: 'Our Team', path: '/about/team' }),
168
+ page({ id: 'blog', title: 'Blog', path: '/blog' }),
169
+ ])
170
+
171
+ it('renders children only when the parent is expanded', () => {
172
+ const collapsed = flattenPageTree(roots, new Set())
173
+ expect(collapsed.map((r) => r.page.id)).toEqual(['about', 'blog'])
174
+
175
+ const open = flattenPageTree(roots, new Set(['about']))
176
+ expect(open.map((r) => r.page.id)).toEqual(['about', 'team', 'blog'])
177
+ })
178
+
179
+ it('reports depth and hasChildren per row', () => {
180
+ const rows = flattenPageTree(roots, new Set(['about']))
181
+ expect(rows[0]).toMatchObject({ depth: 0, hasChildren: true })
182
+ expect(rows[1]).toMatchObject({ depth: 1, hasChildren: false })
183
+ expect(rows[2]).toMatchObject({ depth: 0, hasChildren: false })
184
+ })
185
+ })
186
+
187
+ describe('defaultExpandedIds', () => {
188
+ it('expands only root nodes that have children', () => {
189
+ const roots = buildPageTree([
190
+ page({ id: 'about', title: 'About Us', path: '/about' }),
191
+ page({ id: 'team', title: 'Our Team', path: '/about/team' }),
192
+ page({ id: 'deep', title: 'Deep', path: '/about/team/deep' }),
193
+ page({ id: 'blog', title: 'Blog', path: '/blog' }),
194
+ ])
195
+ expect([...defaultExpandedIds(roots)]).toEqual(['about'])
196
+ })
197
+ })
@@ -59,13 +59,17 @@ describe('Dashboard', () => {
59
59
  expect(screen.queryByText('Recent Activity')).toBeNull()
60
60
  })
61
61
 
62
- it('shows empty states when there is no content', () => {
62
+ it('shows the onboarding block instead of the activity grid when there is no content', () => {
63
63
  responses['/stats'] = statsResult()
64
64
 
65
65
  render(<Dashboard config={{ collections: [] }} session={{}} onNavigate={() => {}} />)
66
66
 
67
- expect(screen.getByText('No activity yet')).toBeTruthy()
68
- expect(screen.getByText('No scheduled content')).toBeTruthy()
67
+ // An effectively-empty site (zero posts+pages, zero media) swaps the
68
+ // Recent Activity / Publishing Queue / Content Health grid for the
69
+ // getting-started onboarding block.
70
+ expect(screen.getByText(/Welcome to ActuateCMS/)).toBeTruthy()
71
+ expect(screen.queryByText('No activity yet')).toBeNull()
72
+ expect(screen.queryByText('No scheduled content')).toBeNull()
69
73
  })
70
74
 
71
75
  it('surfaces a retryable banner when the stats request is exhausted', () => {
@@ -0,0 +1,117 @@
1
+ // @vitest-environment happy-dom
2
+ import { describe, expect, it, vi } from 'vitest'
3
+ import { fireEvent, render, screen, within } from '@testing-library/react'
4
+
5
+ import { MediaSeoAudit, type MediaSeoAuditItem } from '../../views/MediaSeoAudit.js'
6
+
7
+ // Scores mirror what cms-core's `calculateMediaSeoScore()` would return for
8
+ // each row — the component never re-scores, it renders `seoScore` as-is.
9
+ const ITEMS: MediaSeoAuditItem[] = [
10
+ {
11
+ id: 'complete',
12
+ name: 'seattle-team.webp',
13
+ type: 'image/webp',
14
+ size: '120 KB',
15
+ url: 'https://cdn.example.com/seattle-team.webp',
16
+ format: 'webp',
17
+ altTag: 'Team collaborating in the Seattle office',
18
+ title: 'Seattle Team',
19
+ description: 'The team collaborating in the Seattle office.',
20
+ seoScore: 100,
21
+ },
22
+ {
23
+ id: 'no-alt',
24
+ name: 'hero-banner.jpg',
25
+ type: 'image/jpeg',
26
+ size: '342 KB',
27
+ url: 'https://cdn.example.com/hero-banner.jpg',
28
+ format: 'jpeg',
29
+ altTag: '',
30
+ title: 'Hero Banner',
31
+ description: 'Homepage hero banner.',
32
+ seoScore: 70,
33
+ },
34
+ {
35
+ id: 'bare',
36
+ name: 'IMG_4892.jpg',
37
+ type: 'image/jpeg',
38
+ size: '1.8 MB',
39
+ url: 'https://cdn.example.com/IMG_4892.jpg',
40
+ format: 'jpeg',
41
+ altTag: '',
42
+ title: '',
43
+ description: '',
44
+ seoScore: 0,
45
+ },
46
+ ]
47
+
48
+ describe('MediaSeoAudit', () => {
49
+ it('renders the four summary stat cards from item metadata', () => {
50
+ render(<MediaSeoAudit items={ITEMS} onEdit={vi.fn()} />)
51
+
52
+ // Avg = round((100 + 70 + 0) / 3) = 57 → "Fair"
53
+ expect(screen.getByText('57/100')).toBeTruthy()
54
+ expect(screen.getByText('Avg SEO Score')).toBeTruthy()
55
+ expect(screen.getByText('Fair')).toBeTruthy()
56
+
57
+ expect(screen.getByText('Missing Alt Text')).toBeTruthy()
58
+ expect(screen.getByText('1 have alt text')).toBeTruthy()
59
+ expect(screen.getByText('Missing Titles')).toBeTruthy()
60
+ expect(screen.getByText('2 have titles')).toBeTruthy()
61
+ expect(screen.getByText('Missing Descriptions')).toBeTruthy()
62
+ expect(screen.getByText('2 have descriptions')).toBeTruthy()
63
+ })
64
+
65
+ it('shows all items by default with a right-aligned count', () => {
66
+ render(<MediaSeoAudit items={ITEMS} onEdit={vi.fn()} />)
67
+
68
+ const table = screen.getByRole('table', { name: 'Media SEO audit' })
69
+ expect(within(table).getAllByRole('row')).toHaveLength(4) // header + 3 items
70
+ expect(screen.getByText('3 items')).toBeTruthy()
71
+ })
72
+
73
+ it('filters to items missing alt text', () => {
74
+ render(<MediaSeoAudit items={ITEMS} onEdit={vi.fn()} />)
75
+
76
+ fireEvent.click(screen.getByRole('button', { name: 'Missing Alt' }))
77
+
78
+ const table = screen.getByRole('table', { name: 'Media SEO audit' })
79
+ expect(within(table).getAllByRole('row')).toHaveLength(3) // header + 2 items
80
+ expect(within(table).queryByText('seattle-team.webp')).toBeNull()
81
+ expect(screen.getByText('2 items')).toBeTruthy()
82
+ })
83
+
84
+ it('filters to poor scores (score < 40)', () => {
85
+ render(<MediaSeoAudit items={ITEMS} onEdit={vi.fn()} />)
86
+
87
+ fireEvent.click(screen.getByRole('button', { name: 'Poor score' }))
88
+
89
+ const table = screen.getByRole('table', { name: 'Media SEO audit' })
90
+ expect(within(table).getAllByRole('row')).toHaveLength(2) // header + 1 item
91
+ expect(within(table).getByText('IMG_4892.jpg')).toBeTruthy()
92
+ expect(screen.getByText('1 item')).toBeTruthy()
93
+ })
94
+
95
+ it('fires onEdit with the row item from the Edit button', () => {
96
+ const onEdit = vi.fn()
97
+ render(<MediaSeoAudit items={ITEMS} onEdit={onEdit} />)
98
+
99
+ const buttons = screen.getAllByRole('button', { name: 'Edit' })
100
+ expect(buttons).toHaveLength(3)
101
+ fireEvent.click(buttons[1]!)
102
+ expect(onEdit).toHaveBeenCalledTimes(1)
103
+ expect(onEdit.mock.calls[0]![0].id).toBe('no-alt')
104
+ })
105
+
106
+ it('shows an empty state when there is nothing to audit', () => {
107
+ render(<MediaSeoAudit items={[]} onEdit={vi.fn()} />)
108
+ expect(screen.getByText('No media to audit')).toBeTruthy()
109
+ expect(screen.queryByRole('table')).toBeNull()
110
+ })
111
+
112
+ it('shows a filter-specific empty state when a filter matches nothing', () => {
113
+ render(<MediaSeoAudit items={[ITEMS[0]!]} onEdit={vi.fn()} />)
114
+ fireEvent.click(screen.getByRole('button', { name: 'Missing Alt' }))
115
+ expect(screen.getByText('No items match this filter')).toBeTruthy()
116
+ })
117
+ })