@prenta/admin 0.93.0 → 0.95.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 (130) hide show
  1. package/CHANGELOG.md +152 -0
  2. package/dist/__tests__/lib/page-editor-service-api.test.js +37 -0
  3. package/dist/__tests__/lib/page-editor-service-api.test.js.map +1 -1
  4. package/dist/__tests__/lib/version-diff.test.d.ts +2 -0
  5. package/dist/__tests__/lib/version-diff.test.d.ts.map +1 -0
  6. package/dist/__tests__/lib/version-diff.test.js +230 -0
  7. package/dist/__tests__/lib/version-diff.test.js.map +1 -0
  8. package/dist/__tests__/lib/version-history.test.d.ts +2 -0
  9. package/dist/__tests__/lib/version-history.test.d.ts.map +1 -0
  10. package/dist/__tests__/lib/version-history.test.js +125 -0
  11. package/dist/__tests__/lib/version-history.test.js.map +1 -0
  12. package/dist/__tests__/styles/responsive-layer.test.d.ts +2 -0
  13. package/dist/__tests__/styles/responsive-layer.test.d.ts.map +1 -0
  14. package/dist/__tests__/styles/responsive-layer.test.js +127 -0
  15. package/dist/__tests__/styles/responsive-layer.test.js.map +1 -0
  16. package/dist/__tests__/views/canvas-review-mode.render.test.d.ts +2 -0
  17. package/dist/__tests__/views/canvas-review-mode.render.test.d.ts.map +1 -0
  18. package/dist/__tests__/views/canvas-review-mode.render.test.js +70 -0
  19. package/dist/__tests__/views/canvas-review-mode.render.test.js.map +1 -0
  20. package/dist/__tests__/views/editor-top-bar.render.test.js +29 -0
  21. package/dist/__tests__/views/editor-top-bar.render.test.js.map +1 -1
  22. package/dist/__tests__/views/section-edit-form.render.test.d.ts +2 -0
  23. package/dist/__tests__/views/section-edit-form.render.test.d.ts.map +1 -0
  24. package/dist/__tests__/views/section-edit-form.render.test.js +124 -0
  25. package/dist/__tests__/views/section-edit-form.render.test.js.map +1 -0
  26. package/dist/__tests__/views/section-inspector-media.test.js +1 -1
  27. package/dist/__tests__/views/section-inspector-media.test.js.map +1 -1
  28. package/dist/__tests__/views/section-inspector-repeater.render.test.js +2 -1
  29. package/dist/__tests__/views/section-inspector-repeater.render.test.js.map +1 -1
  30. package/dist/__tests__/views/version-history-panel.render.test.d.ts +2 -0
  31. package/dist/__tests__/views/version-history-panel.render.test.d.ts.map +1 -0
  32. package/dist/__tests__/views/version-history-panel.render.test.js +153 -0
  33. package/dist/__tests__/views/version-history-panel.render.test.js.map +1 -0
  34. package/dist/components/CanvasEditTip.js +1 -1
  35. package/dist/components/CanvasEditTip.js.map +1 -1
  36. package/dist/components/EditorRail.js +3 -3
  37. package/dist/components/EditorRail.js.map +1 -1
  38. package/dist/components/page-tab/DirectiveSwitch.d.ts.map +1 -1
  39. package/dist/components/page-tab/DirectiveSwitch.js +5 -1
  40. package/dist/components/page-tab/DirectiveSwitch.js.map +1 -1
  41. package/dist/layout/primitives/AdminShell.d.ts.map +1 -1
  42. package/dist/layout/primitives/AdminShell.js +2 -2
  43. package/dist/layout/primitives/AdminShell.js.map +1 -1
  44. package/dist/lib/version-diff.d.ts +50 -0
  45. package/dist/lib/version-diff.d.ts.map +1 -0
  46. package/dist/lib/version-diff.js +294 -0
  47. package/dist/lib/version-diff.js.map +1 -0
  48. package/dist/lib/version-history.d.ts +73 -0
  49. package/dist/lib/version-history.d.ts.map +1 -0
  50. package/dist/lib/version-history.js +126 -0
  51. package/dist/lib/version-history.js.map +1 -0
  52. package/dist/prenta-admin.css +1 -1
  53. package/dist/views/page-editor/EditorCanvas.d.ts +14 -1
  54. package/dist/views/page-editor/EditorCanvas.d.ts.map +1 -1
  55. package/dist/views/page-editor/EditorCanvas.js +3 -3
  56. package/dist/views/page-editor/EditorCanvas.js.map +1 -1
  57. package/dist/views/page-editor/EditorTopBar.d.ts +8 -2
  58. package/dist/views/page-editor/EditorTopBar.d.ts.map +1 -1
  59. package/dist/views/page-editor/EditorTopBar.js +8 -6
  60. package/dist/views/page-editor/EditorTopBar.js.map +1 -1
  61. package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
  62. package/dist/views/page-editor/PageSectionEditor.js +129 -40
  63. package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
  64. package/dist/views/page-editor/ReviewBar.d.ts +21 -0
  65. package/dist/views/page-editor/ReviewBar.d.ts.map +1 -0
  66. package/dist/views/page-editor/ReviewBar.js +22 -0
  67. package/dist/views/page-editor/ReviewBar.js.map +1 -0
  68. package/dist/views/page-editor/SectionEditForm.d.ts +42 -0
  69. package/dist/views/page-editor/SectionEditForm.d.ts.map +1 -0
  70. package/dist/views/page-editor/SectionEditForm.js +48 -0
  71. package/dist/views/page-editor/SectionEditForm.js.map +1 -0
  72. package/dist/views/page-editor/SectionInspector.d.ts +0 -20
  73. package/dist/views/page-editor/SectionInspector.d.ts.map +1 -1
  74. package/dist/views/page-editor/SectionInspector.js +6 -224
  75. package/dist/views/page-editor/SectionInspector.js.map +1 -1
  76. package/dist/views/page-editor/SectionsPanel.d.ts +10 -1
  77. package/dist/views/page-editor/SectionsPanel.d.ts.map +1 -1
  78. package/dist/views/page-editor/SectionsPanel.js +11 -5
  79. package/dist/views/page-editor/SectionsPanel.js.map +1 -1
  80. package/dist/views/page-editor/VersionHistoryPanel.d.ts +29 -0
  81. package/dist/views/page-editor/VersionHistoryPanel.d.ts.map +1 -0
  82. package/dist/views/page-editor/VersionHistoryPanel.js +81 -0
  83. package/dist/views/page-editor/VersionHistoryPanel.js.map +1 -0
  84. package/dist/views/page-editor/section-fields.d.ts +43 -0
  85. package/dist/views/page-editor/section-fields.d.ts.map +1 -0
  86. package/dist/views/page-editor/section-fields.js +236 -0
  87. package/dist/views/page-editor/section-fields.js.map +1 -0
  88. package/dist/views/page-editor/sections/ArticleBodySection.js +1 -1
  89. package/dist/views/page-editor/sections/ArticleBodySection.js.map +1 -1
  90. package/dist/views/page-editor/sections/SectionRenderer.d.ts +13 -1
  91. package/dist/views/page-editor/sections/SectionRenderer.d.ts.map +1 -1
  92. package/dist/views/page-editor/sections/SectionRenderer.js +23 -8
  93. package/dist/views/page-editor/sections/SectionRenderer.js.map +1 -1
  94. package/dist/views/post-editor/PostEditorCanvas.js +1 -1
  95. package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
  96. package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
  97. package/dist/views/post-editor/PostSectionEditor.js +11 -9
  98. package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
  99. package/package.json +3 -3
  100. package/src/__tests__/lib/page-editor-service-api.test.ts +44 -0
  101. package/src/__tests__/lib/version-diff.test.ts +278 -0
  102. package/src/__tests__/lib/version-history.test.ts +166 -0
  103. package/src/__tests__/styles/responsive-layer.test.ts +152 -0
  104. package/src/__tests__/views/canvas-review-mode.render.test.tsx +94 -0
  105. package/src/__tests__/views/editor-top-bar.render.test.tsx +42 -0
  106. package/src/__tests__/views/section-edit-form.render.test.tsx +162 -0
  107. package/src/__tests__/views/section-inspector-media.test.ts +1 -1
  108. package/src/__tests__/views/section-inspector-repeater.render.test.tsx +2 -1
  109. package/src/__tests__/views/version-history-panel.render.test.tsx +195 -0
  110. package/src/components/CanvasEditTip.tsx +3 -3
  111. package/src/components/EditorRail.tsx +5 -5
  112. package/src/components/page-tab/DirectiveSwitch.tsx +4 -1
  113. package/src/layout/primitives/AdminShell.tsx +13 -1
  114. package/src/lib/version-diff.ts +376 -0
  115. package/src/lib/version-history.ts +192 -0
  116. package/src/styles/responsive.css +281 -0
  117. package/src/styles/theme.css +8 -0
  118. package/src/views/page-editor/EditorCanvas.tsx +34 -7
  119. package/src/views/page-editor/EditorTopBar.tsx +20 -8
  120. package/src/views/page-editor/PageSectionEditor.tsx +182 -65
  121. package/src/views/page-editor/ReviewBar.tsx +76 -0
  122. package/src/views/page-editor/SectionEditForm.tsx +161 -0
  123. package/src/views/page-editor/SectionInspector.tsx +9 -553
  124. package/src/views/page-editor/SectionsPanel.tsx +72 -16
  125. package/src/views/page-editor/VersionHistoryPanel.tsx +302 -0
  126. package/src/views/page-editor/section-fields.tsx +563 -0
  127. package/src/views/page-editor/sections/ArticleBodySection.tsx +1 -1
  128. package/src/views/page-editor/sections/SectionRenderer.tsx +53 -12
  129. package/src/views/post-editor/PostEditorCanvas.tsx +1 -1
  130. package/src/views/post-editor/PostSectionEditor.tsx +18 -26
