@semiont/react-ui 0.2.33-build.78 → 0.2.33-build.80

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 (219) hide show
  1. package/dist/EventBusContext-7GvDyO0d.d.mts +414 -0
  2. package/dist/{PdfAnnotationCanvas.client-ADC4FFSE.mjs → PdfAnnotationCanvas.client-RAJRPQLU.mjs} +42 -27
  3. package/dist/PdfAnnotationCanvas.client-RAJRPQLU.mjs.map +1 -0
  4. package/dist/{ar-RNNSPLQB.mjs → ar-4ZEORRW2.mjs} +8 -4
  5. package/dist/ar-4ZEORRW2.mjs.map +1 -0
  6. package/dist/{bn-S2CDL7EC.mjs → bn-SEDE5BQJ.mjs} +8 -4
  7. package/dist/bn-SEDE5BQJ.mjs.map +1 -0
  8. package/dist/{chunk-UDX2Q35T.mjs → chunk-D7NBW4RV.mjs} +8 -4
  9. package/dist/chunk-D7NBW4RV.mjs.map +1 -0
  10. package/dist/{chunk-35LLVRFK.mjs → chunk-ZR4ZV2LY.mjs} +206 -146
  11. package/dist/chunk-ZR4ZV2LY.mjs.map +1 -0
  12. package/dist/{cs-RSV675WU.mjs → cs-7W4WF5WD.mjs} +8 -4
  13. package/dist/cs-7W4WF5WD.mjs.map +1 -0
  14. package/dist/{da-CHXNPWJC.mjs → da-75XGBCBK.mjs} +8 -4
  15. package/dist/da-75XGBCBK.mjs.map +1 -0
  16. package/dist/{de-KPEZ53D4.mjs → de-ODJVFLHM.mjs} +8 -4
  17. package/dist/de-ODJVFLHM.mjs.map +1 -0
  18. package/dist/{el-MW2BME5T.mjs → el-C4PM4WB3.mjs} +8 -4
  19. package/dist/el-C4PM4WB3.mjs.map +1 -0
  20. package/dist/{en-EVMIX24Y.mjs → en-KJCJQ4OO.mjs} +2 -2
  21. package/dist/{es-HQ24NYS3.mjs → es-WD33R7QL.mjs} +8 -4
  22. package/dist/es-WD33R7QL.mjs.map +1 -0
  23. package/dist/{fa-W34LRLHG.mjs → fa-2BP6V56P.mjs} +8 -4
  24. package/dist/fa-2BP6V56P.mjs.map +1 -0
  25. package/dist/{fi-3U44IGOA.mjs → fi-USRRW24J.mjs} +8 -4
  26. package/dist/fi-USRRW24J.mjs.map +1 -0
  27. package/dist/{fr-N7DKX6NN.mjs → fr-EC5S6WVF.mjs} +8 -4
  28. package/dist/fr-EC5S6WVF.mjs.map +1 -0
  29. package/dist/{he-CS4WRXN3.mjs → he-7TBVIKAA.mjs} +8 -4
  30. package/dist/he-7TBVIKAA.mjs.map +1 -0
  31. package/dist/{hi-GJDY46KA.mjs → hi-FO4VIZLA.mjs} +8 -4
  32. package/dist/hi-FO4VIZLA.mjs.map +1 -0
  33. package/dist/{id-WAEZJK2Y.mjs → id-7U7GGVWY.mjs} +8 -4
  34. package/dist/id-7U7GGVWY.mjs.map +1 -0
  35. package/dist/index.css +123 -85
  36. package/dist/index.css.map +1 -1
  37. package/dist/index.d.mts +699 -529
  38. package/dist/index.mjs +4291 -3491
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/{it-VDNDMZPU.mjs → it-Y4OPL6I2.mjs} +8 -4
  41. package/dist/it-Y4OPL6I2.mjs.map +1 -0
  42. package/dist/{ja-5PEH56J5.mjs → ja-PK7SQL55.mjs} +8 -4
  43. package/dist/ja-PK7SQL55.mjs.map +1 -0
  44. package/dist/{ko-JYPL3WVA.mjs → ko-L25PXMYD.mjs} +8 -4
  45. package/dist/ko-L25PXMYD.mjs.map +1 -0
  46. package/dist/{ms-5PZVW76T.mjs → ms-STH777QM.mjs} +8 -4
  47. package/dist/ms-STH777QM.mjs.map +1 -0
  48. package/dist/{nl-YXES36KM.mjs → nl-Y7LECDDR.mjs} +8 -4
  49. package/dist/nl-Y7LECDDR.mjs.map +1 -0
  50. package/dist/{no-XRA2UCQD.mjs → no-KEKCEWU6.mjs} +8 -4
  51. package/dist/no-KEKCEWU6.mjs.map +1 -0
  52. package/dist/{pl-WH6LJA5G.mjs → pl-7A7OC75O.mjs} +8 -4
  53. package/dist/pl-7A7OC75O.mjs.map +1 -0
  54. package/dist/{pt-7GAG57BM.mjs → pt-35HTM7RA.mjs} +8 -4
  55. package/dist/pt-35HTM7RA.mjs.map +1 -0
  56. package/dist/{ro-BTDDRB7N.mjs → ro-VAWL5KQA.mjs} +8 -4
  57. package/dist/ro-VAWL5KQA.mjs.map +1 -0
  58. package/dist/{sv-7V5C2IT4.mjs → sv-7ZK5EQEB.mjs} +8 -4
  59. package/dist/sv-7ZK5EQEB.mjs.map +1 -0
  60. package/dist/test-utils.d.mts +18 -8
  61. package/dist/test-utils.mjs +36 -14
  62. package/dist/test-utils.mjs.map +1 -1
  63. package/dist/{th-LPKYLBX5.mjs → th-UDWZ4X34.mjs} +8 -4
  64. package/dist/th-UDWZ4X34.mjs.map +1 -0
  65. package/dist/{tr-DU4RQL4M.mjs → tr-4WMPK3UX.mjs} +8 -4
  66. package/dist/tr-4WMPK3UX.mjs.map +1 -0
  67. package/dist/{uk-36UHTDDI.mjs → uk-SSLASQYJ.mjs} +8 -4
  68. package/dist/uk-SSLASQYJ.mjs.map +1 -0
  69. package/dist/{vi-GDHOUZDH.mjs → vi-IF42Z5PU.mjs} +8 -4
  70. package/dist/vi-IF42Z5PU.mjs.map +1 -0
  71. package/dist/{zh-TYUID4XZ.mjs → zh-HRQTNTAI.mjs} +8 -4
  72. package/dist/zh-HRQTNTAI.mjs.map +1 -0
  73. package/package.json +8 -2
  74. package/src/components/CodeMirrorRenderer.tsx +66 -93
  75. package/src/components/DetectionProgressWidget.tsx +16 -5
  76. package/src/components/LiveRegion.tsx +18 -18
  77. package/src/components/ResizeHandle.tsx +10 -4
  78. package/src/components/SessionTimer.tsx +2 -2
  79. package/src/components/Toolbar.tsx +18 -9
  80. package/src/components/__tests__/SessionTimer.test.tsx +9 -9
  81. package/src/components/annotation/AnnotateToolbar.tsx +17 -15
  82. package/src/components/annotation/__tests__/AnnotateToolbar.test.tsx +165 -63
  83. package/src/components/annotation/annotation-entries.css +10 -0
  84. package/src/components/annotation-popups/JsonLdView.tsx +8 -2
  85. package/src/components/image-annotation/AnnotationOverlay.tsx +42 -22
  86. package/src/components/image-annotation/SvgDrawingCanvas.tsx +27 -30
  87. package/src/components/layout/__tests__/LeftSidebar.test.tsx +12 -33
  88. package/src/components/layout/__tests__/PageLayout.test.tsx +37 -32
  89. package/src/components/layout/__tests__/UnifiedHeader.test.tsx +21 -40
  90. package/src/components/modals/ResourceSearchModal.tsx +2 -2
  91. package/src/components/modals/SearchModal.tsx +1 -1
  92. package/src/components/navigation/CollapsibleResourceNavigation.tsx +14 -9
  93. package/src/components/navigation/NavigationTabs.css +36 -24
  94. package/src/components/navigation/ObservableLink.tsx +91 -0
  95. package/src/components/navigation/SimpleNavigation.tsx +20 -16
  96. package/src/components/navigation/SortableResourceTab.tsx +11 -5
  97. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +51 -26
  98. package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +28 -22
  99. package/src/components/resource/AnnotateView.tsx +64 -138
  100. package/src/components/resource/AnnotationHistory.tsx +12 -13
  101. package/src/components/resource/BrowseView.tsx +89 -177
  102. package/src/components/resource/HistoryEvent.tsx +16 -11
  103. package/src/components/resource/ResourceViewer.tsx +201 -370
  104. package/src/components/resource/__tests__/BrowseView.test.tsx +631 -0
  105. package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +231 -0
  106. package/src/components/resource/event-formatting.ts +316 -0
  107. package/src/components/resource/panels/AssessmentEntry.tsx +25 -33
  108. package/src/components/resource/panels/AssessmentPanel.tsx +137 -31
  109. package/src/components/resource/panels/CollaborationPanel.tsx +20 -13
  110. package/src/components/resource/panels/CommentEntry.tsx +38 -32
  111. package/src/components/resource/panels/CommentsPanel.tsx +153 -31
  112. package/src/components/resource/panels/DetectSection.css +36 -1
  113. package/src/components/resource/panels/DetectSection.tsx +38 -10
  114. package/src/components/resource/panels/HighlightEntry.tsx +25 -33
  115. package/src/components/resource/panels/HighlightPanel.tsx +100 -25
  116. package/src/components/resource/panels/ReferenceEntry.tsx +61 -75
  117. package/src/components/resource/panels/ReferencesPanel.tsx +166 -49
  118. package/src/components/resource/panels/ResourceInfoPanel.tsx +47 -48
  119. package/src/components/resource/panels/StatisticsPanel.tsx +9 -19
  120. package/src/components/resource/panels/TagEntry.tsx +25 -33
  121. package/src/components/resource/panels/TaggingPanel.tsx +141 -25
  122. package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +46 -101
  123. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +566 -0
  124. package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +86 -78
  125. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +146 -141
  126. package/src/components/resource/panels/__tests__/DetectSection.test.tsx +480 -0
  127. package/src/components/resource/panels/__tests__/HighlightPanel.detectionProgress.test.tsx +362 -0
  128. package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +228 -103
  129. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +117 -61
  130. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +586 -0
  131. package/src/components/settings/SettingsPanel.tsx +15 -12
  132. package/src/features/admin-devops/__tests__/AdminDevOpsPage.test.tsx +1 -46
  133. package/src/features/admin-devops/components/AdminDevOpsPage.tsx +0 -9
  134. package/src/features/admin-security/__tests__/AdminSecurityPage.test.tsx +0 -3
  135. package/src/features/admin-security/components/AdminSecurityPage.tsx +0 -9
  136. package/src/features/admin-users/__tests__/AdminUsersPage.test.tsx +0 -3
  137. package/src/features/admin-users/components/AdminUsersPage.tsx +0 -9
  138. package/src/features/moderate-entity-tags/__tests__/EntityTagsPage.test.tsx +0 -3
  139. package/src/features/moderate-entity-tags/components/EntityTagsPage.tsx +1 -9
  140. package/src/features/moderate-recent/__tests__/RecentDocumentsPage.test.tsx +0 -32
  141. package/src/features/moderate-recent/components/RecentDocumentsPage.tsx +1 -9
  142. package/src/features/moderate-tag-schemas/__tests__/TagSchemasPage.test.tsx +0 -32
  143. package/src/features/moderate-tag-schemas/components/TagSchemasPage.tsx +1 -9
  144. package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +51 -54
  145. package/src/features/resource-compose/components/ResourceComposePage.tsx +3 -13
  146. package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +39 -45
  147. package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +16 -27
  148. package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +231 -0
  149. package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +234 -0
  150. package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +388 -0
  151. package/src/features/resource-viewer/__tests__/DetectionProgressDismissal.test.tsx +318 -0
  152. package/src/features/resource-viewer/__tests__/GenerationFlowIntegration.test.tsx +504 -0
  153. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +145 -91
  154. package/src/features/resource-viewer/__tests__/detection-progress-flow.test.tsx +322 -0
  155. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +325 -476
  156. package/src/styles/motivations/motivation-assessment.css +28 -0
  157. package/src/styles/patterns/panel-helpers.css +26 -0
  158. package/translations/ar.json +7 -3
  159. package/translations/bn.json +7 -3
  160. package/translations/cs.json +7 -3
  161. package/translations/da.json +7 -3
  162. package/translations/de.json +7 -3
  163. package/translations/el.json +7 -3
  164. package/translations/en.json +7 -3
  165. package/translations/es.json +7 -3
  166. package/translations/fa.json +7 -3
  167. package/translations/fi.json +7 -3
  168. package/translations/fr.json +7 -3
  169. package/translations/he.json +7 -3
  170. package/translations/hi.json +7 -3
  171. package/translations/id.json +7 -3
  172. package/translations/it.json +7 -3
  173. package/translations/ja.json +7 -3
  174. package/translations/ko.json +7 -3
  175. package/translations/ms.json +7 -3
  176. package/translations/nl.json +7 -3
  177. package/translations/no.json +7 -3
  178. package/translations/pl.json +7 -3
  179. package/translations/pt.json +7 -3
  180. package/translations/ro.json +7 -3
  181. package/translations/sv.json +7 -3
  182. package/translations/th.json +7 -3
  183. package/translations/tr.json +7 -3
  184. package/translations/uk.json +7 -3
  185. package/translations/vi.json +7 -3
  186. package/translations/zh.json +7 -3
  187. package/dist/PdfAnnotationCanvas.client-ADC4FFSE.mjs.map +0 -1
  188. package/dist/TranslationManager-Co_5fSxl.d.mts +0 -118
  189. package/dist/ar-RNNSPLQB.mjs.map +0 -1
  190. package/dist/bn-S2CDL7EC.mjs.map +0 -1
  191. package/dist/chunk-35LLVRFK.mjs.map +0 -1
  192. package/dist/chunk-UDX2Q35T.mjs.map +0 -1
  193. package/dist/cs-RSV675WU.mjs.map +0 -1
  194. package/dist/da-CHXNPWJC.mjs.map +0 -1
  195. package/dist/de-KPEZ53D4.mjs.map +0 -1
  196. package/dist/el-MW2BME5T.mjs.map +0 -1
  197. package/dist/es-HQ24NYS3.mjs.map +0 -1
  198. package/dist/fa-W34LRLHG.mjs.map +0 -1
  199. package/dist/fi-3U44IGOA.mjs.map +0 -1
  200. package/dist/fr-N7DKX6NN.mjs.map +0 -1
  201. package/dist/he-CS4WRXN3.mjs.map +0 -1
  202. package/dist/hi-GJDY46KA.mjs.map +0 -1
  203. package/dist/id-WAEZJK2Y.mjs.map +0 -1
  204. package/dist/it-VDNDMZPU.mjs.map +0 -1
  205. package/dist/ja-5PEH56J5.mjs.map +0 -1
  206. package/dist/ko-JYPL3WVA.mjs.map +0 -1
  207. package/dist/ms-5PZVW76T.mjs.map +0 -1
  208. package/dist/nl-YXES36KM.mjs.map +0 -1
  209. package/dist/no-XRA2UCQD.mjs.map +0 -1
  210. package/dist/pl-WH6LJA5G.mjs.map +0 -1
  211. package/dist/pt-7GAG57BM.mjs.map +0 -1
  212. package/dist/ro-BTDDRB7N.mjs.map +0 -1
  213. package/dist/sv-7V5C2IT4.mjs.map +0 -1
  214. package/dist/th-LPKYLBX5.mjs.map +0 -1
  215. package/dist/tr-DU4RQL4M.mjs.map +0 -1
  216. package/dist/uk-36UHTDDI.mjs.map +0 -1
  217. package/dist/vi-GDHOUZDH.mjs.map +0 -1
  218. package/dist/zh-TYUID4XZ.mjs.map +0 -1
  219. /package/dist/{en-EVMIX24Y.mjs.map → en-KJCJQ4OO.mjs.map} +0 -0
