@semiont/react-ui 0.2.34-build.91 → 0.2.34-build.92
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.
- package/dist/{EventBusContext-BmzEcGHZ.d.mts → EventBusContext-DMI4uwYk.d.mts} +2 -2
- package/dist/{PdfAnnotationCanvas.client-VLNA5O5M.mjs → PdfAnnotationCanvas.client-HNYRKFDS.mjs} +10 -9
- package/dist/PdfAnnotationCanvas.client-HNYRKFDS.mjs.map +1 -0
- package/dist/{ar-4ZEORRW2.mjs → ar-MDB7HC5S.mjs} +45 -49
- package/dist/ar-MDB7HC5S.mjs.map +1 -0
- package/dist/{bn-SEDE5BQJ.mjs → bn-3SAV2ZEM.mjs} +45 -49
- package/dist/bn-3SAV2ZEM.mjs.map +1 -0
- package/dist/{chunk-C63BARI7.mjs → chunk-3FIQXKQF.mjs} +31 -31
- package/dist/{chunk-D7NBW4RV.mjs → chunk-JH7BXE2P.mjs} +45 -49
- package/dist/chunk-JH7BXE2P.mjs.map +1 -0
- package/dist/{chunk-M7SZRRIE.mjs → chunk-MWQ5CNKW.mjs} +13 -13
- package/dist/chunk-MWQ5CNKW.mjs.map +1 -0
- package/dist/{chunk-ULIET3MW.mjs → chunk-YI5IX5ZA.mjs} +1 -1
- package/dist/{chunk-ULIET3MW.mjs.map → chunk-YI5IX5ZA.mjs.map} +1 -1
- package/dist/{cs-7W4WF5WD.mjs → cs-AWCETEUV.mjs} +45 -49
- package/dist/cs-AWCETEUV.mjs.map +1 -0
- package/dist/{da-75XGBCBK.mjs → da-UZZHXYLC.mjs} +45 -49
- package/dist/da-UZZHXYLC.mjs.map +1 -0
- package/dist/{de-ODJVFLHM.mjs → de-LQFWN6S5.mjs} +45 -49
- package/dist/de-LQFWN6S5.mjs.map +1 -0
- package/dist/{el-C4PM4WB3.mjs → el-IWOETBJ7.mjs} +45 -49
- package/dist/el-IWOETBJ7.mjs.map +1 -0
- package/dist/{en-KJCJQ4OO.mjs → en-XWEPVTB4.mjs} +2 -6
- package/dist/{es-WD33R7QL.mjs → es-726NTS53.mjs} +45 -49
- package/dist/es-726NTS53.mjs.map +1 -0
- package/dist/{fa-2BP6V56P.mjs → fa-BVEJZT5S.mjs} +45 -49
- package/dist/fa-BVEJZT5S.mjs.map +1 -0
- package/dist/{fi-USRRW24J.mjs → fi-JBNCGGA6.mjs} +45 -49
- package/dist/fi-JBNCGGA6.mjs.map +1 -0
- package/dist/{fr-EC5S6WVF.mjs → fr-OLH7PNGI.mjs} +45 -49
- package/dist/fr-OLH7PNGI.mjs.map +1 -0
- package/dist/{he-7TBVIKAA.mjs → he-KOJQ4HMA.mjs} +45 -49
- package/dist/he-KOJQ4HMA.mjs.map +1 -0
- package/dist/{hi-FO4VIZLA.mjs → hi-BKJFZXAY.mjs} +45 -49
- package/dist/hi-BKJFZXAY.mjs.map +1 -0
- package/dist/{id-7U7GGVWY.mjs → id-DPLHJVNP.mjs} +45 -49
- package/dist/id-DPLHJVNP.mjs.map +1 -0
- package/dist/index.css +80 -80
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +215 -201
- package/dist/index.mjs +810 -748
- package/dist/index.mjs.map +1 -1
- package/dist/{it-Y4OPL6I2.mjs → it-JXHAM7NL.mjs} +45 -49
- package/dist/it-JXHAM7NL.mjs.map +1 -0
- package/dist/{ja-PK7SQL55.mjs → ja-DQRAO3PU.mjs} +45 -49
- package/dist/ja-DQRAO3PU.mjs.map +1 -0
- package/dist/{ko-L25PXMYD.mjs → ko-6IFCOP6F.mjs} +45 -49
- package/dist/ko-6IFCOP6F.mjs.map +1 -0
- package/dist/{ms-STH777QM.mjs → ms-KF5S2TLL.mjs} +45 -49
- package/dist/ms-KF5S2TLL.mjs.map +1 -0
- package/dist/{nl-Y7LECDDR.mjs → nl-2GUUZLQM.mjs} +45 -49
- package/dist/nl-2GUUZLQM.mjs.map +1 -0
- package/dist/{no-KEKCEWU6.mjs → no-2IBCZGEF.mjs} +45 -49
- package/dist/no-2IBCZGEF.mjs.map +1 -0
- package/dist/{pl-7A7OC75O.mjs → pl-ZEUBJ7YU.mjs} +45 -49
- package/dist/pl-ZEUBJ7YU.mjs.map +1 -0
- package/dist/{pt-35HTM7RA.mjs → pt-WLAFIZWQ.mjs} +45 -49
- package/dist/pt-WLAFIZWQ.mjs.map +1 -0
- package/dist/{ro-VAWL5KQA.mjs → ro-K56IXFGU.mjs} +45 -49
- package/dist/ro-K56IXFGU.mjs.map +1 -0
- package/dist/{sv-7ZK5EQEB.mjs → sv-VFJLMJRY.mjs} +45 -49
- package/dist/sv-VFJLMJRY.mjs.map +1 -0
- package/dist/test-utils.d.mts +2 -2
- package/dist/test-utils.mjs +3 -3
- package/dist/{th-UDWZ4X34.mjs → th-RICLQ2GW.mjs} +45 -49
- package/dist/th-RICLQ2GW.mjs.map +1 -0
- package/dist/{tr-4WMPK3UX.mjs → tr-SALXWE2M.mjs} +45 -49
- package/dist/tr-SALXWE2M.mjs.map +1 -0
- package/dist/{uk-SSLASQYJ.mjs → uk-3U3T3O2E.mjs} +45 -49
- package/dist/uk-3U3T3O2E.mjs.map +1 -0
- package/dist/{vi-IF42Z5PU.mjs → vi-LIVNZXOB.mjs} +45 -49
- package/dist/vi-LIVNZXOB.mjs.map +1 -0
- package/dist/{zh-HRQTNTAI.mjs → zh-KDUAZPX3.mjs} +45 -49
- package/dist/zh-KDUAZPX3.mjs.map +1 -0
- package/package.json +1 -1
- package/src/components/AnnotateReferencesProgressWidget.tsx +113 -0
- package/src/components/CodeMirrorRenderer.tsx +9 -27
- package/src/components/Toolbar.tsx +2 -2
- package/src/components/annotation/AnnotateToolbar.tsx +9 -9
- package/src/components/annotation/__tests__/AnnotateToolbar.test.tsx +17 -17
- package/src/components/image-annotation/AnnotationOverlay.tsx +13 -11
- package/src/components/image-annotation/SvgDrawingCanvas.tsx +8 -4
- package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +11 -9
- package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +1 -1
- package/src/components/resource/AnnotateView.tsx +17 -12
- package/src/components/resource/BrowseView.tsx +19 -50
- package/src/components/resource/ResourceViewer.tsx +28 -24
- package/src/components/resource/__tests__/BrowseView.test.tsx +27 -27
- package/src/components/resource/panels/AssessmentEntry.tsx +1 -1
- package/src/components/resource/panels/AssessmentPanel.tsx +16 -16
- package/src/components/resource/panels/{DetectSection.css → AssistSection.css} +79 -79
- package/src/components/resource/panels/{DetectSection.tsx → AssistSection.tsx} +46 -46
- package/src/components/resource/panels/CommentEntry.tsx +1 -1
- package/src/components/resource/panels/CommentsPanel.tsx +16 -16
- package/src/components/resource/panels/HighlightEntry.tsx +1 -1
- package/src/components/resource/panels/HighlightPanel.tsx +14 -14
- package/src/components/resource/panels/ReferenceEntry.tsx +5 -5
- package/src/components/resource/panels/ReferencesPanel.tsx +90 -103
- package/src/components/resource/panels/ResourceInfoPanel.tsx +2 -2
- package/src/components/resource/panels/TagEntry.tsx +1 -1
- package/src/components/resource/panels/TaggingPanel.tsx +53 -53
- package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +12 -20
- package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +12 -12
- package/src/components/resource/panels/__tests__/{DetectSection.test.tsx → AssistSection.test.tsx} +109 -108
- package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +8 -8
- package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +3 -3
- package/src/components/resource/panels/__tests__/{HighlightPanel.detectionProgress.test.tsx → HighlightPanel.annotationProgress.test.tsx} +56 -56
- package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +98 -95
- package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +3 -3
- package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +16 -16
- package/src/components/settings/SettingsPanel.tsx +29 -1
- package/src/features/resource-compose/components/ResourceComposePage.tsx +3 -0
- package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +36 -26
- package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +26 -16
- package/src/features/resource-viewer/__tests__/{DetectionProgressDismissal.test.tsx → AnnotationProgressDismissal.test.tsx} +48 -38
- package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +59 -49
- package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +55 -33
- package/src/features/resource-viewer/__tests__/GenerationFlowIntegration.test.tsx +24 -16
- package/src/features/resource-viewer/__tests__/ResolutionFlowIntegration.test.tsx +41 -31
- package/src/features/resource-viewer/__tests__/ResourceMutations.test.tsx +10 -10
- package/src/features/resource-viewer/__tests__/ToastNotifications.test.tsx +196 -0
- package/src/features/resource-viewer/__tests__/{detection-progress-flow.test.tsx → annotation-progress-flow.test.tsx} +51 -28
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +56 -45
- package/src/styles/core/buttons.css +3 -3
- package/src/styles/core/forms.css +2 -2
- package/src/styles/index.css +1 -1
- package/src/styles/motivations/motivation-assessment.css +9 -9
- package/src/styles/motivations/motivation-comment.css +9 -9
- package/src/styles/motivations/motivation-highlight.css +9 -9
- package/src/styles/motivations/motivation-reference.css +9 -9
- package/src/styles/motivations/motivation-tag.css +9 -9
- package/src/styles/utilities/focus-extended.css +6 -6
- package/translations/ar.json +44 -44
- package/translations/bn.json +44 -44
- package/translations/cs.json +44 -44
- package/translations/da.json +44 -44
- package/translations/de.json +44 -44
- package/translations/el.json +44 -44
- package/translations/en.json +44 -44
- package/translations/es.json +44 -44
- package/translations/fa.json +44 -44
- package/translations/fi.json +44 -44
- package/translations/fr.json +44 -44
- package/translations/he.json +44 -44
- package/translations/hi.json +44 -44
- package/translations/id.json +44 -44
- package/translations/it.json +44 -44
- package/translations/ja.json +44 -44
- package/translations/ko.json +44 -44
- package/translations/ms.json +44 -44
- package/translations/nl.json +44 -44
- package/translations/no.json +44 -44
- package/translations/pl.json +44 -44
- package/translations/pt.json +44 -44
- package/translations/ro.json +44 -44
- package/translations/sv.json +44 -44
- package/translations/th.json +44 -44
- package/translations/tr.json +44 -44
- package/translations/uk.json +44 -44
- package/translations/vi.json +44 -44
- package/translations/zh.json +44 -44
- package/dist/PdfAnnotationCanvas.client-VLNA5O5M.mjs.map +0 -1
- package/dist/ar-4ZEORRW2.mjs.map +0 -1
- package/dist/bn-SEDE5BQJ.mjs.map +0 -1
- package/dist/chunk-D7NBW4RV.mjs.map +0 -1
- package/dist/chunk-M7SZRRIE.mjs.map +0 -1
- package/dist/cs-7W4WF5WD.mjs.map +0 -1
- package/dist/da-75XGBCBK.mjs.map +0 -1
- package/dist/de-ODJVFLHM.mjs.map +0 -1
- package/dist/el-C4PM4WB3.mjs.map +0 -1
- package/dist/es-WD33R7QL.mjs.map +0 -1
- package/dist/fa-2BP6V56P.mjs.map +0 -1
- package/dist/fi-USRRW24J.mjs.map +0 -1
- package/dist/fr-EC5S6WVF.mjs.map +0 -1
- package/dist/he-7TBVIKAA.mjs.map +0 -1
- package/dist/hi-FO4VIZLA.mjs.map +0 -1
- package/dist/id-7U7GGVWY.mjs.map +0 -1
- package/dist/it-Y4OPL6I2.mjs.map +0 -1
- package/dist/ja-PK7SQL55.mjs.map +0 -1
- package/dist/ko-L25PXMYD.mjs.map +0 -1
- package/dist/ms-STH777QM.mjs.map +0 -1
- package/dist/nl-Y7LECDDR.mjs.map +0 -1
- package/dist/no-KEKCEWU6.mjs.map +0 -1
- package/dist/pl-7A7OC75O.mjs.map +0 -1
- package/dist/pt-35HTM7RA.mjs.map +0 -1
- package/dist/ro-VAWL5KQA.mjs.map +0 -1
- package/dist/sv-7ZK5EQEB.mjs.map +0 -1
- package/dist/th-UDWZ4X34.mjs.map +0 -1
- package/dist/tr-4WMPK3UX.mjs.map +0 -1
- package/dist/uk-SSLASQYJ.mjs.map +0 -1
- package/dist/vi-IF42Z5PU.mjs.map +0 -1
- package/dist/zh-HRQTNTAI.mjs.map +0 -1
- package/src/components/DetectionProgressWidget.tsx +0 -113
- /package/dist/{chunk-C63BARI7.mjs.map → chunk-3FIQXKQF.mjs.map} +0 -0
- /package/dist/{en-KJCJQ4OO.mjs.map → en-XWEPVTB4.mjs.map} +0 -0
|
@@ -2,58 +2,68 @@
|
|
|
2
2
|
* FAILING TEST: Reproduces the bug where detection events fire but state doesn't update
|
|
3
3
|
*
|
|
4
4
|
* Based on console logs from production:
|
|
5
|
-
* ✅
|
|
6
|
-
* ✅
|
|
7
|
-
* ❌
|
|
8
|
-
* ❌
|
|
5
|
+
* ✅ annotate:assist-request emitted
|
|
6
|
+
* ✅ annotate:assist-progress emitted
|
|
7
|
+
* ❌ assistingMotivation remains null
|
|
8
|
+
* ❌ progress remains null
|
|
9
9
|
*
|
|
10
|
-
* UPDATED: Now tests
|
|
10
|
+
* UPDATED: Now tests useAnnotationFlow hook instead of DetectionFlowContainer
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
14
14
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
15
15
|
import { act } from 'react';
|
|
16
|
-
import {
|
|
16
|
+
import { useAnnotationFlow } from '../../../hooks/useAnnotationFlow';
|
|
17
17
|
import { EventBusProvider, useEventBus, resetEventBusForTesting } from '../../../contexts/EventBusContext';
|
|
18
18
|
import { ApiClientProvider } from '../../../contexts/ApiClientContext';
|
|
19
19
|
import { AuthTokenProvider } from '../../../contexts/AuthTokenContext';
|
|
20
20
|
import { SSEClient } from '@semiont/api-client';
|
|
21
21
|
|
|
22
|
+
// Mock Toast module to prevent "useToast must be used within a ToastProvider" errors
|
|
23
|
+
vi.mock('../../../components/Toast', () => ({
|
|
24
|
+
useToast: () => ({
|
|
25
|
+
showSuccess: vi.fn(),
|
|
26
|
+
showError: vi.fn(),
|
|
27
|
+
showInfo: vi.fn(),
|
|
28
|
+
showWarning: vi.fn(),
|
|
29
|
+
}),
|
|
30
|
+
}));
|
|
31
|
+
|
|
22
32
|
describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
23
33
|
beforeEach(() => {
|
|
24
34
|
resetEventBusForTesting();
|
|
25
35
|
vi.clearAllMocks();
|
|
26
36
|
|
|
27
37
|
// Minimal mock - SSE streams not needed for this test
|
|
28
|
-
vi.spyOn(SSEClient.prototype, '
|
|
29
|
-
vi.spyOn(SSEClient.prototype, '
|
|
30
|
-
vi.spyOn(SSEClient.prototype, '
|
|
31
|
-
vi.spyOn(SSEClient.prototype, '
|
|
38
|
+
vi.spyOn(SSEClient.prototype, 'annotateReferences').mockReturnValue({ onProgress: vi.fn().mockReturnThis(), onComplete: vi.fn().mockReturnThis(), onError: vi.fn().mockReturnThis(), close: vi.fn() } as any);
|
|
39
|
+
vi.spyOn(SSEClient.prototype, 'annotateHighlights').mockReturnValue({ onProgress: vi.fn().mockReturnThis(), onComplete: vi.fn().mockReturnThis(), onError: vi.fn().mockReturnThis(), close: vi.fn() } as any);
|
|
40
|
+
vi.spyOn(SSEClient.prototype, 'annotateComments').mockReturnValue({ onProgress: vi.fn().mockReturnThis(), onComplete: vi.fn().mockReturnThis(), onError: vi.fn().mockReturnThis(), close: vi.fn() } as any);
|
|
41
|
+
vi.spyOn(SSEClient.prototype, 'annotateAssessments').mockReturnValue({ onProgress: vi.fn().mockReturnThis(), onComplete: vi.fn().mockReturnThis(), onError: vi.fn().mockReturnThis(), close: vi.fn() } as any);
|
|
32
42
|
});
|
|
33
43
|
|
|
34
44
|
afterEach(() => {
|
|
35
45
|
vi.restoreAllMocks();
|
|
36
46
|
});
|
|
37
47
|
|
|
38
|
-
it('SHOULD update state when
|
|
48
|
+
it('SHOULD update state when annotate:assist-request event is emitted', async () => {
|
|
39
49
|
let eventBusInstance: any;
|
|
40
50
|
let currentState: any;
|
|
41
51
|
|
|
42
52
|
// Component to capture EventBus and hook state
|
|
43
53
|
function TestComponent() {
|
|
44
54
|
eventBusInstance = useEventBus();
|
|
45
|
-
const state =
|
|
55
|
+
const state = useAnnotationFlow('http://localhost:8080/resources/test' as any);
|
|
46
56
|
currentState = state;
|
|
47
57
|
|
|
48
|
-
console.log('[TEST]
|
|
49
|
-
|
|
50
|
-
|
|
58
|
+
console.log('[TEST] useAnnotationFlow state:', {
|
|
59
|
+
assistingMotivation: state.assistingMotivation,
|
|
60
|
+
progress: state.progress,
|
|
51
61
|
});
|
|
52
62
|
|
|
53
63
|
return (
|
|
54
64
|
<div>
|
|
55
|
-
<div data-testid="detecting">{state.
|
|
56
|
-
<div data-testid="progress">{state.
|
|
65
|
+
<div data-testid="detecting">{state.assistingMotivation || 'null'}</div>
|
|
66
|
+
<div data-testid="progress">{state.progress?.message || 'null'}</div>
|
|
57
67
|
</div>
|
|
58
68
|
);
|
|
59
69
|
}
|
|
@@ -72,40 +82,40 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
72
82
|
expect(screen.getByTestId('detecting')).toHaveTextContent('null');
|
|
73
83
|
expect(screen.getByTestId('progress')).toHaveTextContent('null');
|
|
74
84
|
|
|
75
|
-
console.log('[TEST] Emitting
|
|
85
|
+
console.log('[TEST] Emitting annotate:assist-request event...');
|
|
76
86
|
|
|
77
|
-
// Emit
|
|
87
|
+
// Emit annotate:assist-request event (exactly like production)
|
|
78
88
|
act(() => {
|
|
79
|
-
eventBusInstance.get('
|
|
89
|
+
eventBusInstance.get('annotate:assist-request').next({
|
|
80
90
|
motivation: 'linking',
|
|
81
91
|
options: { entityTypes: ['Location'] }
|
|
82
92
|
});
|
|
83
93
|
});
|
|
84
94
|
|
|
85
|
-
console.log('[TEST] After
|
|
95
|
+
console.log('[TEST] After annotate:assist-request, checking state...');
|
|
86
96
|
|
|
87
97
|
// THIS SHOULD PASS but currently FAILS
|
|
88
98
|
await waitFor(() => {
|
|
89
99
|
expect(screen.getByTestId('detecting')).toHaveTextContent('linking');
|
|
90
100
|
}, { timeout: 1000 });
|
|
91
101
|
|
|
92
|
-
expect(currentState.
|
|
93
|
-
expect(currentState.
|
|
102
|
+
expect(currentState.assistingMotivation).toBe('linking');
|
|
103
|
+
expect(currentState.progress).toBeNull(); // Should clear on start
|
|
94
104
|
});
|
|
95
105
|
|
|
96
|
-
it('SHOULD update state when
|
|
106
|
+
it('SHOULD update state when annotate:assist-progress event is emitted', async () => {
|
|
97
107
|
let eventBusInstance: any;
|
|
98
108
|
let currentState: any;
|
|
99
109
|
|
|
100
110
|
function TestComponent() {
|
|
101
111
|
eventBusInstance = useEventBus();
|
|
102
|
-
const state =
|
|
112
|
+
const state = useAnnotationFlow('http://localhost:8080/resources/test' as any);
|
|
103
113
|
currentState = state;
|
|
104
114
|
|
|
105
115
|
return (
|
|
106
116
|
<div>
|
|
107
|
-
<div data-testid="detecting">{state.
|
|
108
|
-
<div data-testid="progress">{state.
|
|
117
|
+
<div data-testid="detecting">{state.assistingMotivation || 'null'}</div>
|
|
118
|
+
<div data-testid="progress">{state.progress?.message || 'null'}</div>
|
|
109
119
|
</div>
|
|
110
120
|
);
|
|
111
121
|
}
|
|
@@ -120,11 +130,11 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
120
130
|
</EventBusProvider>
|
|
121
131
|
);
|
|
122
132
|
|
|
123
|
-
console.log('[TEST] Emitting
|
|
133
|
+
console.log('[TEST] Emitting annotate:assist-progress event...');
|
|
124
134
|
|
|
125
|
-
// Emit
|
|
135
|
+
// Emit annotate:assist-progress event (exactly like production)
|
|
126
136
|
act(() => {
|
|
127
|
-
eventBusInstance.get('
|
|
137
|
+
eventBusInstance.get('annotate:progress').next({
|
|
128
138
|
status: 'started',
|
|
129
139
|
resourceId: 'test',
|
|
130
140
|
totalEntityTypes: 1,
|
|
@@ -133,14 +143,14 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
133
143
|
});
|
|
134
144
|
});
|
|
135
145
|
|
|
136
|
-
console.log('[TEST] After
|
|
146
|
+
console.log('[TEST] After annotate:assist-progress, checking state...');
|
|
137
147
|
|
|
138
148
|
// THIS SHOULD PASS but currently FAILS
|
|
139
149
|
await waitFor(() => {
|
|
140
150
|
expect(screen.getByTestId('progress')).toHaveTextContent('Starting entity detection...');
|
|
141
151
|
}, { timeout: 1000 });
|
|
142
152
|
|
|
143
|
-
expect(currentState.
|
|
153
|
+
expect(currentState.progress).toMatchObject({
|
|
144
154
|
status: 'started',
|
|
145
155
|
message: 'Starting entity detection...'
|
|
146
156
|
});
|
|
@@ -152,17 +162,17 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
152
162
|
|
|
153
163
|
function TestComponent() {
|
|
154
164
|
eventBusInstance = useEventBus();
|
|
155
|
-
const state =
|
|
165
|
+
const state = useAnnotationFlow('http://localhost:8080/resources/f45fd44f9cb0b0fe1b7980d3d034bc61' as any);
|
|
156
166
|
|
|
157
167
|
stateSnapshots.push({
|
|
158
|
-
|
|
159
|
-
|
|
168
|
+
assistingMotivation: state.assistingMotivation,
|
|
169
|
+
progress: state.progress,
|
|
160
170
|
});
|
|
161
171
|
|
|
162
172
|
return (
|
|
163
173
|
<div>
|
|
164
|
-
<div data-testid="detecting">{state.
|
|
165
|
-
<div data-testid="progress">{state.
|
|
174
|
+
<div data-testid="detecting">{state.assistingMotivation || 'null'}</div>
|
|
175
|
+
<div data-testid="progress">{state.progress?.message || 'null'}</div>
|
|
166
176
|
</div>
|
|
167
177
|
);
|
|
168
178
|
}
|
|
@@ -182,18 +192,18 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
182
192
|
|
|
183
193
|
// Exactly like production logs
|
|
184
194
|
act(() => {
|
|
185
|
-
console.log('[EventBus] emit:
|
|
186
|
-
eventBusInstance.get('
|
|
195
|
+
console.log('[EventBus] emit: annotate:assist-request {motivation: "linking", options: {...}}');
|
|
196
|
+
eventBusInstance.get('annotate:assist-request').next({
|
|
187
197
|
motivation: 'linking',
|
|
188
198
|
options: { entityTypes: ['Location'] }
|
|
189
199
|
});
|
|
190
200
|
});
|
|
191
201
|
|
|
192
|
-
console.log('After
|
|
202
|
+
console.log('After annotate:assist-request:', stateSnapshots[stateSnapshots.length - 1]);
|
|
193
203
|
|
|
194
204
|
act(() => {
|
|
195
|
-
console.log('[EventBus] emit:
|
|
196
|
-
eventBusInstance.get('
|
|
205
|
+
console.log('[EventBus] emit: annotate:assist-progress {status: "started", ...}');
|
|
206
|
+
eventBusInstance.get('annotate:progress').next({
|
|
197
207
|
status: 'started',
|
|
198
208
|
resourceId: 'f45fd44f9cb0b0fe1b7980d3d034bc61',
|
|
199
209
|
totalEntityTypes: 1,
|
|
@@ -202,11 +212,11 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
202
212
|
});
|
|
203
213
|
});
|
|
204
214
|
|
|
205
|
-
console.log('After
|
|
215
|
+
console.log('After annotate:assist-progress:', stateSnapshots[stateSnapshots.length - 1]);
|
|
206
216
|
|
|
207
217
|
act(() => {
|
|
208
|
-
console.log('[EventBus] emit:
|
|
209
|
-
eventBusInstance.get('
|
|
218
|
+
console.log('[EventBus] emit: annotate:assist-progress {status: "scanning", ...}');
|
|
219
|
+
eventBusInstance.get('annotate:progress').next({
|
|
210
220
|
status: 'scanning',
|
|
211
221
|
resourceId: 'f45fd44f9cb0b0fe1b7980d3d034bc61',
|
|
212
222
|
currentEntityType: 'Location',
|
|
@@ -216,19 +226,19 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
216
226
|
});
|
|
217
227
|
});
|
|
218
228
|
|
|
219
|
-
console.log('After second
|
|
229
|
+
console.log('After second annotate:assist-progress:', stateSnapshots[stateSnapshots.length - 1]);
|
|
220
230
|
console.log('=== END REPRODUCTION ===\n');
|
|
221
231
|
|
|
222
232
|
// THIS IS THE BUG: Events fire but state never updates
|
|
223
|
-
// Production logs show:
|
|
233
|
+
// Production logs show: assistingMotivation: null, progress: null
|
|
224
234
|
// Even though events were emitted
|
|
225
235
|
await waitFor(() => {
|
|
226
236
|
const currentSnapshot = stateSnapshots[stateSnapshots.length - 1];
|
|
227
237
|
console.log('Final state check:', currentSnapshot);
|
|
228
238
|
|
|
229
239
|
// These SHOULD pass but will FAIL if bug is present
|
|
230
|
-
expect(currentSnapshot.
|
|
231
|
-
expect(currentSnapshot.
|
|
240
|
+
expect(currentSnapshot.assistingMotivation).toBe('linking');
|
|
241
|
+
expect(currentSnapshot.progress?.message).toBe('Scanning for Location...');
|
|
232
242
|
}, { timeout: 2000 });
|
|
233
243
|
});
|
|
234
244
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Tests the COMPLETE detection flow with real component composition:
|
|
5
5
|
* - EventBusProvider (REAL)
|
|
6
6
|
* - ApiClientProvider (REAL, with MOCKED client)
|
|
7
|
-
* -
|
|
7
|
+
* - useAnnotationFlow (REAL)
|
|
8
8
|
* - useResolutionFlow (REAL)
|
|
9
9
|
* - useEventSubscriptions (REAL)
|
|
10
10
|
*
|
|
@@ -25,7 +25,7 @@ import React from 'react';
|
|
|
25
25
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
26
26
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
27
27
|
import { act } from 'react';
|
|
28
|
-
import {
|
|
28
|
+
import { useAnnotationFlow } from '../../../hooks/useAnnotationFlow';
|
|
29
29
|
import { EventBusProvider, useEventBus, resetEventBusForTesting } from '../../../contexts/EventBusContext';
|
|
30
30
|
import { ApiClientProvider } from '../../../contexts/ApiClientContext';
|
|
31
31
|
import { AuthTokenProvider } from '../../../contexts/AuthTokenContext';
|
|
@@ -33,6 +33,16 @@ import { SSEClient } from '@semiont/api-client';
|
|
|
33
33
|
import type { Motivation } from '@semiont/core';
|
|
34
34
|
import { resourceUri } from '@semiont/core';
|
|
35
35
|
import type { Emitter } from 'mitt';
|
|
36
|
+
|
|
37
|
+
// Mock Toast module to prevent "useToast must be used within a ToastProvider" errors
|
|
38
|
+
vi.mock('../../../components/Toast', () => ({
|
|
39
|
+
useToast: () => ({
|
|
40
|
+
showSuccess: vi.fn(),
|
|
41
|
+
showError: vi.fn(),
|
|
42
|
+
showInfo: vi.fn(),
|
|
43
|
+
showWarning: vi.fn(),
|
|
44
|
+
}),
|
|
45
|
+
}));
|
|
36
46
|
import type { EventMap } from '@semiont/core';
|
|
37
47
|
|
|
38
48
|
// Mock SSE stream - SSE now emits directly to EventBus, no callbacks
|
|
@@ -44,8 +54,8 @@ const createMockSSEStream = () => {
|
|
|
44
54
|
|
|
45
55
|
describe('Detection Flow - Feature Integration', () => {
|
|
46
56
|
let mockStream: ReturnType<typeof createMockSSEStream>;
|
|
47
|
-
let
|
|
48
|
-
let
|
|
57
|
+
let annotateReferencesSpy: any;
|
|
58
|
+
let annotateHighlightsSpy: any;
|
|
49
59
|
let detectCommentsSpy: any;
|
|
50
60
|
|
|
51
61
|
beforeEach(() => {
|
|
@@ -56,23 +66,23 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
56
66
|
mockStream = createMockSSEStream();
|
|
57
67
|
|
|
58
68
|
// Spy on SSEClient prototype methods
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
detectCommentsSpy = vi.spyOn(SSEClient.prototype, '
|
|
62
|
-
vi.spyOn(SSEClient.prototype, '
|
|
69
|
+
annotateReferencesSpy = vi.spyOn(SSEClient.prototype, 'annotateReferences').mockReturnValue(mockStream as any);
|
|
70
|
+
annotateHighlightsSpy = vi.spyOn(SSEClient.prototype, 'annotateHighlights').mockReturnValue(mockStream as any);
|
|
71
|
+
detectCommentsSpy = vi.spyOn(SSEClient.prototype, 'annotateComments').mockReturnValue(mockStream as any);
|
|
72
|
+
vi.spyOn(SSEClient.prototype, 'annotateAssessments').mockReturnValue(mockStream as any);
|
|
63
73
|
});
|
|
64
74
|
|
|
65
75
|
afterEach(() => {
|
|
66
76
|
vi.restoreAllMocks();
|
|
67
77
|
});
|
|
68
78
|
|
|
69
|
-
it('should call
|
|
79
|
+
it('should call annotateReferences exactly ONCE when detection starts (not twice)', async () => {
|
|
70
80
|
const testUri = resourceUri('http://localhost:4000/resources/test-resource');
|
|
71
81
|
|
|
72
82
|
// Render with real component composition
|
|
73
83
|
const { emitDetectionStart } = renderDetectionFlow(testUri);
|
|
74
84
|
|
|
75
|
-
// Trigger detection for linking (uses
|
|
85
|
+
// Trigger detection for linking (uses annotateReferences)
|
|
76
86
|
act(() => {
|
|
77
87
|
emitDetectionStart('linking', {
|
|
78
88
|
entityTypes: ['Person', 'Organization'],
|
|
@@ -83,11 +93,11 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
83
93
|
// CRITICAL ASSERTION: API called exactly once (not twice!)
|
|
84
94
|
// This would FAIL if useResolutionFlow was called in multiple places
|
|
85
95
|
await waitFor(() => {
|
|
86
|
-
expect(
|
|
96
|
+
expect(annotateReferencesSpy).toHaveBeenCalledTimes(1);
|
|
87
97
|
});
|
|
88
98
|
|
|
89
99
|
// Verify correct parameters (eventBus is passed but we don't need to verify its exact value)
|
|
90
|
-
expect(
|
|
100
|
+
expect(annotateReferencesSpy).toHaveBeenCalledWith(
|
|
91
101
|
testUri,
|
|
92
102
|
{
|
|
93
103
|
entityTypes: ['Person', 'Organization'],
|
|
@@ -97,7 +107,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
97
107
|
);
|
|
98
108
|
});
|
|
99
109
|
|
|
100
|
-
it('should propagate SSE progress events to
|
|
110
|
+
it('should propagate SSE progress events to useAnnotationFlow state', async () => {
|
|
101
111
|
const testUri = resourceUri('http://localhost:4000/resources/test-resource');
|
|
102
112
|
|
|
103
113
|
// Render with state observer
|
|
@@ -112,12 +122,12 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
112
122
|
|
|
113
123
|
// Wait for stream to be created
|
|
114
124
|
await waitFor(() => {
|
|
115
|
-
expect(
|
|
125
|
+
expect(annotateReferencesSpy).toHaveBeenCalled();
|
|
116
126
|
});
|
|
117
127
|
|
|
118
128
|
// Simulate SSE progress event being emitted to EventBus (how SSE actually works now)
|
|
119
129
|
act(() => {
|
|
120
|
-
getEventBus().get('
|
|
130
|
+
getEventBus().get('annotate:progress').next({
|
|
121
131
|
status: 'scanning',
|
|
122
132
|
message: 'Scanning for Person...',
|
|
123
133
|
currentEntityType: 'Person',
|
|
@@ -146,12 +156,12 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
146
156
|
});
|
|
147
157
|
|
|
148
158
|
await waitFor(() => {
|
|
149
|
-
expect(
|
|
159
|
+
expect(annotateHighlightsSpy).toHaveBeenCalledTimes(1);
|
|
150
160
|
});
|
|
151
161
|
|
|
152
162
|
// First progress update via EventBus
|
|
153
163
|
act(() => {
|
|
154
|
-
getEventBus().get('
|
|
164
|
+
getEventBus().get('annotate:progress').next({
|
|
155
165
|
status: 'started',
|
|
156
166
|
message: 'Starting analysis...',
|
|
157
167
|
percentage: 0,
|
|
@@ -164,7 +174,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
164
174
|
|
|
165
175
|
// Second progress update via EventBus
|
|
166
176
|
act(() => {
|
|
167
|
-
getEventBus().get('
|
|
177
|
+
getEventBus().get('annotate:progress').next({
|
|
168
178
|
status: 'analyzing',
|
|
169
179
|
message: 'Analyzing text...',
|
|
170
180
|
percentage: 50,
|
|
@@ -177,7 +187,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
177
187
|
|
|
178
188
|
// Final progress update via EventBus
|
|
179
189
|
act(() => {
|
|
180
|
-
getEventBus().get('
|
|
190
|
+
getEventBus().get('annotate:progress').next({
|
|
181
191
|
status: 'complete',
|
|
182
192
|
message: 'Created 14 highlights',
|
|
183
193
|
percentage: 100,
|
|
@@ -204,7 +214,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
204
214
|
|
|
205
215
|
// Send final progress via EventBus
|
|
206
216
|
act(() => {
|
|
207
|
-
getEventBus().get('
|
|
217
|
+
getEventBus().get('annotate:progress').next({
|
|
208
218
|
status: 'complete',
|
|
209
219
|
message: 'Created 14 highlights',
|
|
210
220
|
});
|
|
@@ -216,7 +226,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
216
226
|
|
|
217
227
|
// Emit completion event
|
|
218
228
|
act(() => {
|
|
219
|
-
getEventBus().get('
|
|
229
|
+
getEventBus().get('annotate:assist-finished').next({ motivation: 'highlighting' });
|
|
220
230
|
});
|
|
221
231
|
|
|
222
232
|
// Verify: detecting flag cleared BUT progress still visible
|
|
@@ -237,7 +247,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
237
247
|
|
|
238
248
|
// Add some progress via EventBus
|
|
239
249
|
act(() => {
|
|
240
|
-
getEventBus().get('
|
|
250
|
+
getEventBus().get('annotate:progress').next({
|
|
241
251
|
status: 'scanning',
|
|
242
252
|
message: 'Scanning...',
|
|
243
253
|
});
|
|
@@ -249,7 +259,19 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
249
259
|
|
|
250
260
|
// Emit failure
|
|
251
261
|
act(() => {
|
|
252
|
-
getEventBus().get('
|
|
262
|
+
getEventBus().get('annotate:assist-failed').next({
|
|
263
|
+
type: 'job.failed' as const,
|
|
264
|
+
resourceId: 'test-resource' as any,
|
|
265
|
+
userId: 'user' as any,
|
|
266
|
+
id: 'evt-1' as any,
|
|
267
|
+
timestamp: new Date().toISOString(),
|
|
268
|
+
version: 1,
|
|
269
|
+
payload: {
|
|
270
|
+
jobId: 'job-1' as any,
|
|
271
|
+
jobType: 'detection',
|
|
272
|
+
error: 'Network error',
|
|
273
|
+
},
|
|
274
|
+
});
|
|
253
275
|
});
|
|
254
276
|
|
|
255
277
|
// Verify: both detecting and progress cleared
|
|
@@ -269,8 +291,8 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
269
291
|
});
|
|
270
292
|
|
|
271
293
|
await waitFor(() => {
|
|
272
|
-
expect(
|
|
273
|
-
expect(
|
|
294
|
+
expect(annotateHighlightsSpy).toHaveBeenCalledTimes(1);
|
|
295
|
+
expect(annotateHighlightsSpy).toHaveBeenCalledWith(testUri, {
|
|
274
296
|
instructions: 'Find important text',
|
|
275
297
|
}, expect.objectContaining({ auth: undefined }));
|
|
276
298
|
});
|
|
@@ -306,7 +328,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
306
328
|
|
|
307
329
|
// Add an additional event listener (simulating multiple subscribers)
|
|
308
330
|
const additionalListener = vi.fn();
|
|
309
|
-
const subscription = getEventBus().get('
|
|
331
|
+
const subscription = getEventBus().get('annotate:assist-request').subscribe(additionalListener);
|
|
310
332
|
|
|
311
333
|
// Trigger detection
|
|
312
334
|
act(() => {
|
|
@@ -315,11 +337,11 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
315
337
|
|
|
316
338
|
// Wait for operation to complete
|
|
317
339
|
await waitFor(() => {
|
|
318
|
-
expect(
|
|
340
|
+
expect(annotateReferencesSpy).toHaveBeenCalled();
|
|
319
341
|
});
|
|
320
342
|
|
|
321
343
|
// VERIFY: API called exactly once, even though multiple listeners exist
|
|
322
|
-
expect(
|
|
344
|
+
expect(annotateReferencesSpy).toHaveBeenCalledTimes(1);
|
|
323
345
|
|
|
324
346
|
// VERIFY: Our additional listener was called (events work)
|
|
325
347
|
expect(additionalListener).toHaveBeenCalledTimes(1);
|
|
@@ -329,7 +351,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
329
351
|
});
|
|
330
352
|
|
|
331
353
|
/**
|
|
332
|
-
* Helper: Render
|
|
354
|
+
* Helper: Render useAnnotationFlow hook with real component composition
|
|
333
355
|
* Returns methods to interact with the rendered component
|
|
334
356
|
*/
|
|
335
357
|
function renderDetectionFlow(testUri: string) {
|
|
@@ -343,12 +365,12 @@ function renderDetectionFlow(testUri: string) {
|
|
|
343
365
|
|
|
344
366
|
// Test harness component that uses the hook
|
|
345
367
|
function DetectionFlowTestHarness() {
|
|
346
|
-
const {
|
|
368
|
+
const { progress, assistingMotivation } = useAnnotationFlow(testUri as any);
|
|
347
369
|
return (
|
|
348
370
|
<div>
|
|
349
|
-
<div data-testid="detecting">{
|
|
371
|
+
<div data-testid="detecting">{assistingMotivation || 'none'}</div>
|
|
350
372
|
<div data-testid="progress">
|
|
351
|
-
{
|
|
373
|
+
{progress?.message || 'No progress'}
|
|
352
374
|
</div>
|
|
353
375
|
</div>
|
|
354
376
|
);
|
|
@@ -367,7 +389,7 @@ function renderDetectionFlow(testUri: string) {
|
|
|
367
389
|
|
|
368
390
|
return {
|
|
369
391
|
emitDetectionStart: (motivation: Motivation, options: any) => {
|
|
370
|
-
eventBusInstance.get('
|
|
392
|
+
eventBusInstance.get('annotate:assist-request').next({ motivation, options });
|
|
371
393
|
},
|
|
372
394
|
getEventBus: () => eventBusInstance,
|
|
373
395
|
};
|
|
@@ -32,6 +32,16 @@ import { resourceUri, annotationUri } from '@semiont/core';
|
|
|
32
32
|
import type { Emitter } from 'mitt';
|
|
33
33
|
import type { EventMap } from '@semiont/core';
|
|
34
34
|
|
|
35
|
+
// Mock Toast module to prevent "useToast must be used within a ToastProvider" errors
|
|
36
|
+
vi.mock('../../../components/Toast', () => ({
|
|
37
|
+
useToast: () => ({
|
|
38
|
+
showSuccess: vi.fn(),
|
|
39
|
+
showError: vi.fn(),
|
|
40
|
+
showInfo: vi.fn(),
|
|
41
|
+
showWarning: vi.fn(),
|
|
42
|
+
}),
|
|
43
|
+
}));
|
|
44
|
+
|
|
35
45
|
// Mock SSE stream - SSE now emits directly to EventBus, no callbacks
|
|
36
46
|
const createMockGenerationStream = () => {
|
|
37
47
|
return {
|
|
@@ -66,7 +76,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
66
76
|
vi.restoreAllMocks();
|
|
67
77
|
});
|
|
68
78
|
|
|
69
|
-
it('should open modal when
|
|
79
|
+
it('should open modal when generate:modal-open event is emitted', async () => {
|
|
70
80
|
const testResourceUri = resourceUri('http://localhost:4000/resources/test-resource');
|
|
71
81
|
const testAnnotationUri = annotationUri('http://localhost:4000/resources/test-resource/annotations/test-annotation');
|
|
72
82
|
|
|
@@ -157,7 +167,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
157
167
|
|
|
158
168
|
// Simulate SSE progress callback being invoked
|
|
159
169
|
act(() => {
|
|
160
|
-
getEventBus().get('
|
|
170
|
+
getEventBus().get('generate:progress').next({
|
|
161
171
|
status: 'generating',
|
|
162
172
|
message: 'Generating content...',
|
|
163
173
|
percentage: 25,
|
|
@@ -193,7 +203,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
193
203
|
|
|
194
204
|
// First progress update
|
|
195
205
|
act(() => {
|
|
196
|
-
getEventBus().get('
|
|
206
|
+
getEventBus().get('generate:progress').next({
|
|
197
207
|
status: 'started',
|
|
198
208
|
message: 'Starting generation...',
|
|
199
209
|
percentage: 0,
|
|
@@ -206,7 +216,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
206
216
|
|
|
207
217
|
// Second progress update
|
|
208
218
|
act(() => {
|
|
209
|
-
getEventBus().get('
|
|
219
|
+
getEventBus().get('generate:progress').next({
|
|
210
220
|
status: 'generating',
|
|
211
221
|
message: 'Creating document structure...',
|
|
212
222
|
percentage: 50,
|
|
@@ -219,7 +229,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
219
229
|
|
|
220
230
|
// Final progress update via onComplete
|
|
221
231
|
act(() => {
|
|
222
|
-
getEventBus().get('
|
|
232
|
+
getEventBus().get('generate:finished').next({
|
|
223
233
|
status: 'complete',
|
|
224
234
|
referenceId: testAnnotationUri,
|
|
225
235
|
message: 'Document created successfully',
|
|
@@ -256,7 +266,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
256
266
|
|
|
257
267
|
// Simulate completion with final chunk
|
|
258
268
|
act(() => {
|
|
259
|
-
getEventBus().get('
|
|
269
|
+
getEventBus().get('generate:progress').next({
|
|
260
270
|
status: 'complete',
|
|
261
271
|
message: 'Complete',
|
|
262
272
|
resourceName: 'Generated Document',
|
|
@@ -265,7 +275,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
265
275
|
|
|
266
276
|
// Emit completion event
|
|
267
277
|
act(() => {
|
|
268
|
-
getEventBus().get('
|
|
278
|
+
getEventBus().get('generate:finished').next({
|
|
269
279
|
status: 'complete',
|
|
270
280
|
referenceId: testAnnotationUri,
|
|
271
281
|
resourceName: 'Generated Document',
|
|
@@ -295,7 +305,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
295
305
|
|
|
296
306
|
// Add some progress
|
|
297
307
|
act(() => {
|
|
298
|
-
getEventBus().get('
|
|
308
|
+
getEventBus().get('generate:progress').next({
|
|
299
309
|
status: 'generating',
|
|
300
310
|
message: 'Generating...',
|
|
301
311
|
});
|
|
@@ -307,7 +317,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
307
317
|
|
|
308
318
|
// Emit failure
|
|
309
319
|
act(() => {
|
|
310
|
-
getEventBus().get('
|
|
320
|
+
getEventBus().get('generate:failed').next({ error: new Error('Network error') });
|
|
311
321
|
});
|
|
312
322
|
|
|
313
323
|
// Verify: progress cleared and not generating
|
|
@@ -327,7 +337,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
327
337
|
|
|
328
338
|
// Add an additional event listener (simulating multiple subscribers)
|
|
329
339
|
const additionalListener = vi.fn();
|
|
330
|
-
const subscription = getEventBus().get('
|
|
340
|
+
const subscription = getEventBus().get('generate:request').subscribe(additionalListener);
|
|
331
341
|
|
|
332
342
|
// Trigger generation
|
|
333
343
|
act(() => {
|
|
@@ -373,7 +383,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
373
383
|
|
|
374
384
|
// Simulate onComplete with final chunk
|
|
375
385
|
act(() => {
|
|
376
|
-
getEventBus().get('
|
|
386
|
+
getEventBus().get('generate:finished').next({
|
|
377
387
|
status: 'complete',
|
|
378
388
|
referenceId: testAnnotationUri,
|
|
379
389
|
message: 'Document created: My Document',
|
|
@@ -403,7 +413,7 @@ function renderGenerationFlow(
|
|
|
403
413
|
function EventBusCapture() {
|
|
404
414
|
eventBusInstance = useEventBus();
|
|
405
415
|
|
|
406
|
-
// Set up resolution flow (
|
|
416
|
+
// Set up resolution flow (resolve:update-body, resolve:link)
|
|
407
417
|
useResolutionFlow(testResourceUri);
|
|
408
418
|
|
|
409
419
|
return null;
|
|
@@ -419,8 +429,6 @@ function renderGenerationFlow(
|
|
|
419
429
|
} = useGenerationFlow(
|
|
420
430
|
'en',
|
|
421
431
|
testResourceUri.split('/resources/')[1] || 'test-resource',
|
|
422
|
-
vi.fn(),
|
|
423
|
-
vi.fn(),
|
|
424
432
|
vi.fn()
|
|
425
433
|
);
|
|
426
434
|
|
|
@@ -456,7 +464,7 @@ function renderGenerationFlow(
|
|
|
456
464
|
resourceUri: ResourceUri,
|
|
457
465
|
defaultTitle: string
|
|
458
466
|
) => {
|
|
459
|
-
eventBusInstance.get('
|
|
467
|
+
eventBusInstance.get('generate:modal-open').next({
|
|
460
468
|
annotationUri,
|
|
461
469
|
resourceUri,
|
|
462
470
|
defaultTitle,
|
|
@@ -474,7 +482,7 @@ function renderGenerationFlow(
|
|
|
474
482
|
context: any;
|
|
475
483
|
}
|
|
476
484
|
) => {
|
|
477
|
-
eventBusInstance.get('
|
|
485
|
+
eventBusInstance.get('generate:request').next({
|
|
478
486
|
annotationUri,
|
|
479
487
|
resourceUri,
|
|
480
488
|
options,
|