package/CHANGELOG.md CHANGED
@@ -1,5 +1,157 @@
1
1
  # @actuate-media/cms-admin
2
2
 
3
+ ## 0.95.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 209939e: Edit sections inside the list, and stop offering design controls
8
+
9
+ The section editor was a third column docked on the right. The design puts it
10
+ inside the row it belongs to — click a section, it opens underneath — and never
11
+ had a right-hand panel at all.
12
+
13
+ **This was an unfinished migration, not a decision.** The rail work that
14
+ introduced the tab strip moved the SEO pane out of a right-hand aside and said
15
+ why: "so the editor has one settings surface rather than two competing ones."
16
+ It retired that aside and left the section inspector sitting in the same
17
+ column — the very surface that sentence names. The inspector predates the whole
18
+ handoff, so no stage owned retiring it, and it went unrecorded in the followups
19
+ doc. Both content editors now open the form in the row; a chevron on each row
20
+ says it opens at all, which the old list never did.
21
+
22
+ **No more styling controls.** The panel offered Background, Colour, Spacing and
23
+ CSS class. `docs/design-owned-sections.md` opens with "the editor changes copy,
24
+ CTAs, and imagery — never layout, order, or styling", and the handoff is
25
+ blunter: "if a feature would let an editor change layout, it does not belong."
26
+ The controls contradicted the rule from one panel away from the sentence
27
+ stating it. This CMS edits headings, body copy, images and embed code; the rest
28
+ comes from the template.
29
+
30
+ **The values are untouched.** `settings` round-trips through save exactly as
31
+ before and the renderers keep reading it, so every existing page renders
32
+ identically — the editor simply stops offering to change it. Removing a control
33
+ and dropping the data are very different changes and only the first has
34
+ happened; a test asserts every settings key survives both save and publish. The
35
+ post **template** editor keeps the full set, including the docked inspector,
36
+ because authoring a template is where styling genuinely belongs.
37
+
38
+ Field renderers moved to `section-fields.tsx` so the inline form and the
39
+ template inspector share one implementation rather than a copy each — this
40
+ codebase has twice paid for a duplicated renderer drifting from its original.
41
+
42
+ Also corrects three bits of copy that still directed people to "the inspector".
43
+
44
+ ## 0.94.0
45
+
46
+ ### Minor Changes
47
+
48
+ - 385dd10: Responsive + accessibility layer
49
+
50
+ Ports `design-system/cms-responsive.css` from the page-builder design bundle,
51
+ which the prototype now links and which post-dates the handoff copy in
52
+ `design_handoff_page_builder/` (followup 7: the bundle in hand had one `:focus`
53
+ rule, no `:focus-visible`, no reduced-motion, no contrast preference). None of
54
+ it existed in the admin.
55
+
56
+ The prototype's selectors (`.ni`, `.sec-panel`, `.icbtn`) do not exist here —
57
+ this admin is Tailwind over the same tokens — so the **rules** are ported and
58
+ re-expressed against the real structure, in one stylesheet scoped throughout to
59
+ `.prenta-admin`. The admin renders inside consumer applications; an unscoped
60
+ `@media print` or `:focus-visible` rule would restyle the host's own pages, and
61
+ a test asserts every selector in the file carries the scope.
62
+ - **Visible focus everywhere**, as a floor. Base-layer, so any component with
63
+ its own `focus-visible:ring` still wins and this only fills the gaps.
64
+ - **A skip link** — the first focusable thing in the admin, so a keyboard user's
65
+ first Tab offers a jump past ~20 sidebar items.
66
+ - **`prefers-reduced-motion`** honoured as a media query, not only through the
67
+ Appearance setting and the `motion-safe:` utilities that were written with it.
68
+ - **`prefers-contrast: more`** raises the three tertiary tokens, in both themes,
69
+ and a test asserts it raises rather than lowers — the shipped `--muted` is
70
+ already an AA correction over the handoff's value, and a "more contrast"
71
+ preference that moved it the other way would be worse than ignoring it.
72
+ - **44px touch targets under a coarse pointer**, opt-in per control rather than
73
+ a blanket `button` rule. The admin is full of dense tables where growing every
74
+ button reflows the layout around it; the design bundle carries a curated list
75
+ for the same reason. The switch is the carve-out both hit: its thumb is
76
+ positioned against the track, so the **hit area** grows and the control paints
77
+ at its designed 34×19.
78
+ - **The editor stacks below 900px** — rail above canvas, both full width, drag
79
+ handle gone. The width override needs `!important`: the rail's width is an
80
+ inline style because it is drag-resizable and persisted.
81
+ - **Print** drops the chrome and lets the canvas print at natural size instead
82
+ of as a clipped, transformed thumbnail.
83
+
84
+ Two rules deliberately did not come across. The prototype turns the sidebar into
85
+ a fixed bottom bar under 768px, where `AdminShell` already has a working
86
+ slide-in overlay driven by `matchMedia` — replacing a working navigation pattern
87
+ was not part of finishing the page builder. And the blanket `min-height` list is
88
+ the per-control class described above.
89
+
90
+ Every way this breaks is invisible: a stylesheet that stops being imported, a
91
+ class hook renamed in a component, or a token override placed before the token
92
+ it overrides all render perfectly and simply lack the behaviour. Unit tests pin
93
+ the import order and assert every hook is applied by some component; e2e tests
94
+ measure the result in a browser, because "the CSS says 44px" and "the button is
95
+ 44px" are different claims. The second caught a real gap — the history button's
96
+ conditional className had been missed by the edit that added the class to its
97
+ four neighbours.
98
+
99
+ - 385dd10: Version history: a mode, not a popup
100
+
101
+ The page editor's history was a right-hand dialog with a flat list and a
102
+ Restore button. The handoff's stage 6 asks for something different in kind:
103
+ history is about comparing **renders**, so selecting a version puts it on the
104
+ canvas and marks what changed. A modal covers the thing it exists to let you
105
+ look at; a drawer resizes it. This overlays the rail instead, so the canvas
106
+ does not move a pixel and the only thing that differs between two versions is
107
+ the page itself. An e2e test measures exactly that.
108
+
109
+ **The diff is computed, not stored.** Field-level, from the full snapshots the
110
+ versions API already returns, and the same result drives three surfaces: the
111
+ per-field list in the panel, the dashed outlines on the canvas, and the review
112
+ bar's count. One computation, so they cannot disagree. Field names come from
113
+ the section registry — the same definitions the inspector renders from — so a
114
+ diff reads in the words the editor typed under, and a custom section type
115
+ falls back to its raw key rather than dropping the row.
116
+
117
+ Whether a field changed is decided **structurally**, and the display summary is
118
+ used only to render it. Comparing the summaries is the obvious shortcut and it
119
+ loses real edits: the summary collapses an array to "N items", so retyping a
120
+ stats row while keeping the row count formats identically on both sides and the
121
+ field reports no change — no panel row and no canvas outline, on exactly the
122
+ edit a reviewer opened history to find. Repeaters are descended into row by
123
+ row, labelled through the registry's own nouns ("Stats · Stat 2 · Value"), so a
124
+ collapsed summary never has to stand in for a change it cannot express.
125
+
126
+ Visibility is diffed alongside content: hiding a section is the one structural
127
+ change a design-owned CMS gives an editor, and a history that omitted it would
128
+ be missing the only structural edit there is.
129
+
130
+ **Review mode is its own mode, deliberately.** It and site-preview mode both
131
+ drop the cursor, the hover outline and the section label, which makes one
132
+ shared suppression rule very tempting — and that rule hides the changed-section
133
+ label review mode exists to show. They are separate flags, with a test that
134
+ holds them apart. Editing is frozen throughout: every control that writes reads
135
+ one flag, so no surface can mutate the current page while the canvas shows a
136
+ different one.
137
+
138
+ **Two things found by testing this against a real browser rather than a mock:**
139
+ - Restore was nested inside the diff block, so a version with no computed
140
+ changes — the oldest snapshot held, or a metadata-only save — was reviewable
141
+ and not restorable. That is backwards: the oldest version is the one a
142
+ rollback most often wants. The prototype nests it the same way.
143
+ - Selection and disclosure were separate state, so the review bar's "Back to
144
+ current" could leave the panel describing one version while the canvas
145
+ rendered another, with Restore stranded on a row nobody could see. They are
146
+ the same act and are now one piece of state.
147
+
148
+ **And one the review bots found.** The inline site preview is a second editing
149
+ surface — an iframe of the real site with click-to-edit wired into the same
150
+ section state — and its handlers checked the user's role and nothing else. The
151
+ review lock, which every control in the rail honours, stopped at the iframe
152
+ boundary; so did the read-only lock on Page-Builder-owned pages. Both now read
153
+ the same single gate. A lock that covers only the rail is not a lock.
154
+
3
155
  ## 0.93.0