@@ -0,0 +1,362 @@
1
+ /**
2
+ * Layer 2 Integration Test: HighlightPanel + DetectSection
3
+ *
4
+ * Tests the integration between HighlightPanel and DetectSection components.
5
+ * Verifies that detectionProgress prop is correctly passed down the component tree.
6
+ *
7
+ * This is a Layer 2 test because it:
8
+ * - Tests multiple real React components together (HighlightPanel + DetectSection)
9
+ * - Uses real EventBus for annotation:click events
10
+ * - Mocks API and external dependencies
11
+ * - Tests the data flow between parent and child components
12
+ */
13
+
14
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
15
+ import React from 'react';
16
+ import { screen } from '@testing-library/react';
17
+ import { renderWithProviders } from '../../../../test-utils';
18
+ import { HighlightPanel } from '../HighlightPanel';
19
+ import type { components } from '@semiont/api-client';
20
+ import { resetEventBusForTesting } from '../../../../contexts/EventBusContext';
21
+
22
+ type Annotation = components['schemas']['Annotation'];
23
+
24
+ // Mock translations - simulates useTranslations('HighlightPanel')
25
+ // The mock receives keys like 'title', 'noHighlights', etc. and returns translated strings
26
+ const mockT = vi.fn((key: string) => {
27
+ const translations: Record<string, string> = {
28
+ title: 'Highlights',
29
+ noHighlights: 'No highlights yet',
30
+ detectHighlights: 'Detect Highlights',
31
+ instructions: 'Instructions',
32
+ optional: '(optional)',
33
+ instructionsPlaceholder: 'Enter custom instructions...',
34
+ densityLabel: 'Density',
35
+ densitySparse: 'Sparse',
36
+ densityDense: 'Dense',
37
+ detect: 'Detect',
38
+ };
39
+ return translations[key] || key;
40
+ });
41
+
42
+ vi.mock('../../../../contexts/TranslationContext', () => ({
43
+ useTranslations: () => mockT,
44
+ TranslationProvider: ({ children }: { children: React.ReactNode }) => children,
45
+ }));
46
+
47
+ vi.mock('../../../../contexts/useEventSubscription', () => ({
48
+ useEventSubscriptions: vi.fn(),
49
+ }));
50
+
51
+ describe('HighlightPanel + DetectSection Integration', () => {
52
+ let mockAnnotations: Annotation[];
53
+
54
+ beforeEach(() => {
55
+ vi.clearAllMocks();
56
+ resetEventBusForTesting();
57
+
58
+ mockAnnotations = [
59
+ {
60
+ id: 'highlight-1',
61
+ motivation: 'highlighting',
62
+ body: [],
63
+ target: {
64
+ source: 'resource-1',
65
+ selector: {
66
+ type: 'TextPositionSelector',
67
+ start: 0,
68
+ end: 10,
69
+ },
70
+ },
71
+ created: '2024-01-01T00:00:00Z',
72
+ },
73
+ ];
74
+ });
75
+
76
+ describe('Detection Progress Prop Passing', () => {
77
+ it('should pass detectionProgress to DetectSection when provided', () => {
78
+ renderWithProviders(
79
+ <HighlightPanel
80
+ annotations={mockAnnotations}
81
+ pendingAnnotation={null}
82
+ isDetecting={true}
83
+ detectionProgress={{
84
+ status: 'analyzing',
85
+ percentage: 30,
86
+ message: 'Analyzing text for highlights...',
87
+ }}
88
+ annotateMode={true}
89
+ />
90
+ );
91
+
92
+ // Verify DetectSection received and rendered the progress
93
+ expect(screen.getByText('Analyzing text for highlights...')).toBeInTheDocument();
94
+ });
95
+
96
+ it('should pass null detectionProgress to DetectSection', () => {
97
+ renderWithProviders(
98
+ <HighlightPanel
99
+ annotations={mockAnnotations}
100
+ pendingAnnotation={null}
101
+ isDetecting={false}
102
+ detectionProgress={null}
103
+ annotateMode={true}
104
+ />
105
+ );
106
+
107
+ // Form should be visible (meaning detectionProgress was null)
108
+ expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
109
+ expect(screen.getByRole('button', { name: /✨ Detect/ })).toBeInTheDocument();
110
+ });
111
+
112
+ it('should pass undefined detectionProgress to DetectSection', () => {
113
+ renderWithProviders(
114
+ <HighlightPanel
115
+ annotations={mockAnnotations}
116
+ pendingAnnotation={null}
117
+ isDetecting={false}
118
+ detectionProgress={undefined}
119
+ annotateMode={true}
120
+ />
121
+ );
122
+
123
+ // Form should be visible (meaning detectionProgress was undefined)
124
+ expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
125
+ expect(screen.getByRole('button', { name: /✨ Detect/ })).toBeInTheDocument();
126
+ });
127
+
128
+ it('should keep progress visible after detection completes (isDetecting=false)', () => {
129
+ renderWithProviders(
130
+ <HighlightPanel
131
+ annotations={mockAnnotations}
132
+ pendingAnnotation={null}
133
+ isDetecting={false}
134
+ detectionProgress={{
135
+ status: 'complete',
136
+ percentage: 100,
137
+ message: 'Complete! Created 14 highlights',
138
+ }}
139
+ annotateMode={true}
140
+ />
141
+ );
142
+
143
+ // Progress should still be visible
144
+ expect(screen.getByText('Complete! Created 14 highlights')).toBeInTheDocument();
145
+ // Form should NOT be visible
146
+ expect(screen.queryByPlaceholderText('Enter custom instructions...')).not.toBeInTheDocument();
147
+ });
148
+
149
+ it('should pass progress with request parameters to DetectSection', () => {
150
+ renderWithProviders(
151
+ <HighlightPanel
152
+ annotations={mockAnnotations}
153
+ pendingAnnotation={null}
154
+ isDetecting={true}
155
+ detectionProgress={{
156
+ status: 'analyzing',
157
+ message: 'Analyzing...',
158
+ requestParams: [
159
+ { label: 'Instructions', value: 'Find important points' },
160
+ { label: 'Density', value: '5' },
161
+ ],
162
+ }}
163
+ annotateMode={true}
164
+ />
165
+ );
166
+
167
+ expect(screen.getByText('Request Parameters:')).toBeInTheDocument();
168
+ expect(screen.getByText('Find important points')).toBeInTheDocument();
169
+ expect(screen.getByText('5')).toBeInTheDocument();
170
+ });
171
+ });
172
+
173
+ describe('Annotate Mode Toggling', () => {
174
+ it('should render DetectSection when annotateMode is true', () => {
175
+ renderWithProviders(
176
+ <HighlightPanel
177
+ annotations={mockAnnotations}
178
+ pendingAnnotation={null}
179
+ isDetecting={false}
180
+ detectionProgress={null}
181
+ annotateMode={true}
182
+ />
183
+ );
184
+
185
+ expect(screen.getByText('Detect Highlights')).toBeInTheDocument();
186
+ });
187
+
188
+ it('should NOT render DetectSection when annotateMode is false', () => {
189
+ renderWithProviders(
190
+ <HighlightPanel
191
+ annotations={mockAnnotations}
192
+ pendingAnnotation={null}
193
+ isDetecting={false}
194
+ detectionProgress={null}
195
+ annotateMode={false}
196
+ />
197
+ );
198
+
199
+ expect(screen.queryByText('Detect Highlights')).not.toBeInTheDocument();
200
+ });
201
+
202
+ it('should hide progress when switching to browse mode (annotateMode=false)', () => {
203
+ const { rerender } = renderWithProviders(
204
+ <HighlightPanel
205
+ annotations={mockAnnotations}
206
+ pendingAnnotation={null}
207
+ isDetecting={true}
208
+ detectionProgress={{
209
+ status: 'analyzing',
210
+ message: 'Analyzing...',
211
+ }}
212
+ annotateMode={true}
213
+ />
214
+ );
215
+
216
+ expect(screen.getByText('Analyzing...')).toBeInTheDocument();
217
+
218
+ // Switch to browse mode
219
+ rerender(
220
+ <HighlightPanel
221
+ annotations={mockAnnotations}
222
+ pendingAnnotation={null}
223
+ isDetecting={true}
224
+ detectionProgress={{
225
+ status: 'analyzing',
226
+ message: 'Analyzing...',
227
+ }}
228
+ annotateMode={false}
229
+ />
230
+ );
231
+
232
+ // Progress should be hidden
233
+ expect(screen.queryByText('Analyzing...')).not.toBeInTheDocument();
234
+ });
235
+ });
236
+
237
+ describe('State Combinations', () => {
238
+ it('should handle isDetecting=true with no progress (starting state)', () => {
239
+ renderWithProviders(
240
+ <HighlightPanel
241
+ annotations={mockAnnotations}
242
+ pendingAnnotation={null}
243
+ isDetecting={true}
244
+ detectionProgress={null}
245
+ annotateMode={true}
246
+ />
247
+ );
248
+
249
+ // Form should still be visible (waiting for first progress chunk)
250
+ expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
251
+ });
252
+
253
+ it('should handle isDetecting=false with progress (final state)', () => {
254
+ renderWithProviders(
255
+ <HighlightPanel
256
+ annotations={mockAnnotations}
257
+ pendingAnnotation={null}
258
+ isDetecting={false}
259
+ detectionProgress={{
260
+ status: 'complete',
261
+ message: 'Done!',
262
+ }}
263
+ annotateMode={true}
264
+ />
265
+ );
266
+
267
+ // Progress should be visible
268
+ expect(screen.getByText('Done!')).toBeInTheDocument();
269
+ // Form should be hidden
270
+ expect(screen.queryByPlaceholderText('Enter custom instructions...')).not.toBeInTheDocument();
271
+ });
272
+
273
+ it('should handle multiple progress updates', () => {
274
+ const { rerender } = renderWithProviders(
275
+ <HighlightPanel
276
+ annotations={mockAnnotations}
277
+ pendingAnnotation={null}
278
+ isDetecting={true}
279
+ detectionProgress={{
280
+ status: 'started',
281
+ percentage: 0,
282
+ message: 'Starting...',
283
+ }}
284
+ annotateMode={true}
285
+ />
286
+ );
287
+
288
+ expect(screen.getByText('Starting...')).toBeInTheDocument();
289
+
290
+ // Update to analyzing
291
+ rerender(
292
+ <HighlightPanel
293
+ annotations={mockAnnotations}
294
+ pendingAnnotation={null}
295
+ isDetecting={true}
296
+ detectionProgress={{
297
+ status: 'analyzing',
298
+ percentage: 50,
299
+ message: 'Analyzing...',
300
+ }}
301
+ annotateMode={true}
302
+ />
303
+ );
304
+
305
+ expect(screen.queryByText('Starting...')).not.toBeInTheDocument();
306
+ expect(screen.getByText('Analyzing...')).toBeInTheDocument();
307
+
308
+ // Update to complete
309
+ rerender(
310
+ <HighlightPanel
311
+ annotations={mockAnnotations}
312
+ pendingAnnotation={null}
313
+ isDetecting={false}
314
+ detectionProgress={{
315
+ status: 'complete',
316
+ percentage: 100,
317
+ message: 'Complete!',
318
+ }}
319
+ annotateMode={true}
320
+ />
321
+ );
322
+
323
+ expect(screen.queryByText('Analyzing...')).not.toBeInTheDocument();
324
+ expect(screen.getByText('Complete!')).toBeInTheDocument();
325
+ });
326
+ });
327
+
328
+ describe('Highlights List Rendering', () => {
329
+ it('should render highlights list alongside detection progress', () => {
330
+ renderWithProviders(
331
+ <HighlightPanel
332
+ annotations={mockAnnotations}
333
+ pendingAnnotation={null}
334
+ isDetecting={true}
335
+ detectionProgress={{
336
+ status: 'analyzing',
337
+ message: 'Analyzing...',
338
+ }}
339
+ annotateMode={true}
340
+ />
341
+ );
342
+
343
+ // Both progress and highlights should be visible
344
+ expect(screen.getByText('Analyzing...')).toBeInTheDocument();
345
+ expect(screen.getByText('Highlights')).toBeInTheDocument();
346
+ });
347
+
348
+ it('should show empty state when no highlights', () => {
349
+ renderWithProviders(
350
+ <HighlightPanel
351
+ annotations={[]}
352
+ pendingAnnotation={null}
353
+ isDetecting={false}
354
+ detectionProgress={null}
355
+ annotateMode={true}
356
+ />
357
+ );
358
+
359
+ expect(screen.getByText('No highlights yet')).toBeInTheDocument();
360
+ });
361
+ });
362
+ });