@semiont/react-ui 0.2.35-build.98 → 0.2.35
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/README.md +1 -0
- package/dist/{EventBusContext-DMI4uwYk.d.mts → EventBusContext-CLnb2LmB.d.mts} +5 -5
- package/dist/{PdfAnnotationCanvas.client-HNYRKFDS.mjs → PdfAnnotationCanvas.client-COQREPXU.mjs} +7 -7
- package/dist/PdfAnnotationCanvas.client-COQREPXU.mjs.map +1 -0
- package/dist/ar-7SUXNE34.mjs +376 -0
- package/dist/ar-7SUXNE34.mjs.map +1 -0
- package/dist/bn-XOET3DOI.mjs +376 -0
- package/dist/bn-XOET3DOI.mjs.map +1 -0
- package/dist/{chunk-YI5IX5ZA.mjs → chunk-2HGWOLVN.mjs} +1 -1
- package/dist/{chunk-YI5IX5ZA.mjs.map → chunk-2HGWOLVN.mjs.map} +1 -1
- package/dist/{chunk-3FIQXKQF.mjs → chunk-Q2KV6Y2J.mjs} +28 -28
- package/dist/{chunk-MWQ5CNKW.mjs → chunk-ZPV43WN2.mjs} +11 -11
- package/dist/chunk-ZPV43WN2.mjs.map +1 -0
- package/dist/cs-X63DXX7L.mjs +376 -0
- package/dist/cs-X63DXX7L.mjs.map +1 -0
- package/dist/da-OWTCV57A.mjs +376 -0
- package/dist/da-OWTCV57A.mjs.map +1 -0
- package/dist/de-77BMFDVF.mjs +376 -0
- package/dist/de-77BMFDVF.mjs.map +1 -0
- package/dist/el-FIBNLH2V.mjs +376 -0
- package/dist/el-FIBNLH2V.mjs.map +1 -0
- package/dist/fa-3N4CIWE6.mjs +376 -0
- package/dist/fa-3N4CIWE6.mjs.map +1 -0
- package/dist/fi-JOM3M7Z4.mjs +376 -0
- package/dist/fi-JOM3M7Z4.mjs.map +1 -0
- package/dist/fr-56QSXS7E.mjs +376 -0
- package/dist/fr-56QSXS7E.mjs.map +1 -0
- package/dist/he-SNAXPJEK.mjs +376 -0
- package/dist/he-SNAXPJEK.mjs.map +1 -0
- package/dist/hi-CRBRD5TB.mjs +376 -0
- package/dist/hi-CRBRD5TB.mjs.map +1 -0
- package/dist/id-BRCVLICF.mjs +376 -0
- package/dist/id-BRCVLICF.mjs.map +1 -0
- package/dist/index.d.mts +169 -165
- package/dist/index.mjs +317 -313
- package/dist/index.mjs.map +1 -1
- package/dist/it-M2Z27BNB.mjs +376 -0
- package/dist/it-M2Z27BNB.mjs.map +1 -0
- package/dist/ja-TZUKW7HD.mjs +376 -0
- package/dist/ja-TZUKW7HD.mjs.map +1 -0
- package/dist/ko-NKBGGOL6.mjs +376 -0
- package/dist/ko-NKBGGOL6.mjs.map +1 -0
- package/dist/ms-XFXPN6RX.mjs +376 -0
- package/dist/ms-XFXPN6RX.mjs.map +1 -0
- package/dist/nl-MVYXAS5C.mjs +379 -0
- package/dist/nl-MVYXAS5C.mjs.map +1 -0
- package/dist/no-XOLO4JPV.mjs +376 -0
- package/dist/no-XOLO4JPV.mjs.map +1 -0
- package/dist/pl-TRWLMMC4.mjs +376 -0
- package/dist/pl-TRWLMMC4.mjs.map +1 -0
- package/dist/pt-M3TE24UI.mjs +376 -0
- package/dist/pt-M3TE24UI.mjs.map +1 -0
- package/dist/ro-QBFG2T64.mjs +376 -0
- package/dist/ro-QBFG2T64.mjs.map +1 -0
- package/dist/sv-IUECBXWX.mjs +376 -0
- package/dist/sv-IUECBXWX.mjs.map +1 -0
- package/dist/test-utils.d.mts +2 -2
- package/dist/test-utils.mjs +2 -2
- package/dist/th-US7KIN5Q.mjs +376 -0
- package/dist/th-US7KIN5Q.mjs.map +1 -0
- package/dist/tr-DWJ2FFUK.mjs +376 -0
- package/dist/tr-DWJ2FFUK.mjs.map +1 -0
- package/dist/uk-M4ZE4DPZ.mjs +376 -0
- package/dist/uk-M4ZE4DPZ.mjs.map +1 -0
- package/dist/vi-FERZNPSH.mjs +376 -0
- package/dist/vi-FERZNPSH.mjs.map +1 -0
- package/dist/zh-3J2I3WYK.mjs +376 -0
- package/dist/zh-3J2I3WYK.mjs.map +1 -0
- package/package.json +1 -1
- package/src/components/AnnotateReferencesProgressWidget.tsx +5 -5
- package/src/components/CodeMirrorRenderer.tsx +5 -5
- 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 +10 -10
- package/src/components/image-annotation/SvgDrawingCanvas.tsx +4 -4
- package/src/components/navigation/CollapsibleResourceNavigation.tsx +7 -7
- package/src/components/navigation/ObservableLink.tsx +3 -3
- package/src/components/navigation/SimpleNavigation.tsx +2 -2
- package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +8 -8
- package/src/components/resource/AnnotateView.tsx +12 -12
- package/src/components/resource/BrowseView.tsx +9 -9
- package/src/components/resource/ResourceViewer.tsx +23 -23
- package/src/components/resource/__tests__/BrowseView.test.tsx +27 -27
- package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +1 -1
- package/src/components/resource/panels/AssessmentEntry.tsx +2 -2
- package/src/components/resource/panels/AssessmentPanel.tsx +7 -7
- package/src/components/resource/panels/AssistSection.tsx +5 -5
- package/src/components/resource/panels/CommentEntry.tsx +2 -2
- package/src/components/resource/panels/CommentsPanel.tsx +7 -7
- package/src/components/resource/panels/HighlightEntry.tsx +2 -2
- package/src/components/resource/panels/HighlightPanel.tsx +5 -5
- package/src/components/resource/panels/ReferenceEntry.tsx +8 -8
- package/src/components/resource/panels/ReferencesPanel.tsx +10 -10
- package/src/components/resource/panels/ResourceInfoPanel.tsx +6 -6
- package/src/components/resource/panels/TagEntry.tsx +2 -2
- package/src/components/resource/panels/TaggingPanel.tsx +8 -8
- package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +2 -2
- package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +4 -4
- package/src/components/resource/panels/__tests__/AssistSection.test.tsx +4 -4
- 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.annotationProgress.test.tsx +1 -1
- package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +3 -3
- package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +9 -9
- package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +5 -5
- package/src/features/admin-devops/components/AdminDevOpsPage.tsx +2 -1
- package/src/features/admin-security/components/AdminSecurityPage.tsx +2 -1
- package/src/features/admin-users/components/AdminUsersPage.tsx +2 -1
- package/src/features/moderate-entity-tags/components/EntityTagsPage.tsx +2 -1
- package/src/features/moderate-recent/components/RecentDocumentsPage.tsx +2 -1
- package/src/features/moderate-tag-schemas/components/TagSchemasPage.tsx +2 -1
- package/src/features/resource-compose/components/ResourceComposePage.tsx +2 -1
- package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +2 -1
- package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +26 -26
- package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +21 -21
- package/src/features/resource-viewer/__tests__/AnnotationProgressDismissal.test.tsx +23 -23
- package/src/features/resource-viewer/__tests__/{ResolutionFlowIntegration.test.tsx → BindFlowIntegration.test.tsx} +49 -49
- package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +18 -18
- package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +19 -19
- package/src/features/resource-viewer/__tests__/ResourceMutations.test.tsx +19 -19
- package/src/features/resource-viewer/__tests__/ToastNotifications.test.tsx +13 -13
- package/src/features/resource-viewer/__tests__/{GenerationFlowIntegration.test.tsx → YieldFlowIntegration.test.tsx} +34 -34
- package/src/features/resource-viewer/__tests__/annotation-progress-flow.test.tsx +11 -11
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +55 -55
- package/translations/ar.json +298 -298
- package/translations/bn.json +298 -298
- package/translations/cs.json +295 -295
- package/translations/da.json +282 -282
- package/translations/de.json +281 -281
- package/translations/el.json +298 -298
- package/translations/fa.json +298 -298
- package/translations/fi.json +298 -298
- package/translations/fr.json +279 -279
- package/translations/he.json +298 -298
- package/translations/hi.json +298 -298
- package/translations/id.json +295 -295
- package/translations/it.json +299 -299
- package/translations/ja.json +298 -298
- package/translations/ko.json +298 -298
- package/translations/ms.json +296 -296
- package/translations/nl.json +299 -296
- package/translations/no.json +292 -292
- package/translations/pl.json +297 -297
- package/translations/pt.json +294 -294
- package/translations/ro.json +298 -298
- package/translations/sv.json +293 -293
- package/translations/th.json +298 -298
- package/translations/tr.json +298 -298
- package/translations/uk.json +298 -298
- package/translations/vi.json +298 -298
- package/translations/zh.json +298 -298
- package/dist/PdfAnnotationCanvas.client-HNYRKFDS.mjs.map +0 -1
- package/dist/ar-MDB7HC5S.mjs +0 -376
- package/dist/ar-MDB7HC5S.mjs.map +0 -1
- package/dist/bn-3SAV2ZEM.mjs +0 -376
- package/dist/bn-3SAV2ZEM.mjs.map +0 -1
- package/dist/chunk-MWQ5CNKW.mjs.map +0 -1
- package/dist/cs-AWCETEUV.mjs +0 -376
- package/dist/cs-AWCETEUV.mjs.map +0 -1
- package/dist/da-UZZHXYLC.mjs +0 -376
- package/dist/da-UZZHXYLC.mjs.map +0 -1
- package/dist/de-LQFWN6S5.mjs +0 -376
- package/dist/de-LQFWN6S5.mjs.map +0 -1
- package/dist/el-IWOETBJ7.mjs +0 -376
- package/dist/el-IWOETBJ7.mjs.map +0 -1
- package/dist/fa-BVEJZT5S.mjs +0 -376
- package/dist/fa-BVEJZT5S.mjs.map +0 -1
- package/dist/fi-JBNCGGA6.mjs +0 -376
- package/dist/fi-JBNCGGA6.mjs.map +0 -1
- package/dist/fr-OLH7PNGI.mjs +0 -376
- package/dist/fr-OLH7PNGI.mjs.map +0 -1
- package/dist/he-KOJQ4HMA.mjs +0 -376
- package/dist/he-KOJQ4HMA.mjs.map +0 -1
- package/dist/hi-BKJFZXAY.mjs +0 -376
- package/dist/hi-BKJFZXAY.mjs.map +0 -1
- package/dist/id-DPLHJVNP.mjs +0 -376
- package/dist/id-DPLHJVNP.mjs.map +0 -1
- package/dist/it-JXHAM7NL.mjs +0 -376
- package/dist/it-JXHAM7NL.mjs.map +0 -1
- package/dist/ja-DQRAO3PU.mjs +0 -376
- package/dist/ja-DQRAO3PU.mjs.map +0 -1
- package/dist/ko-6IFCOP6F.mjs +0 -376
- package/dist/ko-6IFCOP6F.mjs.map +0 -1
- package/dist/ms-KF5S2TLL.mjs +0 -376
- package/dist/ms-KF5S2TLL.mjs.map +0 -1
- package/dist/nl-2GUUZLQM.mjs +0 -376
- package/dist/nl-2GUUZLQM.mjs.map +0 -1
- package/dist/no-2IBCZGEF.mjs +0 -376
- package/dist/no-2IBCZGEF.mjs.map +0 -1
- package/dist/pl-ZEUBJ7YU.mjs +0 -376
- package/dist/pl-ZEUBJ7YU.mjs.map +0 -1
- package/dist/pt-WLAFIZWQ.mjs +0 -376
- package/dist/pt-WLAFIZWQ.mjs.map +0 -1
- package/dist/ro-K56IXFGU.mjs +0 -376
- package/dist/ro-K56IXFGU.mjs.map +0 -1
- package/dist/sv-VFJLMJRY.mjs +0 -376
- package/dist/sv-VFJLMJRY.mjs.map +0 -1
- package/dist/th-RICLQ2GW.mjs +0 -376
- package/dist/th-RICLQ2GW.mjs.map +0 -1
- package/dist/tr-SALXWE2M.mjs +0 -376
- package/dist/tr-SALXWE2M.mjs.map +0 -1
- package/dist/uk-3U3T3O2E.mjs +0 -376
- package/dist/uk-3U3T3O2E.mjs.map +0 -1
- package/dist/vi-LIVNZXOB.mjs +0 -376
- package/dist/vi-LIVNZXOB.mjs.map +0 -1
- package/dist/zh-KDUAZPX3.mjs +0 -376
- package/dist/zh-KDUAZPX3.mjs.map +0 -1
- /package/dist/{chunk-3FIQXKQF.mjs.map → chunk-Q2KV6Y2J.mjs.map} +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Layer 3: Feature Integration Test - Resolution Flow (search modal & body update)
|
|
3
3
|
*
|
|
4
|
-
* Tests the UNCOVERED half of
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
4
|
+
* Tests the UNCOVERED half of useBindFlow:
|
|
5
|
+
* - bind:link → emits bind:search-requested
|
|
6
|
+
* - bind:search-requested → opens search modal with pendingReferenceId
|
|
7
7
|
* - onCloseSearchModal → closes modal
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
8
|
+
* - bind:update-body → calls updateAnnotationBody API
|
|
9
|
+
* - bind:update-body → emits bind:body-updated on success
|
|
10
|
+
* - bind:update-body → emits bind:body-update-failed on error
|
|
11
11
|
* - auth token passed to updateAnnotationBody
|
|
12
12
|
*
|
|
13
|
-
* The deletion half of
|
|
13
|
+
* The deletion half of useBindFlow is covered by AnnotationDeletionIntegration.test.tsx.
|
|
14
14
|
*
|
|
15
15
|
* Uses real providers (EventBus, ApiClient, AuthToken) with mocked API boundary.
|
|
16
16
|
*/
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
19
19
|
import { render, waitFor } from '@testing-library/react';
|
|
20
20
|
import { act } from 'react';
|
|
21
|
-
import {
|
|
21
|
+
import { useBindFlow } from '../../../hooks/useBindFlow';
|
|
22
22
|
import { EventBusProvider, useEventBus, resetEventBusForTesting } from '../../../contexts/EventBusContext';
|
|
23
23
|
import { ApiClientProvider } from '../../../contexts/ApiClientContext';
|
|
24
24
|
import { AuthTokenProvider } from '../../../contexts/AuthTokenContext';
|
|
@@ -55,13 +55,13 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
|
|
|
55
55
|
|
|
56
56
|
// ─── Render helper ──────────────────────────────────────────────────────────
|
|
57
57
|
|
|
58
|
-
function
|
|
58
|
+
function renderBindFlow() {
|
|
59
59
|
let eventBusInstance: ReturnType<typeof useEventBus> | null = null;
|
|
60
|
-
let lastState: ReturnType<typeof
|
|
60
|
+
let lastState: ReturnType<typeof useBindFlow> | null = null;
|
|
61
61
|
|
|
62
62
|
function TestComponent() {
|
|
63
63
|
eventBusInstance = useEventBus();
|
|
64
|
-
lastState =
|
|
64
|
+
lastState = useBindFlow(testUri);
|
|
65
65
|
return null;
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -84,19 +84,19 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
|
|
|
84
84
|
// ─── Initial state ──────────────────────────────────────────────────────────
|
|
85
85
|
|
|
86
86
|
it('starts with search modal closed and no pending reference', () => {
|
|
87
|
-
const { getState } =
|
|
87
|
+
const { getState } = renderBindFlow();
|
|
88
88
|
expect(getState().searchModalOpen).toBe(false);
|
|
89
89
|
expect(getState().pendingReferenceId).toBeNull();
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
// ───
|
|
92
|
+
// ─── bind:link ─────────────────────────────────────────────────────────
|
|
93
93
|
|
|
94
|
-
it('
|
|
95
|
-
const { getEventBus } =
|
|
94
|
+
it('bind:link emits bind:search-requested with referenceId and searchTerm', () => {
|
|
95
|
+
const { getEventBus } = renderBindFlow();
|
|
96
96
|
const searchRequestedSpy = vi.fn();
|
|
97
97
|
|
|
98
|
-
const subscription = getEventBus().get('
|
|
99
|
-
act(() => { getEventBus().get('
|
|
98
|
+
const subscription = getEventBus().get('bind:search-requested').subscribe(searchRequestedSpy);
|
|
99
|
+
act(() => { getEventBus().get('bind:link').next({ annotationUri: 'ann-uri-123', searchTerm: 'climate change' }); });
|
|
100
100
|
subscription.unsubscribe();
|
|
101
101
|
|
|
102
102
|
expect(searchRequestedSpy).toHaveBeenCalledTimes(1);
|
|
@@ -106,35 +106,35 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
|
|
|
106
106
|
});
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
-
// ───
|
|
109
|
+
// ─── bind:search-requested ────────────────────────────────────────────
|
|
110
110
|
|
|
111
|
-
it('
|
|
112
|
-
const { getState, getEventBus } =
|
|
111
|
+
it('bind:search-requested opens the search modal', async () => {
|
|
112
|
+
const { getState, getEventBus } = renderBindFlow();
|
|
113
113
|
|
|
114
114
|
expect(getState().searchModalOpen).toBe(false);
|
|
115
115
|
|
|
116
|
-
act(() => { getEventBus().get('
|
|
116
|
+
act(() => { getEventBus().get('bind:search-requested').next({ referenceId: 'ref-abc', searchTerm: 'oceans' }); });
|
|
117
117
|
|
|
118
118
|
await waitFor(() => {
|
|
119
119
|
expect(getState().searchModalOpen).toBe(true);
|
|
120
120
|
});
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
-
it('
|
|
124
|
-
const { getState, getEventBus } =
|
|
123
|
+
it('bind:search-requested sets pendingReferenceId', async () => {
|
|
124
|
+
const { getState, getEventBus } = renderBindFlow();
|
|
125
125
|
|
|
126
|
-
act(() => { getEventBus().get('
|
|
126
|
+
act(() => { getEventBus().get('bind:search-requested').next({ referenceId: 'ref-xyz', searchTerm: 'forests' }); });
|
|
127
127
|
|
|
128
128
|
await waitFor(() => {
|
|
129
129
|
expect(getState().pendingReferenceId).toBe('ref-xyz');
|
|
130
130
|
});
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
-
it('
|
|
134
|
-
const { getState, getEventBus } =
|
|
133
|
+
it('bind:link → bind:search-requested chain opens modal end-to-end', async () => {
|
|
134
|
+
const { getState, getEventBus } = renderBindFlow();
|
|
135
135
|
|
|
136
136
|
// Simulate the full user journey: user clicks "Link Document" on a reference entry
|
|
137
|
-
act(() => { getEventBus().get('
|
|
137
|
+
act(() => { getEventBus().get('bind:link').next({ annotationUri: 'ann-full-chain', searchTerm: 'biodiversity' }); });
|
|
138
138
|
|
|
139
139
|
await waitFor(() => {
|
|
140
140
|
expect(getState().searchModalOpen).toBe(true);
|
|
@@ -145,9 +145,9 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
|
|
|
145
145
|
// ─── onCloseSearchModal ──────────────────────────────────────────────────────
|
|
146
146
|
|
|
147
147
|
it('onCloseSearchModal closes the search modal', async () => {
|
|
148
|
-
const { getState, getEventBus } =
|
|
148
|
+
const { getState, getEventBus } = renderBindFlow();
|
|
149
149
|
|
|
150
|
-
act(() => { getEventBus().get('
|
|
150
|
+
act(() => { getEventBus().get('bind:search-requested').next({ referenceId: 'ref-close', searchTerm: 'test' }); });
|
|
151
151
|
|
|
152
152
|
await waitFor(() => expect(getState().searchModalOpen).toBe(true));
|
|
153
153
|
|
|
@@ -159,9 +159,9 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
|
|
|
159
159
|
});
|
|
160
160
|
|
|
161
161
|
it('onCloseSearchModal does not clear pendingReferenceId (preserves for re-open)', async () => {
|
|
162
|
-
const { getState, getEventBus } =
|
|
162
|
+
const { getState, getEventBus } = renderBindFlow();
|
|
163
163
|
|
|
164
|
-
act(() => { getEventBus().get('
|
|
164
|
+
act(() => { getEventBus().get('bind:search-requested').next({ referenceId: 'ref-persist', searchTerm: 'test' }); });
|
|
165
165
|
await waitFor(() => expect(getState().searchModalOpen).toBe(true));
|
|
166
166
|
|
|
167
167
|
act(() => { getState().onCloseSearchModal(); });
|
|
@@ -171,12 +171,12 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
|
|
|
171
171
|
expect(getState().pendingReferenceId).toBe('ref-persist');
|
|
172
172
|
});
|
|
173
173
|
|
|
174
|
-
// ───
|
|
174
|
+
// ─── bind:update-body ──────────────────────────────────────────────────
|
|
175
175
|
|
|
176
|
-
it('
|
|
177
|
-
const { getEventBus } =
|
|
176
|
+
it('bind:update-body calls updateAnnotationBody API', async () => {
|
|
177
|
+
const { getEventBus } = renderBindFlow();
|
|
178
178
|
|
|
179
|
-
act(() => { getEventBus().get('
|
|
179
|
+
act(() => { getEventBus().get('bind:update-body').next({
|
|
180
180
|
annotationUri: 'http://localhost:4000/resources/test-resource/annotations/ann-body-1',
|
|
181
181
|
resourceId: 'linked-resource-id',
|
|
182
182
|
operations: [{ op: 'add', item: { id: 'linked-resource-id' } }],
|
|
@@ -187,10 +187,10 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
|
|
|
187
187
|
});
|
|
188
188
|
});
|
|
189
189
|
|
|
190
|
-
it('
|
|
191
|
-
const { getEventBus } =
|
|
190
|
+
it('bind:update-body passes auth token to API call', async () => {
|
|
191
|
+
const { getEventBus } = renderBindFlow();
|
|
192
192
|
|
|
193
|
-
act(() => { getEventBus().get('
|
|
193
|
+
act(() => { getEventBus().get('bind:update-body').next({
|
|
194
194
|
annotationUri: 'http://localhost:4000/resources/test-resource/annotations/ann-auth',
|
|
195
195
|
resourceId: 'resource-id',
|
|
196
196
|
operations: [{ op: 'replace', newItem: { id: 'resource-id' } }],
|
|
@@ -205,13 +205,13 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
|
|
|
205
205
|
expect(callArgs[2].auth).toBe(accessToken(testToken));
|
|
206
206
|
});
|
|
207
207
|
|
|
208
|
-
it('
|
|
209
|
-
const { getEventBus } =
|
|
208
|
+
it('bind:update-body emits bind:body-updated on success', async () => {
|
|
209
|
+
const { getEventBus } = renderBindFlow();
|
|
210
210
|
const bodyUpdatedSpy = vi.fn();
|
|
211
211
|
|
|
212
|
-
const subscription = getEventBus().get('
|
|
212
|
+
const subscription = getEventBus().get('bind:body-updated').subscribe(bodyUpdatedSpy);
|
|
213
213
|
|
|
214
|
-
act(() => { getEventBus().get('
|
|
214
|
+
act(() => { getEventBus().get('bind:update-body').next({
|
|
215
215
|
annotationUri: 'http://localhost:4000/resources/test-resource/annotations/ann-success',
|
|
216
216
|
resourceId: 'resource-id',
|
|
217
217
|
operations: [{ op: 'add', item: { id: 'resource-id' } }],
|
|
@@ -228,15 +228,15 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
|
|
|
228
228
|
});
|
|
229
229
|
});
|
|
230
230
|
|
|
231
|
-
it('
|
|
231
|
+
it('bind:update-body emits bind:body-update-failed on API error', async () => {
|
|
232
232
|
updateAnnotationBodySpy.mockRejectedValue(new Error('Update failed'));
|
|
233
233
|
|
|
234
|
-
const { getEventBus } =
|
|
234
|
+
const { getEventBus } = renderBindFlow();
|
|
235
235
|
const bodyUpdateFailedSpy = vi.fn();
|
|
236
236
|
|
|
237
|
-
const subscription = getEventBus().get('
|
|
237
|
+
const subscription = getEventBus().get('bind:body-update-failed').subscribe(bodyUpdateFailedSpy);
|
|
238
238
|
|
|
239
|
-
act(() => { getEventBus().get('
|
|
239
|
+
act(() => { getEventBus().get('bind:update-body').next({
|
|
240
240
|
annotationUri: 'http://localhost:4000/resources/test-resource/annotations/ann-fail',
|
|
241
241
|
resourceId: 'resource-id',
|
|
242
242
|
operations: [{ op: 'remove', item: { id: 'old-id' } }],
|
|
@@ -253,10 +253,10 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
|
|
|
253
253
|
});
|
|
254
254
|
});
|
|
255
255
|
|
|
256
|
-
it('
|
|
257
|
-
const { getEventBus } =
|
|
256
|
+
it('bind:update-body called ONCE — no duplicate subscriptions', async () => {
|
|
257
|
+
const { getEventBus } = renderBindFlow();
|
|
258
258
|
|
|
259
|
-
act(() => { getEventBus().get('
|
|
259
|
+
act(() => { getEventBus().get('bind:update-body').next({
|
|
260
260
|
annotationUri: 'http://localhost:4000/resources/test-resource/annotations/ann-dedup',
|
|
261
261
|
resourceId: 'resource-id',
|
|
262
262
|
operations: [{ op: 'add', item: { id: 'resource-id' } }],
|
|
@@ -2,18 +2,18 @@
|
|
|
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
|
-
* ✅
|
|
5
|
+
* ✅ mark:assist-request emitted
|
|
6
6
|
* ✅ annotate:assist-progress emitted
|
|
7
7
|
* ❌ assistingMotivation remains null
|
|
8
8
|
* ❌ progress remains null
|
|
9
9
|
*
|
|
10
|
-
* UPDATED: Now tests
|
|
10
|
+
* UPDATED: Now tests useMarkFlow 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 { useMarkFlow } from '../../../hooks/useMarkFlow';
|
|
17
17
|
import { EventBusProvider, useEventBus, resetEventBusForTesting } from '../../../contexts/EventBusContext';
|
|
18
18
|
import { ApiClientProvider } from '../../../contexts/ApiClientContext';
|
|
19
19
|
import { AuthTokenProvider } from '../../../contexts/AuthTokenContext';
|
|
@@ -45,17 +45,17 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
45
45
|
vi.restoreAllMocks();
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
it('SHOULD update state when
|
|
48
|
+
it('SHOULD update state when mark:assist-request event is emitted', async () => {
|
|
49
49
|
let eventBusInstance: any;
|
|
50
50
|
let currentState: any;
|
|
51
51
|
|
|
52
52
|
// Component to capture EventBus and hook state
|
|
53
53
|
function TestComponent() {
|
|
54
54
|
eventBusInstance = useEventBus();
|
|
55
|
-
const state =
|
|
55
|
+
const state = useMarkFlow('http://localhost:8080/resources/test' as any);
|
|
56
56
|
currentState = state;
|
|
57
57
|
|
|
58
|
-
console.log('[TEST]
|
|
58
|
+
console.log('[TEST] useMarkFlow state:', {
|
|
59
59
|
assistingMotivation: state.assistingMotivation,
|
|
60
60
|
progress: state.progress,
|
|
61
61
|
});
|
|
@@ -82,17 +82,17 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
82
82
|
expect(screen.getByTestId('detecting')).toHaveTextContent('null');
|
|
83
83
|
expect(screen.getByTestId('progress')).toHaveTextContent('null');
|
|
84
84
|
|
|
85
|
-
console.log('[TEST] Emitting
|
|
85
|
+
console.log('[TEST] Emitting mark:assist-request event...');
|
|
86
86
|
|
|
87
|
-
// Emit
|
|
87
|
+
// Emit mark:assist-request event (exactly like production)
|
|
88
88
|
act(() => {
|
|
89
|
-
eventBusInstance.get('
|
|
89
|
+
eventBusInstance.get('mark:assist-request').next({
|
|
90
90
|
motivation: 'linking',
|
|
91
91
|
options: { entityTypes: ['Location'] }
|
|
92
92
|
});
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
console.log('[TEST] After
|
|
95
|
+
console.log('[TEST] After mark:assist-request, checking state...');
|
|
96
96
|
|
|
97
97
|
// THIS SHOULD PASS but currently FAILS
|
|
98
98
|
await waitFor(() => {
|
|
@@ -109,7 +109,7 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
109
109
|
|
|
110
110
|
function TestComponent() {
|
|
111
111
|
eventBusInstance = useEventBus();
|
|
112
|
-
const state =
|
|
112
|
+
const state = useMarkFlow('http://localhost:8080/resources/test' as any);
|
|
113
113
|
currentState = state;
|
|
114
114
|
|
|
115
115
|
return (
|
|
@@ -134,7 +134,7 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
134
134
|
|
|
135
135
|
// Emit annotate:assist-progress event (exactly like production)
|
|
136
136
|
act(() => {
|
|
137
|
-
eventBusInstance.get('
|
|
137
|
+
eventBusInstance.get('mark:progress').next({
|
|
138
138
|
status: 'started',
|
|
139
139
|
resourceId: 'test',
|
|
140
140
|
totalEntityTypes: 1,
|
|
@@ -162,7 +162,7 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
162
162
|
|
|
163
163
|
function TestComponent() {
|
|
164
164
|
eventBusInstance = useEventBus();
|
|
165
|
-
const state =
|
|
165
|
+
const state = useMarkFlow('http://localhost:8080/resources/f45fd44f9cb0b0fe1b7980d3d034bc61' as any);
|
|
166
166
|
|
|
167
167
|
stateSnapshots.push({
|
|
168
168
|
assistingMotivation: state.assistingMotivation,
|
|
@@ -192,18 +192,18 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
192
192
|
|
|
193
193
|
// Exactly like production logs
|
|
194
194
|
act(() => {
|
|
195
|
-
console.log('[EventBus] emit:
|
|
196
|
-
eventBusInstance.get('
|
|
195
|
+
console.log('[EventBus] emit: mark:assist-request {motivation: "linking", options: {...}}');
|
|
196
|
+
eventBusInstance.get('mark:assist-request').next({
|
|
197
197
|
motivation: 'linking',
|
|
198
198
|
options: { entityTypes: ['Location'] }
|
|
199
199
|
});
|
|
200
200
|
});
|
|
201
201
|
|
|
202
|
-
console.log('After
|
|
202
|
+
console.log('After mark:assist-request:', stateSnapshots[stateSnapshots.length - 1]);
|
|
203
203
|
|
|
204
204
|
act(() => {
|
|
205
205
|
console.log('[EventBus] emit: annotate:assist-progress {status: "started", ...}');
|
|
206
|
-
eventBusInstance.get('
|
|
206
|
+
eventBusInstance.get('mark:progress').next({
|
|
207
207
|
status: 'started',
|
|
208
208
|
resourceId: 'f45fd44f9cb0b0fe1b7980d3d034bc61',
|
|
209
209
|
totalEntityTypes: 1,
|
|
@@ -216,7 +216,7 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
216
216
|
|
|
217
217
|
act(() => {
|
|
218
218
|
console.log('[EventBus] emit: annotate:assist-progress {status: "scanning", ...}');
|
|
219
|
-
eventBusInstance.get('
|
|
219
|
+
eventBusInstance.get('mark:progress').next({
|
|
220
220
|
status: 'scanning',
|
|
221
221
|
resourceId: 'f45fd44f9cb0b0fe1b7980d3d034bc61',
|
|
222
222
|
currentEntityType: 'Location',
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Tests the COMPLETE detection flow with real component composition:
|
|
5
5
|
* - EventBusProvider (REAL)
|
|
6
6
|
* - ApiClientProvider (REAL, with MOCKED client)
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
7
|
+
* - useMarkFlow (REAL)
|
|
8
|
+
* - useBindFlow (REAL)
|
|
9
9
|
* - useEventSubscriptions (REAL)
|
|
10
10
|
*
|
|
11
11
|
* This test focuses on ARCHITECTURE and EVENT WIRING:
|
|
@@ -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 { useMarkFlow } from '../../../hooks/useMarkFlow';
|
|
29
29
|
import { EventBusProvider, useEventBus, resetEventBusForTesting } from '../../../contexts/EventBusContext';
|
|
30
30
|
import { ApiClientProvider } from '../../../contexts/ApiClientContext';
|
|
31
31
|
import { AuthTokenProvider } from '../../../contexts/AuthTokenContext';
|
|
@@ -91,7 +91,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
// CRITICAL ASSERTION: API called exactly once (not twice!)
|
|
94
|
-
// This would FAIL if
|
|
94
|
+
// This would FAIL if useBindFlow was called in multiple places
|
|
95
95
|
await waitFor(() => {
|
|
96
96
|
expect(annotateReferencesSpy).toHaveBeenCalledTimes(1);
|
|
97
97
|
});
|
|
@@ -107,7 +107,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
107
107
|
);
|
|
108
108
|
});
|
|
109
109
|
|
|
110
|
-
it('should propagate SSE progress events to
|
|
110
|
+
it('should propagate SSE progress events to useMarkFlow state', async () => {
|
|
111
111
|
const testUri = resourceUri('http://localhost:4000/resources/test-resource');
|
|
112
112
|
|
|
113
113
|
// Render with state observer
|
|
@@ -127,7 +127,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
127
127
|
|
|
128
128
|
// Simulate SSE progress event being emitted to EventBus (how SSE actually works now)
|
|
129
129
|
act(() => {
|
|
130
|
-
getEventBus().get('
|
|
130
|
+
getEventBus().get('mark:progress').next({
|
|
131
131
|
status: 'scanning',
|
|
132
132
|
message: 'Scanning for Person...',
|
|
133
133
|
currentEntityType: 'Person',
|
|
@@ -161,7 +161,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
161
161
|
|
|
162
162
|
// First progress update via EventBus
|
|
163
163
|
act(() => {
|
|
164
|
-
getEventBus().get('
|
|
164
|
+
getEventBus().get('mark:progress').next({
|
|
165
165
|
status: 'started',
|
|
166
166
|
message: 'Starting analysis...',
|
|
167
167
|
percentage: 0,
|
|
@@ -174,7 +174,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
174
174
|
|
|
175
175
|
// Second progress update via EventBus
|
|
176
176
|
act(() => {
|
|
177
|
-
getEventBus().get('
|
|
177
|
+
getEventBus().get('mark:progress').next({
|
|
178
178
|
status: 'analyzing',
|
|
179
179
|
message: 'Analyzing text...',
|
|
180
180
|
percentage: 50,
|
|
@@ -187,7 +187,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
187
187
|
|
|
188
188
|
// Final progress update via EventBus
|
|
189
189
|
act(() => {
|
|
190
|
-
getEventBus().get('
|
|
190
|
+
getEventBus().get('mark:progress').next({
|
|
191
191
|
status: 'complete',
|
|
192
192
|
message: 'Created 14 highlights',
|
|
193
193
|
percentage: 100,
|
|
@@ -214,7 +214,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
214
214
|
|
|
215
215
|
// Send final progress via EventBus
|
|
216
216
|
act(() => {
|
|
217
|
-
getEventBus().get('
|
|
217
|
+
getEventBus().get('mark:progress').next({
|
|
218
218
|
status: 'complete',
|
|
219
219
|
message: 'Created 14 highlights',
|
|
220
220
|
});
|
|
@@ -226,7 +226,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
226
226
|
|
|
227
227
|
// Emit completion event
|
|
228
228
|
act(() => {
|
|
229
|
-
getEventBus().get('
|
|
229
|
+
getEventBus().get('mark:assist-finished').next({ motivation: 'highlighting' });
|
|
230
230
|
});
|
|
231
231
|
|
|
232
232
|
// Verify: detecting flag cleared BUT progress still visible
|
|
@@ -247,7 +247,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
247
247
|
|
|
248
248
|
// Add some progress via EventBus
|
|
249
249
|
act(() => {
|
|
250
|
-
getEventBus().get('
|
|
250
|
+
getEventBus().get('mark:progress').next({
|
|
251
251
|
status: 'scanning',
|
|
252
252
|
message: 'Scanning...',
|
|
253
253
|
});
|
|
@@ -259,7 +259,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
259
259
|
|
|
260
260
|
// Emit failure
|
|
261
261
|
act(() => {
|
|
262
|
-
getEventBus().get('
|
|
262
|
+
getEventBus().get('mark:assist-failed').next({
|
|
263
263
|
type: 'job.failed' as const,
|
|
264
264
|
resourceId: 'test-resource' as any,
|
|
265
265
|
userId: 'user' as any,
|
|
@@ -322,13 +322,13 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
322
322
|
it('should only call API once even with multiple event listeners', async () => {
|
|
323
323
|
const testUri = resourceUri('http://localhost:4000/resources/test-resource');
|
|
324
324
|
|
|
325
|
-
// This test specifically catches the duplicate
|
|
326
|
-
// If multiple components call
|
|
325
|
+
// This test specifically catches the duplicate useBindFlow bug
|
|
326
|
+
// If multiple components call useBindFlow, we'll see multiple API calls
|
|
327
327
|
const { emitDetectionStart, getEventBus } = renderDetectionFlow(testUri);
|
|
328
328
|
|
|
329
329
|
// Add an additional event listener (simulating multiple subscribers)
|
|
330
330
|
const additionalListener = vi.fn();
|
|
331
|
-
const subscription = getEventBus().get('
|
|
331
|
+
const subscription = getEventBus().get('mark:assist-request').subscribe(additionalListener);
|
|
332
332
|
|
|
333
333
|
// Trigger detection
|
|
334
334
|
act(() => {
|
|
@@ -351,7 +351,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
351
351
|
});
|
|
352
352
|
|
|
353
353
|
/**
|
|
354
|
-
* Helper: Render
|
|
354
|
+
* Helper: Render useMarkFlow hook with real component composition
|
|
355
355
|
* Returns methods to interact with the rendered component
|
|
356
356
|
*/
|
|
357
357
|
function renderDetectionFlow(testUri: string) {
|
|
@@ -365,7 +365,7 @@ function renderDetectionFlow(testUri: string) {
|
|
|
365
365
|
|
|
366
366
|
// Test harness component that uses the hook
|
|
367
367
|
function DetectionFlowTestHarness() {
|
|
368
|
-
const { progress, assistingMotivation } =
|
|
368
|
+
const { progress, assistingMotivation } = useMarkFlow(testUri as any);
|
|
369
369
|
return (
|
|
370
370
|
<div>
|
|
371
371
|
<div data-testid="detecting">{assistingMotivation || 'none'}</div>
|
|
@@ -389,7 +389,7 @@ function renderDetectionFlow(testUri: string) {
|
|
|
389
389
|
|
|
390
390
|
return {
|
|
391
391
|
emitDetectionStart: (motivation: Motivation, options: any) => {
|
|
392
|
-
eventBusInstance.get('
|
|
392
|
+
eventBusInstance.get('mark:assist-request').next({ motivation, options });
|
|
393
393
|
},
|
|
394
394
|
getEventBus: () => eventBusInstance,
|
|
395
395
|
};
|
|
@@ -80,9 +80,9 @@ function ResourceMutationHarness({ onEventBus }: { onEventBus: (eventBus: EventB
|
|
|
80
80
|
}, [generateCloneTokenMutation]);
|
|
81
81
|
|
|
82
82
|
useEventSubscriptions({
|
|
83
|
-
'
|
|
84
|
-
'
|
|
85
|
-
'
|
|
83
|
+
'mark:archive': handleResourceArchive,
|
|
84
|
+
'mark:unarchive': handleResourceUnarchive,
|
|
85
|
+
'yield:clone': handleResourceClone,
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
return null;
|
|
@@ -153,11 +153,11 @@ describe('Resource mutations — hooks hoisted to top level', () => {
|
|
|
153
153
|
|
|
154
154
|
// ── Clone ──────────────────────────────────────────────────────────────────
|
|
155
155
|
|
|
156
|
-
it('calls generateCloneToken API when
|
|
156
|
+
it('calls generateCloneToken API when yield:clone event fires', async () => {
|
|
157
157
|
const { emit } = renderHarness();
|
|
158
158
|
|
|
159
159
|
await act(async () => {
|
|
160
|
-
emit('
|
|
160
|
+
emit('yield:clone', undefined);
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
await waitFor(() => {
|
|
@@ -169,7 +169,7 @@ describe('Resource mutations — hooks hoisted to top level', () => {
|
|
|
169
169
|
const { emit } = renderHarness();
|
|
170
170
|
|
|
171
171
|
await act(async () => {
|
|
172
|
-
emit('
|
|
172
|
+
emit('yield:clone', undefined);
|
|
173
173
|
});
|
|
174
174
|
|
|
175
175
|
await waitFor(() => {
|
|
@@ -184,7 +184,7 @@ describe('Resource mutations — hooks hoisted to top level', () => {
|
|
|
184
184
|
const { emit } = renderHarness();
|
|
185
185
|
|
|
186
186
|
await act(async () => {
|
|
187
|
-
emit('
|
|
187
|
+
emit('yield:clone', undefined);
|
|
188
188
|
});
|
|
189
189
|
|
|
190
190
|
await waitFor(() => {
|
|
@@ -199,7 +199,7 @@ describe('Resource mutations — hooks hoisted to top level', () => {
|
|
|
199
199
|
const { emit } = renderHarness();
|
|
200
200
|
|
|
201
201
|
await act(async () => {
|
|
202
|
-
emit('
|
|
202
|
+
emit('yield:clone', undefined);
|
|
203
203
|
});
|
|
204
204
|
|
|
205
205
|
await waitFor(() => {
|
|
@@ -211,11 +211,11 @@ describe('Resource mutations — hooks hoisted to top level', () => {
|
|
|
211
211
|
expect(writtenUrl).toContain('/know/clone?token=');
|
|
212
212
|
});
|
|
213
213
|
|
|
214
|
-
it('does NOT call updateResource when
|
|
214
|
+
it('does NOT call updateResource when yield:clone fires', async () => {
|
|
215
215
|
const { emit } = renderHarness();
|
|
216
216
|
|
|
217
217
|
await act(async () => {
|
|
218
|
-
emit('
|
|
218
|
+
emit('yield:clone', undefined);
|
|
219
219
|
});
|
|
220
220
|
|
|
221
221
|
await waitFor(() => {
|
|
@@ -227,11 +227,11 @@ describe('Resource mutations — hooks hoisted to top level', () => {
|
|
|
227
227
|
|
|
228
228
|
// ── Archive ────────────────────────────────────────────────────────────────
|
|
229
229
|
|
|
230
|
-
it('calls updateResource with archived:true when
|
|
230
|
+
it('calls updateResource with archived:true when mark:archive fires', async () => {
|
|
231
231
|
const { emit } = renderHarness();
|
|
232
232
|
|
|
233
233
|
await act(async () => {
|
|
234
|
-
emit('
|
|
234
|
+
emit('mark:archive', undefined);
|
|
235
235
|
});
|
|
236
236
|
|
|
237
237
|
await waitFor(() => {
|
|
@@ -245,11 +245,11 @@ describe('Resource mutations — hooks hoisted to top level', () => {
|
|
|
245
245
|
);
|
|
246
246
|
});
|
|
247
247
|
|
|
248
|
-
it('does NOT call generateCloneToken when
|
|
248
|
+
it('does NOT call generateCloneToken when mark:archive fires', async () => {
|
|
249
249
|
const { emit } = renderHarness();
|
|
250
250
|
|
|
251
251
|
await act(async () => {
|
|
252
|
-
emit('
|
|
252
|
+
emit('mark:archive', undefined);
|
|
253
253
|
});
|
|
254
254
|
|
|
255
255
|
await waitFor(() => {
|
|
@@ -261,11 +261,11 @@ describe('Resource mutations — hooks hoisted to top level', () => {
|
|
|
261
261
|
|
|
262
262
|
// ── Unarchive ──────────────────────────────────────────────────────────────
|
|
263
263
|
|
|
264
|
-
it('calls updateResource with archived:false when
|
|
264
|
+
it('calls updateResource with archived:false when mark:unarchive fires', async () => {
|
|
265
265
|
const { emit } = renderHarness();
|
|
266
266
|
|
|
267
267
|
await act(async () => {
|
|
268
|
-
emit('
|
|
268
|
+
emit('mark:unarchive', undefined);
|
|
269
269
|
});
|
|
270
270
|
|
|
271
271
|
await waitFor(() => {
|
|
@@ -281,15 +281,15 @@ describe('Resource mutations — hooks hoisted to top level', () => {
|
|
|
281
281
|
|
|
282
282
|
// ── Isolation ─────────────────────────────────────────────────────────────
|
|
283
283
|
|
|
284
|
-
it('
|
|
284
|
+
it('mark:archive and yield:clone events each call their own API exactly once', async () => {
|
|
285
285
|
const { emit } = renderHarness();
|
|
286
286
|
|
|
287
287
|
await act(async () => {
|
|
288
|
-
emit('
|
|
288
|
+
emit('mark:archive', undefined);
|
|
289
289
|
});
|
|
290
290
|
|
|
291
291
|
await act(async () => {
|
|
292
|
-
emit('
|
|
292
|
+
emit('yield:clone', undefined);
|
|
293
293
|
});
|
|
294
294
|
|
|
295
295
|
await waitFor(() => {
|