4
156
 
5
157
  ### Minor Changes
@@ -215,4 +215,41 @@ describe('missingPageFields', () => {
215
215
  expect(missingPageFields(config)).toEqual(['sections']);
216
216
  });
217
217
  });
218
+ /**
219
+ * Removing the styling CONTROLS from the content editors must not remove the
220
+ * styling DATA. Background, spacing, anchor and CSS class are now
221
+ * template-authored, but every existing page carries values the renderers
222
+ * still read — and the save payload is built from `page.sections`, so a save
223
+ * that dropped `settings` would silently restyle every page it touched the
224
+ * first time anyone edited a heading.
225
+ */
226
+ describe('section settings survive a save', () => {
227
+ const styled = {
228
+ id: 's1',
229
+ sectionType: 'hero',
230
+ name: 'Hero Banner',
231
+ visible: true,
232
+ content: { heading: 'Hi' },
233
+ settings: {
234
+ backgroundType: 'solid',
235
+ backgroundColor: 'purple',
236
+ paddingY: 'xl',
237
+ anchorId: 'top',
238
+ cssClass: 'legacy-hero',
239
+ },
240
+ };
241
+ it('round-trips every settings key the editor no longer edits', async () => {
242
+ cmsApi.mockResolvedValue({ data: { id: 'p1', data: {} } });
243
+ await savePageDraft({ ...draft('p1'), sections: [styled] });
244
+ const body = JSON.parse(cmsApi.mock.calls[0][1].body);
245
+ expect(body.sections[0].settings).toEqual(styled.settings);
246
+ });
247
+ it('round-trips them through publish too', async () => {
248
+ cmsApi.mockResolvedValue({ data: { id: 'p1', data: {} } });
249
+ await publishPage({ ...draft('p1'), sections: [styled] });
250
+ const body = JSON.parse(cmsApi.mock.calls[0][1].body);
251
+ expect(body.sections[0].settings).toEqual(styled.settings);
252
+ expect(body.status).toBe('PUBLISHED');
253
+ });
254
+ });
218
255
  //# sourceMappingURL=page-editor-service-api.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"page-editor-service-api.test.js","sourceRoot":"","sources":["../../../src/__tests__/lib/page-editor-service-api.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"page-editor-service-api.test.js","sourceRoot":"","sources":["../../../src/__tests__/lib/page-editor-service-api.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=version-diff.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-diff.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/lib/version-diff.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,230 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { changedSectionIds, diffVersions, formatValue, groupChangesBySection, } from '../../lib/version-diff.js';
3
+ function section(overrides) {
4
+ return {
5
+ sectionType: 'hero',
6
+ name: 'Hero Banner',
7
+ visible: true,
8
+ content: {},
9
+ settings: {},
10
+ ...overrides,
11
+ };
12
+ }
13
+ describe('formatValue', () => {
14
+ it('renders absent and blank values as an em dash so an empty diff cell is never blank', () => {
15
+ expect(formatValue(null)).toBe('—');
16
+ expect(formatValue(undefined)).toBe('—');
17
+ expect(formatValue('')).toBe('—');
18
+ expect(formatValue(' ')).toBe('—');
19
+ expect(formatValue([])).toBe('—');
20
+ expect(formatValue({})).toBe('—');
21
+ });
22
+ it('summarises structured values rather than dumping them', () => {
23
+ expect(formatValue([{ value: '1' }, { value: '2' }])).toBe('2 items');
24
+ expect(formatValue([{ value: '1' }])).toBe('1 item');
25
+ expect(formatValue({ name: 'hero.jpg', url: '/m/hero.jpg' })).toBe('hero.jpg');
26
+ // No name-ish key: fall back to a shape description, not "[object Object]".
27
+ expect(formatValue({ x: 1, y: 2 })).toBe('2 fields');
28
+ });
29
+ it('reads booleans and numbers as words the panel can show', () => {
30
+ expect(formatValue(true)).toBe('Yes');
31
+ expect(formatValue(false)).toBe('No');
32
+ expect(formatValue(0)).toBe('0');
33
+ });
34
+ });
35
+ describe('diffVersions', () => {
36
+ it('labels content fields through the section registry, not by raw key', () => {
37
+ const before = [section({ id: 's1', content: { heading: 'Old headline' } })];
38
+ const after = [section({ id: 's1', content: { heading: 'New headline' } })];
39
+ const changes = diffVersions(after, before);
40
+ expect(changes).toEqual([
41
+ {
42
+ sectionId: 's1',
43
+ sectionName: 'Hero Banner',
44
+ // 'heading' is `label: 'Heading'` on the hero type in the registry.
45
+ field: 'Heading',
46
+ from: 'Old headline',
47
+ to: 'New headline',
48
+ },
49
+ ]);
50
+ });
51
+ it('falls back to the raw key for a type the registry does not describe', () => {
52
+ const before = [section({ id: 's1', sectionType: 'opal-pricing', content: { tiers: 'a' } })];
53
+ const after = [section({ id: 's1', sectionType: 'opal-pricing', content: { tiers: 'b' } })];
54
+ expect(diffVersions(after, before)[0]?.field).toBe('tiers');
55
+ });
56
+ it('reports a field cleared to nothing — the key exists only in the older snapshot', () => {
57
+ const before = [section({ id: 's1', content: { heading: 'Something' } })];
58
+ const after = [section({ id: 's1', content: {} })];
59
+ expect(diffVersions(after, before)).toEqual([
60
+ { sectionId: 's1', sectionName: 'Hero Banner', field: 'Heading', from: 'Something', to: '—' },
61
+ ]);
62
+ });
63
+ it('reports visibility as a state, because hiding a section is the one structural edit there is', () => {
64
+ const before = [section({ id: 's1', visible: true })];
65
+ const after = [section({ id: 's1', visible: false })];
66
+ expect(diffVersions(after, before)).toEqual([
67
+ {
68
+ sectionId: 's1',
69
+ sectionName: 'Hero Banner',
70
+ field: 'Visibility',
71
+ from: 'Shown',
72
+ to: 'Hidden',
73
+ },
74
+ ]);
75
+ });
76
+ it('reports added and removed sections', () => {
77
+ const before = [section({ id: 's1' })];
78
+ const after = [section({ id: 's1' }), section({ id: 's2', name: 'CTA', sectionType: 'cta' })];
79
+ expect(diffVersions(after, before)).toEqual([
80
+ { sectionId: 's2', sectionName: 'CTA', field: 'Section', from: '—', to: 'Added' },
81
+ ]);
82
+ expect(diffVersions(before, after)).toEqual([
83
+ { sectionId: 's2', sectionName: 'CTA', field: 'Section', from: 'Present', to: 'Removed' },
84
+ ]);
85
+ });
86
+ it('reports nothing when the snapshots match', () => {
87
+ const same = [section({ id: 's1', content: { heading: 'Same' } })];
88
+ expect(diffVersions(same, [section({ id: 's1', content: { heading: 'Same' } })])).toEqual([]);
89
+ });
90
+ it('reports nothing against a missing predecessor', () => {
91
+ // The oldest version we hold is not the moment the page was created, so
92
+ // reporting every field as "added" would state something false.
93
+ expect(diffVersions([section({ id: 's1', content: { heading: 'x' } })], undefined)).toEqual([]);
94
+ expect(diffVersions([section({ id: 's1' })], null)).toEqual([]);
95
+ });
96
+ it('does not report a settings key that was merely absent versus explicitly default', () => {
97
+ // `{}` and `{ backgroundType: undefined }` format identically, so neither
98
+ // produces a row. Without this the first save after a schema addition
99
+ // would light up every section on the canvas.
100
+ const before = [section({ id: 's1', settings: {} })];
101
+ const after = [section({ id: 's1', settings: { backgroundType: undefined } })];
102
+ expect(diffVersions(after, before)).toEqual([]);
103
+ });
104
+ it('labels known settings and reports a real background change', () => {
105
+ const before = [section({ id: 's1', settings: { backgroundType: 'none' } })];
106
+ const after = [section({ id: 's1', settings: { backgroundType: 'solid' } })];
107
+ expect(diffVersions(after, before)).toEqual([
108
+ {
109
+ sectionId: 's1',
110
+ sectionName: 'Hero Banner',
111
+ field: 'Background type',
112
+ from: 'none',
113
+ to: 'solid',
114
+ },
115
+ ]);
116
+ });
117
+ });
118
+ describe('diffVersions — structured fields', () => {
119
+ const stats = (rows) => section({ id: 's1', sectionType: 'stats', name: 'By The Numbers', content: { stats: rows } });
120
+ it('catches an edit that keeps the row count', () => {
121
+ // The bug this exists for: deciding "did it change" from the DISPLAY
122
+ // summary collapses an array to "2 items", so retyping a row while keeping
123
+ // the count formats identically on both sides and the field reports no
124
+ // change — no panel row AND no outline on the canvas, which is exactly the
125
+ // edit a reviewer opened history to find.
126
+ const before = [
127
+ stats([
128
+ { value: '10k', label: 'Users' },
129
+ { value: '99%', label: 'Uptime' },
130
+ ]),
131
+ ];
132
+ const after = [
133
+ stats([
134
+ { value: '20k', label: 'Users' },
135
+ { value: '99%', label: 'Uptime' },
136
+ ]),
137
+ ];
138
+ const changes = diffVersions(after, before);
139
+ expect(changes).toHaveLength(1);
140
+ expect(changes[0]?.from).toBe('10k');
141
+ expect(changes[0]?.to).toBe('20k');
142
+ // Named down to the row and the sub-field, so "which one" has an answer.
143
+ expect(changes[0]?.field).toBe('Stats · Stat 1 · Value');
144
+ expect(changedSectionIds(changes).has('s1')).toBe(true);
145
+ });
146
+ it('never emits a row whose before and after both read as a bare count', () => {
147
+ const before = [
148
+ stats([
149
+ { value: 'a', label: 'x' },
150
+ { value: 'b', label: 'y' },
151
+ ]),
152
+ ];
153
+ const after = [
154
+ stats([
155
+ { value: 'c', label: 'x' },
156
+ { value: 'd', label: 'y' },
157
+ ]),
158
+ ];
159
+ for (const change of diffVersions(after, before)) {
160
+ expect(change.from).not.toBe(change.to);
161
+ expect(change.from).not.toMatch(/^\d+ items?$/);
162
+ }
163
+ });
164
+ it('reports added and removed rows', () => {
165
+ const before = [stats([{ value: '10k', label: 'Users' }])];
166
+ const after = [
167
+ stats([
168
+ { value: '10k', label: 'Users' },
169
+ { value: '99%', label: 'Uptime' },
170
+ ]),
171
+ ];
172
+ expect(diffVersions(after, before)).toEqual([
173
+ expect.objectContaining({ field: 'Stats · Stat 2', from: '—', to: 'Added' }),
174
+ ]);
175
+ expect(diffVersions(before, after)).toEqual([
176
+ expect.objectContaining({ field: 'Stats · Stat 2', from: 'Present', to: 'Removed' }),
177
+ ]);
178
+ });
179
+ it('catches a nested change inside a media object', () => {
180
+ // Same failure one level down: two media objects with the same `name` used
181
+ // to format identically while pointing at different files.
182
+ const media = (url) => ({ name: 'hero.jpg', url });
183
+ const before = [section({ id: 's1', content: { imageUrl: media('/a.jpg') } })];
184
+ const after = [section({ id: 's1', content: { imageUrl: media('/b.jpg') } })];
185
+ expect(diffVersions(after, before)).toHaveLength(1);
186
+ });
187
+ it('treats every spelling of blank as unchanged', () => {
188
+ // Tightening the comparison must not start reporting "— → —".
189
+ for (const [before, after] of [
190
+ ['', null],
191
+ [null, undefined],
192
+ [undefined, ' '],
193
+ [[], undefined],
194
+ [{}, null],
195
+ ]) {
196
+ const changes = diffVersions([section({ id: 's1', content: { heading: after } })], [section({ id: 's1', content: { heading: before } })]);
197
+ expect(changes, `${JSON.stringify(before)} → ${JSON.stringify(after)}`).toEqual([]);
198
+ }
199
+ });
200
+ it('reports an unchanged repeater as no change at all', () => {
201
+ const rows = [{ value: '10k', label: 'Users' }];
202
+ expect(diffVersions([stats(rows)], [stats([...rows.map((r) => ({ ...r }))])])).toEqual([]);
203
+ });
204
+ });
205
+ describe('groupChangesBySection', () => {
206
+ it('groups by section in first-seen order', () => {
207
+ const before = [
208
+ section({ id: 's1', content: { heading: 'a', body: 'a' } }),
209
+ section({ id: 's2', name: 'CTA', sectionType: 'cta', content: { heading: 'a' } }),
210
+ ];
211
+ const after = [
212
+ section({ id: 's1', content: { heading: 'b', body: 'b' } }),
213
+ section({ id: 's2', name: 'CTA', sectionType: 'cta', content: { heading: 'b' } }),
214
+ ];
215
+ const groups = groupChangesBySection(diffVersions(after, before));
216
+ expect(groups.map((g) => g.sectionId)).toEqual(['s1', 's2']);
217
+ expect(groups[0]?.changes).toHaveLength(2);
218
+ expect(groups[1]?.changes).toHaveLength(1);
219
+ });
220
+ });
221
+ describe('changedSectionIds', () => {
222
+ it('collapses several changes on one section to a single outline', () => {
223
+ const before = [section({ id: 's1', content: { heading: 'a', body: 'a' } })];
224
+ const after = [section({ id: 's1', content: { heading: 'b', body: 'b' } })];
225
+ const ids = changedSectionIds(diffVersions(after, before));
226
+ expect(ids.size).toBe(1);
227
+ expect(ids.has('s1')).toBe(true);
228
+ });
229
+ });
230
+ //# sourceMappingURL=version-diff.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-diff.test.js","sourceRoot":"","sources":["../../../src/__tests__/lib/version-diff.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=version-history.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-history.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/lib/version-history.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,125 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { dayLabel, groupVersionsByDay, initials, toPageVersion, versionKind, } from '../../lib/version-history.js';
3
+ const NOW = new Date('2026-08-02T17:00:00Z');
4
+ function version(id, createdAt) {
5
+ return {
6
+ id,
7
+ changeType: 'UPDATE',
8
+ createdAt,
9
+ author: { id: 'u1', name: 'Sarah Mills' },
10
+ sections: [],
11
+ };
12
+ }
13
+ describe('toPageVersion', () => {
14
+ it('lifts the section snapshot out of the version payload', () => {
15
+ const mapped = toPageVersion({
16
+ id: 'v1',
17
+ changeType: 'PUBLISH',
18
+ createdAt: '2026-08-02T12:00:00Z',
19
+ data: {
20
+ sections: [
21
+ { id: 's1', sectionType: 'hero', name: 'Hero', visible: true, content: {}, settings: {} },
22
+ ],
23
+ },
24
+ changedBy: { id: 'u1', name: 'Sarah Mills', email: 's@example.com' },
25
+ });
26
+ expect(mapped.sections).toHaveLength(1);
27
+ expect(mapped.sections[0]?.id).toBe('s1');
28
+ expect(mapped.changeType).toBe('PUBLISH');
29
+ expect(mapped.author.name).toBe('Sarah Mills');
30
+ });
31
+ it('preserves an unmanaged section rather than dropping it from the snapshot', () => {
32
+ // Coercing a snapshot more strictly than the live document reads would
33
+ // make an externally-managed section look deleted in every version.
34
+ const mapped = toPageVersion({
35
+ id: 'v1',
36
+ changeType: 'UPDATE',
37
+ createdAt: '2026-08-02T12:00:00Z',
38
+ data: {
39
+ sections: [
40
+ { id: 's1', sectionType: 'opal-pricing', name: 'Pricing', visible: true, content: {} },
41
+ ],
42
+ },
43
+ });
44
+ expect(mapped.sections).toHaveLength(1);
45
+ expect(mapped.sections[0]?.sectionType).toBe('opal-pricing');
46
+ });
47
+ it('falls back through name → email → a real word for the avatar', () => {
48
+ expect(toPageVersion({ id: 'v', changeType: 'UPDATE', createdAt: '', data: null }).author.name).toBe('Unknown');
49
+ expect(toPageVersion({
50
+ id: 'v',
51
+ changeType: 'UPDATE',
52
+ createdAt: '',
53
+ data: null,
54
+ changedBy: { id: 'u', name: ' ', email: 'a@b.com' },
55
+ }).author.name).toBe('a@b.com');
56
+ });
57
+ it('yields no sections for a version whose payload has none', () => {
58
+ expect(toPageVersion({ id: 'v', changeType: 'DELETE', createdAt: '', data: {} }).sections).toEqual([]);
59
+ });
60
+ });
61
+ describe('versionKind', () => {
62
+ it('marks a published snapshot as the one a visitor could have seen', () => {
63
+ expect(versionKind('PUBLISH')).toEqual({ label: 'Published', tone: 'live' });
64
+ });
65
+ it('calls UPDATE "Saved", never "Draft"', () => {
66
+ // Every row written before cms-core started recording PUBLISH is an UPDATE
67
+ // whether or not it went live, so "Draft" would be false for those.
68
+ expect(versionKind('UPDATE').label).toBe('Saved');
69
+ });
70
+ it('distinguishes a rollback from authored content', () => {
71
+ expect(versionKind('RESTORE').label).toBe('Restored');
72
+ });
73
+ it('degrades to a neutral label for an unrecognised type', () => {
74
+ expect(versionKind('SOMETHING_NEW').label).toBe('Saved');
75
+ });
76
+ });
77
+ describe('dayLabel', () => {
78
+ it('names today and yesterday', () => {
79
+ expect(dayLabel('2026-08-02T09:00:00', NOW)).toBe('Today');
80
+ expect(dayLabel('2026-08-01T23:59:00', NOW)).toBe('Yesterday');
81
+ });
82
+ it('drops the year within the current one and keeps it outside', () => {
83
+ expect(dayLabel('2026-07-27T09:00:00', NOW)).not.toMatch(/2026/);
84
+ expect(dayLabel('2025-07-27T09:00:00', NOW)).toMatch(/2025/);
85
+ });
86
+ it('does not throw on an unparseable timestamp', () => {
87
+ expect(dayLabel('not-a-date', NOW)).toBe('Unknown date');
88
+ });
89
+ });
90
+ describe('groupVersionsByDay', () => {
91
+ it('groups consecutive runs and keeps newest-first order', () => {
92
+ const groups = groupVersionsByDay([
93
+ version('v5', '2026-08-02T16:12:00'),
94
+ version('v4', '2026-08-02T11:03:00'),
95
+ version('v3', '2026-08-01T17:47:00'),
96
+ version('v1', '2026-07-27T09:30:00'),
97
+ ], NOW);
98
+ expect(groups.map((g) => g.label)).toEqual(['Today', 'Yesterday', expect.stringMatching(/Jul/)]);
99
+ expect(groups[0]?.versions.map((v) => v.id)).toEqual(['v5', 'v4']);
100
+ });
101
+ it('does not merge two non-adjacent runs that share a label', () => {
102
+ // A Map keyed on the label would silently reorder an unsorted page into
103
+ // something that reads as chronological but is not.
104
+ const groups = groupVersionsByDay([
105
+ version('a', '2026-08-02T16:00:00'),
106
+ version('b', '2026-08-01T16:00:00'),
107
+ version('c', '2026-08-02T09:00:00'),
108
+ ], NOW);
109
+ expect(groups.map((g) => g.label)).toEqual(['Today', 'Yesterday', 'Today']);
110
+ });
111
+ it('returns nothing for an empty list', () => {
112
+ expect(groupVersionsByDay([], NOW)).toEqual([]);
113
+ });
114
+ });
115
+ describe('initials', () => {
116
+ it('takes first and last for a full name, two letters for one word', () => {
117
+ expect(initials('Sarah Mills')).toBe('SM');
118
+ expect(initials('Sarah Jane Mills')).toBe('SM');
119
+ expect(initials('sarah')).toBe('SA');
120
+ });
121
+ it('never renders an empty monogram', () => {
122
+ expect(initials(' ')).toBe('?');
123
+ });
124
+ });
125
+ //# sourceMappingURL=version-history.test.js.map