@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.
- package/dist/EventBusContext-7GvDyO0d.d.mts +414 -0
- package/dist/{PdfAnnotationCanvas.client-ADC4FFSE.mjs → PdfAnnotationCanvas.client-RAJRPQLU.mjs} +42 -27
- package/dist/PdfAnnotationCanvas.client-RAJRPQLU.mjs.map +1 -0
- package/dist/{ar-RNNSPLQB.mjs → ar-4ZEORRW2.mjs} +8 -4
- package/dist/ar-4ZEORRW2.mjs.map +1 -0
- package/dist/{bn-S2CDL7EC.mjs → bn-SEDE5BQJ.mjs} +8 -4
- package/dist/bn-SEDE5BQJ.mjs.map +1 -0
- package/dist/{chunk-UDX2Q35T.mjs → chunk-D7NBW4RV.mjs} +8 -4
- package/dist/chunk-D7NBW4RV.mjs.map +1 -0
- package/dist/{chunk-35LLVRFK.mjs → chunk-ZR4ZV2LY.mjs} +206 -146
- package/dist/chunk-ZR4ZV2LY.mjs.map +1 -0
- package/dist/{cs-RSV675WU.mjs → cs-7W4WF5WD.mjs} +8 -4
- package/dist/cs-7W4WF5WD.mjs.map +1 -0
- package/dist/{da-CHXNPWJC.mjs → da-75XGBCBK.mjs} +8 -4
- package/dist/da-75XGBCBK.mjs.map +1 -0
- package/dist/{de-KPEZ53D4.mjs → de-ODJVFLHM.mjs} +8 -4
- package/dist/de-ODJVFLHM.mjs.map +1 -0
- package/dist/{el-MW2BME5T.mjs → el-C4PM4WB3.mjs} +8 -4
- package/dist/el-C4PM4WB3.mjs.map +1 -0
- package/dist/{en-EVMIX24Y.mjs → en-KJCJQ4OO.mjs} +2 -2
- package/dist/{es-HQ24NYS3.mjs → es-WD33R7QL.mjs} +8 -4
- package/dist/es-WD33R7QL.mjs.map +1 -0
- package/dist/{fa-W34LRLHG.mjs → fa-2BP6V56P.mjs} +8 -4
- package/dist/fa-2BP6V56P.mjs.map +1 -0
- package/dist/{fi-3U44IGOA.mjs → fi-USRRW24J.mjs} +8 -4
- package/dist/fi-USRRW24J.mjs.map +1 -0
- package/dist/{fr-N7DKX6NN.mjs → fr-EC5S6WVF.mjs} +8 -4
- package/dist/fr-EC5S6WVF.mjs.map +1 -0
- package/dist/{he-CS4WRXN3.mjs → he-7TBVIKAA.mjs} +8 -4
- package/dist/he-7TBVIKAA.mjs.map +1 -0
- package/dist/{hi-GJDY46KA.mjs → hi-FO4VIZLA.mjs} +8 -4
- package/dist/hi-FO4VIZLA.mjs.map +1 -0
- package/dist/{id-WAEZJK2Y.mjs → id-7U7GGVWY.mjs} +8 -4
- package/dist/id-7U7GGVWY.mjs.map +1 -0
- package/dist/index.css +123 -85
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +699 -529
- package/dist/index.mjs +4291 -3491
- package/dist/index.mjs.map +1 -1
- package/dist/{it-VDNDMZPU.mjs → it-Y4OPL6I2.mjs} +8 -4
- package/dist/it-Y4OPL6I2.mjs.map +1 -0
- package/dist/{ja-5PEH56J5.mjs → ja-PK7SQL55.mjs} +8 -4
- package/dist/ja-PK7SQL55.mjs.map +1 -0
- package/dist/{ko-JYPL3WVA.mjs → ko-L25PXMYD.mjs} +8 -4
- package/dist/ko-L25PXMYD.mjs.map +1 -0
- package/dist/{ms-5PZVW76T.mjs → ms-STH777QM.mjs} +8 -4
- package/dist/ms-STH777QM.mjs.map +1 -0
- package/dist/{nl-YXES36KM.mjs → nl-Y7LECDDR.mjs} +8 -4
- package/dist/nl-Y7LECDDR.mjs.map +1 -0
- package/dist/{no-XRA2UCQD.mjs → no-KEKCEWU6.mjs} +8 -4
- package/dist/no-KEKCEWU6.mjs.map +1 -0
- package/dist/{pl-WH6LJA5G.mjs → pl-7A7OC75O.mjs} +8 -4
- package/dist/pl-7A7OC75O.mjs.map +1 -0
- package/dist/{pt-7GAG57BM.mjs → pt-35HTM7RA.mjs} +8 -4
- package/dist/pt-35HTM7RA.mjs.map +1 -0
- package/dist/{ro-BTDDRB7N.mjs → ro-VAWL5KQA.mjs} +8 -4
- package/dist/ro-VAWL5KQA.mjs.map +1 -0
- package/dist/{sv-7V5C2IT4.mjs → sv-7ZK5EQEB.mjs} +8 -4
- package/dist/sv-7ZK5EQEB.mjs.map +1 -0
- package/dist/test-utils.d.mts +18 -8
- package/dist/test-utils.mjs +36 -14
- package/dist/test-utils.mjs.map +1 -1
- package/dist/{th-LPKYLBX5.mjs → th-UDWZ4X34.mjs} +8 -4
- package/dist/th-UDWZ4X34.mjs.map +1 -0
- package/dist/{tr-DU4RQL4M.mjs → tr-4WMPK3UX.mjs} +8 -4
- package/dist/tr-4WMPK3UX.mjs.map +1 -0
- package/dist/{uk-36UHTDDI.mjs → uk-SSLASQYJ.mjs} +8 -4
- package/dist/uk-SSLASQYJ.mjs.map +1 -0
- package/dist/{vi-GDHOUZDH.mjs → vi-IF42Z5PU.mjs} +8 -4
- package/dist/vi-IF42Z5PU.mjs.map +1 -0
- package/dist/{zh-TYUID4XZ.mjs → zh-HRQTNTAI.mjs} +8 -4
- package/dist/zh-HRQTNTAI.mjs.map +1 -0
- package/package.json +8 -2
- package/src/components/CodeMirrorRenderer.tsx +66 -93
- package/src/components/DetectionProgressWidget.tsx +16 -5
- package/src/components/LiveRegion.tsx +18 -18
- package/src/components/ResizeHandle.tsx +10 -4
- package/src/components/SessionTimer.tsx +2 -2
- package/src/components/Toolbar.tsx +18 -9
- package/src/components/__tests__/SessionTimer.test.tsx +9 -9
- package/src/components/annotation/AnnotateToolbar.tsx +17 -15
- package/src/components/annotation/__tests__/AnnotateToolbar.test.tsx +165 -63
- package/src/components/annotation/annotation-entries.css +10 -0
- package/src/components/annotation-popups/JsonLdView.tsx +8 -2
- package/src/components/image-annotation/AnnotationOverlay.tsx +42 -22
- package/src/components/image-annotation/SvgDrawingCanvas.tsx +27 -30
- package/src/components/layout/__tests__/LeftSidebar.test.tsx +12 -33
- package/src/components/layout/__tests__/PageLayout.test.tsx +37 -32
- package/src/components/layout/__tests__/UnifiedHeader.test.tsx +21 -40
- package/src/components/modals/ResourceSearchModal.tsx +2 -2
- package/src/components/modals/SearchModal.tsx +1 -1
- package/src/components/navigation/CollapsibleResourceNavigation.tsx +14 -9
- package/src/components/navigation/NavigationTabs.css +36 -24
- package/src/components/navigation/ObservableLink.tsx +91 -0
- package/src/components/navigation/SimpleNavigation.tsx +20 -16
- package/src/components/navigation/SortableResourceTab.tsx +11 -5
- package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +51 -26
- package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +28 -22
- package/src/components/resource/AnnotateView.tsx +64 -138
- package/src/components/resource/AnnotationHistory.tsx +12 -13
- package/src/components/resource/BrowseView.tsx +89 -177
- package/src/components/resource/HistoryEvent.tsx +16 -11
- package/src/components/resource/ResourceViewer.tsx +201 -370
- package/src/components/resource/__tests__/BrowseView.test.tsx +631 -0
- package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +231 -0
- package/src/components/resource/event-formatting.ts +316 -0
- package/src/components/resource/panels/AssessmentEntry.tsx +25 -33
- package/src/components/resource/panels/AssessmentPanel.tsx +137 -31
- package/src/components/resource/panels/CollaborationPanel.tsx +20 -13
- package/src/components/resource/panels/CommentEntry.tsx +38 -32
- package/src/components/resource/panels/CommentsPanel.tsx +153 -31
- package/src/components/resource/panels/DetectSection.css +36 -1
- package/src/components/resource/panels/DetectSection.tsx +38 -10
- package/src/components/resource/panels/HighlightEntry.tsx +25 -33
- package/src/components/resource/panels/HighlightPanel.tsx +100 -25
- package/src/components/resource/panels/ReferenceEntry.tsx +61 -75
- package/src/components/resource/panels/ReferencesPanel.tsx +166 -49
- package/src/components/resource/panels/ResourceInfoPanel.tsx +47 -48
- package/src/components/resource/panels/StatisticsPanel.tsx +9 -19
- package/src/components/resource/panels/TagEntry.tsx +25 -33
- package/src/components/resource/panels/TaggingPanel.tsx +141 -25
- package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +46 -101
- package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +566 -0
- package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +86 -78
- package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +146 -141
- package/src/components/resource/panels/__tests__/DetectSection.test.tsx +480 -0
- package/src/components/resource/panels/__tests__/HighlightPanel.detectionProgress.test.tsx +362 -0
- package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +228 -103
- package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +117 -61
- package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +586 -0
- package/src/components/settings/SettingsPanel.tsx +15 -12
- package/src/features/admin-devops/__tests__/AdminDevOpsPage.test.tsx +1 -46
- package/src/features/admin-devops/components/AdminDevOpsPage.tsx +0 -9
- package/src/features/admin-security/__tests__/AdminSecurityPage.test.tsx +0 -3
- package/src/features/admin-security/components/AdminSecurityPage.tsx +0 -9
- package/src/features/admin-users/__tests__/AdminUsersPage.test.tsx +0 -3
- package/src/features/admin-users/components/AdminUsersPage.tsx +0 -9
- package/src/features/moderate-entity-tags/__tests__/EntityTagsPage.test.tsx +0 -3
- package/src/features/moderate-entity-tags/components/EntityTagsPage.tsx +1 -9
- package/src/features/moderate-recent/__tests__/RecentDocumentsPage.test.tsx +0 -32
- package/src/features/moderate-recent/components/RecentDocumentsPage.tsx +1 -9
- package/src/features/moderate-tag-schemas/__tests__/TagSchemasPage.test.tsx +0 -32
- package/src/features/moderate-tag-schemas/components/TagSchemasPage.tsx +1 -9
- package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +51 -54
- package/src/features/resource-compose/components/ResourceComposePage.tsx +3 -13
- package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +39 -45
- package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +16 -27
- package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +231 -0
- package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +234 -0
- package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +388 -0
- package/src/features/resource-viewer/__tests__/DetectionProgressDismissal.test.tsx +318 -0
- package/src/features/resource-viewer/__tests__/GenerationFlowIntegration.test.tsx +504 -0
- package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +145 -91
- package/src/features/resource-viewer/__tests__/detection-progress-flow.test.tsx +322 -0
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +325 -476
- package/src/styles/motivations/motivation-assessment.css +28 -0
- package/src/styles/patterns/panel-helpers.css +26 -0
- package/translations/ar.json +7 -3
- package/translations/bn.json +7 -3
- package/translations/cs.json +7 -3
- package/translations/da.json +7 -3
- package/translations/de.json +7 -3
- package/translations/el.json +7 -3
- package/translations/en.json +7 -3
- package/translations/es.json +7 -3
- package/translations/fa.json +7 -3
- package/translations/fi.json +7 -3
- package/translations/fr.json +7 -3
- package/translations/he.json +7 -3
- package/translations/hi.json +7 -3
- package/translations/id.json +7 -3
- package/translations/it.json +7 -3
- package/translations/ja.json +7 -3
- package/translations/ko.json +7 -3
- package/translations/ms.json +7 -3
- package/translations/nl.json +7 -3
- package/translations/no.json +7 -3
- package/translations/pl.json +7 -3
- package/translations/pt.json +7 -3
- package/translations/ro.json +7 -3
- package/translations/sv.json +7 -3
- package/translations/th.json +7 -3
- package/translations/tr.json +7 -3
- package/translations/uk.json +7 -3
- package/translations/vi.json +7 -3
- package/translations/zh.json +7 -3
- package/dist/PdfAnnotationCanvas.client-ADC4FFSE.mjs.map +0 -1
- package/dist/TranslationManager-Co_5fSxl.d.mts +0 -118
- package/dist/ar-RNNSPLQB.mjs.map +0 -1
- package/dist/bn-S2CDL7EC.mjs.map +0 -1
- package/dist/chunk-35LLVRFK.mjs.map +0 -1
- package/dist/chunk-UDX2Q35T.mjs.map +0 -1
- package/dist/cs-RSV675WU.mjs.map +0 -1
- package/dist/da-CHXNPWJC.mjs.map +0 -1
- package/dist/de-KPEZ53D4.mjs.map +0 -1
- package/dist/el-MW2BME5T.mjs.map +0 -1
- package/dist/es-HQ24NYS3.mjs.map +0 -1
- package/dist/fa-W34LRLHG.mjs.map +0 -1
- package/dist/fi-3U44IGOA.mjs.map +0 -1
- package/dist/fr-N7DKX6NN.mjs.map +0 -1
- package/dist/he-CS4WRXN3.mjs.map +0 -1
- package/dist/hi-GJDY46KA.mjs.map +0 -1
- package/dist/id-WAEZJK2Y.mjs.map +0 -1
- package/dist/it-VDNDMZPU.mjs.map +0 -1
- package/dist/ja-5PEH56J5.mjs.map +0 -1
- package/dist/ko-JYPL3WVA.mjs.map +0 -1
- package/dist/ms-5PZVW76T.mjs.map +0 -1
- package/dist/nl-YXES36KM.mjs.map +0 -1
- package/dist/no-XRA2UCQD.mjs.map +0 -1
- package/dist/pl-WH6LJA5G.mjs.map +0 -1
- package/dist/pt-7GAG57BM.mjs.map +0 -1
- package/dist/ro-BTDDRB7N.mjs.map +0 -1
- package/dist/sv-7V5C2IT4.mjs.map +0 -1
- package/dist/th-LPKYLBX5.mjs.map +0 -1
- package/dist/tr-DU4RQL4M.mjs.map +0 -1
- package/dist/uk-36UHTDDI.mjs.map +0 -1
- package/dist/vi-GDHOUZDH.mjs.map +0 -1
- package/dist/zh-TYUID4XZ.mjs.map +0 -1
- /package/dist/{en-EVMIX24Y.mjs.map → en-KJCJQ4OO.mjs.map} +0 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 1 Unit Test: DetectSection Component
|
|
3
|
+
*
|
|
4
|
+
* Tests the DetectSection component in isolation with mocked dependencies.
|
|
5
|
+
*
|
|
6
|
+
* This test verifies:
|
|
7
|
+
* - Detection progress rendering when detectionProgress prop is provided
|
|
8
|
+
* - Progress message display
|
|
9
|
+
* - Request parameters display
|
|
10
|
+
* - Form visibility toggling based on progress state
|
|
11
|
+
* - Event emission when detect button clicked
|
|
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 userEvent from '@testing-library/user-event';
|
|
19
|
+
import { DetectSection } from '../DetectSection';
|
|
20
|
+
import { resetEventBusForTesting } from '../../../../contexts/EventBusContext';
|
|
21
|
+
import type { EventBus } from '../../../../contexts/EventBusContext';
|
|
22
|
+
|
|
23
|
+
// Mock translations
|
|
24
|
+
const mockT = vi.fn((key: string) => {
|
|
25
|
+
const translations: Record<string, string> = {
|
|
26
|
+
detectHighlights: 'Detect Highlights',
|
|
27
|
+
detectAssessments: 'Detect Assessments',
|
|
28
|
+
detectComments: 'Detect Comments',
|
|
29
|
+
instructions: 'Instructions',
|
|
30
|
+
optional: '(optional)',
|
|
31
|
+
instructionsPlaceholder: 'Enter custom instructions...',
|
|
32
|
+
toneLabel: 'Tone',
|
|
33
|
+
toneOptional: '(optional)',
|
|
34
|
+
toneScholarly: 'Scholarly',
|
|
35
|
+
toneExplanatory: 'Explanatory',
|
|
36
|
+
toneConversational: 'Conversational',
|
|
37
|
+
toneTechnical: 'Technical',
|
|
38
|
+
toneAnalytical: 'Analytical',
|
|
39
|
+
toneCritical: 'Critical',
|
|
40
|
+
toneBalanced: 'Balanced',
|
|
41
|
+
toneConstructive: 'Constructive',
|
|
42
|
+
densityLabel: 'Density',
|
|
43
|
+
densitySparse: 'Sparse',
|
|
44
|
+
densityDense: 'Dense',
|
|
45
|
+
detect: 'Detect',
|
|
46
|
+
};
|
|
47
|
+
return translations[key] || key;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
vi.mock('../../../../contexts/TranslationContext', () => ({
|
|
51
|
+
useTranslations: () => mockT,
|
|
52
|
+
TranslationProvider: ({ children }: { children: React.ReactNode }) => children,
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
describe('DetectSection', () => {
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
vi.clearAllMocks();
|
|
58
|
+
resetEventBusForTesting();
|
|
59
|
+
// Clear localStorage
|
|
60
|
+
if (typeof window !== 'undefined') {
|
|
61
|
+
localStorage.clear();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('Progress Display', () => {
|
|
66
|
+
it('should render progress message when detectionProgress prop provided', () => {
|
|
67
|
+
renderWithProviders(
|
|
68
|
+
<DetectSection
|
|
69
|
+
annotationType="highlight"
|
|
70
|
+
isDetecting={true}
|
|
71
|
+
detectionProgress={{
|
|
72
|
+
status: 'analyzing',
|
|
73
|
+
percentage: 30,
|
|
74
|
+
message: 'Analyzing text for highlights...',
|
|
75
|
+
}}
|
|
76
|
+
/>
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
expect(screen.getByText('Analyzing text for highlights...')).toBeInTheDocument();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should render progress message with sparkle icon', () => {
|
|
83
|
+
renderWithProviders(
|
|
84
|
+
<DetectSection
|
|
85
|
+
annotationType="highlight"
|
|
86
|
+
isDetecting={true}
|
|
87
|
+
detectionProgress={{
|
|
88
|
+
status: 'analyzing',
|
|
89
|
+
message: 'Processing...',
|
|
90
|
+
}}
|
|
91
|
+
/>
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// Check for icon and message
|
|
95
|
+
const progressDiv = screen.getByText('Processing...').closest('.semiont-detection-progress__message');
|
|
96
|
+
expect(progressDiv).toBeInTheDocument();
|
|
97
|
+
expect(progressDiv?.querySelector('.semiont-detection-progress__icon')).toBeInTheDocument();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should render request parameters when provided', () => {
|
|
101
|
+
renderWithProviders(
|
|
102
|
+
<DetectSection
|
|
103
|
+
annotationType="highlight"
|
|
104
|
+
isDetecting={true}
|
|
105
|
+
detectionProgress={{
|
|
106
|
+
status: 'analyzing',
|
|
107
|
+
message: 'Analyzing...',
|
|
108
|
+
requestParams: [
|
|
109
|
+
{ label: 'Instructions', value: 'Find important points' },
|
|
110
|
+
{ label: 'Density', value: '5' },
|
|
111
|
+
],
|
|
112
|
+
}}
|
|
113
|
+
/>
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
expect(screen.getByText('Request Parameters:')).toBeInTheDocument();
|
|
117
|
+
expect(screen.getByText('Find important points')).toBeInTheDocument();
|
|
118
|
+
expect(screen.getByText(/Instructions:/)).toBeInTheDocument();
|
|
119
|
+
expect(screen.getByText('5')).toBeInTheDocument();
|
|
120
|
+
expect(screen.getByText(/Density:/)).toBeInTheDocument();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should hide form when detectionProgress is present', () => {
|
|
124
|
+
renderWithProviders(
|
|
125
|
+
<DetectSection
|
|
126
|
+
annotationType="highlight"
|
|
127
|
+
isDetecting={true}
|
|
128
|
+
detectionProgress={{
|
|
129
|
+
status: 'analyzing',
|
|
130
|
+
message: 'Analyzing...',
|
|
131
|
+
}}
|
|
132
|
+
/>
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// Form should not be visible
|
|
136
|
+
expect(screen.queryByPlaceholderText('Enter custom instructions...')).not.toBeInTheDocument();
|
|
137
|
+
expect(screen.queryByRole('button', { name: /✨ Detect/ })).not.toBeInTheDocument();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should show form when detectionProgress is null', () => {
|
|
141
|
+
renderWithProviders(
|
|
142
|
+
<DetectSection
|
|
143
|
+
annotationType="highlight"
|
|
144
|
+
isDetecting={false}
|
|
145
|
+
detectionProgress={null}
|
|
146
|
+
/>
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
// Form should be visible
|
|
150
|
+
expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
|
|
151
|
+
expect(screen.getByRole('button', { name: /✨ Detect/ })).toBeInTheDocument();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should show form when detectionProgress is undefined', () => {
|
|
155
|
+
renderWithProviders(
|
|
156
|
+
<DetectSection
|
|
157
|
+
annotationType="highlight"
|
|
158
|
+
isDetecting={false}
|
|
159
|
+
detectionProgress={undefined}
|
|
160
|
+
/>
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// Form should be visible
|
|
164
|
+
expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
|
|
165
|
+
expect(screen.getByRole('button', { name: /✨ Detect/ })).toBeInTheDocument();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should keep progress visible after detection completes (isDetecting=false but progress exists)', () => {
|
|
169
|
+
renderWithProviders(
|
|
170
|
+
<DetectSection
|
|
171
|
+
annotationType="highlight"
|
|
172
|
+
isDetecting={false}
|
|
173
|
+
detectionProgress={{
|
|
174
|
+
status: 'complete',
|
|
175
|
+
percentage: 100,
|
|
176
|
+
message: 'Complete! Created 14 highlights',
|
|
177
|
+
}}
|
|
178
|
+
/>
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
// Progress should still be visible
|
|
182
|
+
expect(screen.getByText('Complete! Created 14 highlights')).toBeInTheDocument();
|
|
183
|
+
// Form should NOT be visible
|
|
184
|
+
expect(screen.queryByPlaceholderText('Enter custom instructions...')).not.toBeInTheDocument();
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('Annotation Type Variations', () => {
|
|
189
|
+
it('should render for highlight type', () => {
|
|
190
|
+
renderWithProviders(
|
|
191
|
+
<DetectSection
|
|
192
|
+
annotationType="highlight"
|
|
193
|
+
isDetecting={false}
|
|
194
|
+
detectionProgress={null}
|
|
195
|
+
/>
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
expect(screen.getByText('Detect Highlights')).toBeInTheDocument();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should render for assessment type', () => {
|
|
202
|
+
renderWithProviders(
|
|
203
|
+
<DetectSection
|
|
204
|
+
annotationType="assessment"
|
|
205
|
+
isDetecting={false}
|
|
206
|
+
detectionProgress={null}
|
|
207
|
+
/>
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
expect(screen.getByText('Detect Assessments')).toBeInTheDocument();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('should render for comment type', () => {
|
|
214
|
+
renderWithProviders(
|
|
215
|
+
<DetectSection
|
|
216
|
+
annotationType="comment"
|
|
217
|
+
isDetecting={false}
|
|
218
|
+
detectionProgress={null}
|
|
219
|
+
/>
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
expect(screen.getByText('Detect Comments')).toBeInTheDocument();
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('should show tone selector for comments', () => {
|
|
226
|
+
renderWithProviders(
|
|
227
|
+
<DetectSection
|
|
228
|
+
annotationType="comment"
|
|
229
|
+
isDetecting={false}
|
|
230
|
+
detectionProgress={null}
|
|
231
|
+
/>
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
expect(screen.getByText('Scholarly')).toBeInTheDocument();
|
|
235
|
+
expect(screen.getByText('Explanatory')).toBeInTheDocument();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should show tone selector for assessments', () => {
|
|
239
|
+
renderWithProviders(
|
|
240
|
+
<DetectSection
|
|
241
|
+
annotationType="assessment"
|
|
242
|
+
isDetecting={false}
|
|
243
|
+
detectionProgress={null}
|
|
244
|
+
/>
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
expect(screen.getByText('Analytical')).toBeInTheDocument();
|
|
248
|
+
expect(screen.getByText('Critical')).toBeInTheDocument();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('should not show tone selector for highlights', () => {
|
|
252
|
+
renderWithProviders(
|
|
253
|
+
<DetectSection
|
|
254
|
+
annotationType="highlight"
|
|
255
|
+
isDetecting={false}
|
|
256
|
+
detectionProgress={null}
|
|
257
|
+
/>
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
expect(screen.queryByText('Scholarly')).not.toBeInTheDocument();
|
|
261
|
+
expect(screen.queryByText('Analytical')).not.toBeInTheDocument();
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
describe('Event Emission', () => {
|
|
266
|
+
it('should emit detection:start event when detect button clicked', async () => {
|
|
267
|
+
const user = userEvent.setup();
|
|
268
|
+
const detectionHandler = vi.fn();
|
|
269
|
+
|
|
270
|
+
const { eventBus } = renderWithProviders(
|
|
271
|
+
<DetectSection
|
|
272
|
+
annotationType="highlight"
|
|
273
|
+
isDetecting={false}
|
|
274
|
+
detectionProgress={null}
|
|
275
|
+
/>,
|
|
276
|
+
{ returnEventBus: true }
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
eventBus!.on('detection:start', detectionHandler);
|
|
280
|
+
|
|
281
|
+
const detectButton = screen.getByRole('button', { name: /✨ Detect/ });
|
|
282
|
+
await user.click(detectButton);
|
|
283
|
+
|
|
284
|
+
expect(detectionHandler).toHaveBeenCalledWith({
|
|
285
|
+
motivation: 'highlighting',
|
|
286
|
+
options: expect.any(Object),
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
eventBus!.off('detection:start', detectionHandler);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('should emit correct motivation for assessment type', async () => {
|
|
293
|
+
const user = userEvent.setup();
|
|
294
|
+
const detectionHandler = vi.fn();
|
|
295
|
+
|
|
296
|
+
const { eventBus } = renderWithProviders(
|
|
297
|
+
<DetectSection
|
|
298
|
+
annotationType="assessment"
|
|
299
|
+
isDetecting={false}
|
|
300
|
+
detectionProgress={null}
|
|
301
|
+
/>,
|
|
302
|
+
{ returnEventBus: true }
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
eventBus!.on('detection:start', detectionHandler);
|
|
306
|
+
|
|
307
|
+
const detectButton = screen.getByRole('button', { name: /✨ Detect/ });
|
|
308
|
+
await user.click(detectButton);
|
|
309
|
+
|
|
310
|
+
expect(detectionHandler).toHaveBeenCalledWith({
|
|
311
|
+
motivation: 'assessing',
|
|
312
|
+
options: expect.any(Object),
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
eventBus!.off('detection:start', detectionHandler);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('should emit correct motivation for comment type', async () => {
|
|
319
|
+
const user = userEvent.setup();
|
|
320
|
+
const detectionHandler = vi.fn();
|
|
321
|
+
|
|
322
|
+
const { eventBus } = renderWithProviders(
|
|
323
|
+
<DetectSection
|
|
324
|
+
annotationType="comment"
|
|
325
|
+
isDetecting={false}
|
|
326
|
+
detectionProgress={null}
|
|
327
|
+
/>,
|
|
328
|
+
{ returnEventBus: true }
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
eventBus!.on('detection:start', detectionHandler);
|
|
332
|
+
|
|
333
|
+
const detectButton = screen.getByRole('button', { name: /✨ Detect/ });
|
|
334
|
+
await user.click(detectButton);
|
|
335
|
+
|
|
336
|
+
expect(detectionHandler).toHaveBeenCalledWith({
|
|
337
|
+
motivation: 'commenting',
|
|
338
|
+
options: expect.any(Object),
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
eventBus!.off('detection:start', detectionHandler);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
it('should include instructions in event when provided', async () => {
|
|
345
|
+
const user = userEvent.setup();
|
|
346
|
+
const detectionHandler = vi.fn();
|
|
347
|
+
|
|
348
|
+
const { eventBus } = renderWithProviders(
|
|
349
|
+
<DetectSection
|
|
350
|
+
annotationType="highlight"
|
|
351
|
+
isDetecting={false}
|
|
352
|
+
detectionProgress={null}
|
|
353
|
+
/>,
|
|
354
|
+
{ returnEventBus: true }
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
eventBus!.on('detection:start', detectionHandler);
|
|
358
|
+
|
|
359
|
+
const textarea = screen.getByPlaceholderText('Enter custom instructions...');
|
|
360
|
+
await user.type(textarea, 'Find key concepts');
|
|
361
|
+
|
|
362
|
+
const detectButton = screen.getByRole('button', { name: /✨ Detect/ });
|
|
363
|
+
await user.click(detectButton);
|
|
364
|
+
|
|
365
|
+
expect(detectionHandler).toHaveBeenCalledWith({
|
|
366
|
+
motivation: 'highlighting',
|
|
367
|
+
options: {
|
|
368
|
+
instructions: 'Find key concepts',
|
|
369
|
+
density: expect.any(Number),
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
eventBus!.off('detection:start', detectionHandler);
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
describe('Collapsible Behavior', () => {
|
|
378
|
+
it('should be expanded by default', () => {
|
|
379
|
+
renderWithProviders(
|
|
380
|
+
<DetectSection
|
|
381
|
+
annotationType="highlight"
|
|
382
|
+
isDetecting={false}
|
|
383
|
+
detectionProgress={null}
|
|
384
|
+
/>
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
const collapseButton = screen.getByRole('button', { name: /Detect Highlights/ });
|
|
388
|
+
expect(collapseButton).toHaveAttribute('aria-expanded', 'true');
|
|
389
|
+
expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it('should collapse when title clicked', async () => {
|
|
393
|
+
const user = userEvent.setup();
|
|
394
|
+
|
|
395
|
+
renderWithProviders(
|
|
396
|
+
<DetectSection
|
|
397
|
+
annotationType="highlight"
|
|
398
|
+
isDetecting={false}
|
|
399
|
+
detectionProgress={null}
|
|
400
|
+
/>
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
const collapseButton = screen.getByRole('button', { name: /Detect Highlights/ });
|
|
404
|
+
await user.click(collapseButton);
|
|
405
|
+
|
|
406
|
+
expect(collapseButton).toHaveAttribute('aria-expanded', 'false');
|
|
407
|
+
expect(screen.queryByPlaceholderText('Enter custom instructions...')).not.toBeInTheDocument();
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it('should expand when title clicked again', async () => {
|
|
411
|
+
const user = userEvent.setup();
|
|
412
|
+
|
|
413
|
+
renderWithProviders(
|
|
414
|
+
<DetectSection
|
|
415
|
+
annotationType="highlight"
|
|
416
|
+
isDetecting={false}
|
|
417
|
+
detectionProgress={null}
|
|
418
|
+
/>
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
const collapseButton = screen.getByRole('button', { name: /Detect Highlights/ });
|
|
422
|
+
await user.click(collapseButton); // Collapse
|
|
423
|
+
await user.click(collapseButton); // Expand
|
|
424
|
+
|
|
425
|
+
expect(collapseButton).toHaveAttribute('aria-expanded', 'true');
|
|
426
|
+
expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
describe('Edge Cases', () => {
|
|
431
|
+
it('should handle empty progress message', () => {
|
|
432
|
+
renderWithProviders(
|
|
433
|
+
<DetectSection
|
|
434
|
+
annotationType="highlight"
|
|
435
|
+
isDetecting={true}
|
|
436
|
+
detectionProgress={{
|
|
437
|
+
status: 'analyzing',
|
|
438
|
+
message: '',
|
|
439
|
+
}}
|
|
440
|
+
/>
|
|
441
|
+
);
|
|
442
|
+
|
|
443
|
+
// Should render progress section even with empty message
|
|
444
|
+
const progressDiv = document.querySelector('.semiont-detection-progress');
|
|
445
|
+
expect(progressDiv).toBeInTheDocument();
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
it('should handle progress without percentage', () => {
|
|
449
|
+
renderWithProviders(
|
|
450
|
+
<DetectSection
|
|
451
|
+
annotationType="highlight"
|
|
452
|
+
isDetecting={true}
|
|
453
|
+
detectionProgress={{
|
|
454
|
+
status: 'analyzing',
|
|
455
|
+
message: 'Processing...',
|
|
456
|
+
// no percentage
|
|
457
|
+
}}
|
|
458
|
+
/>
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
expect(screen.getByText('Processing...')).toBeInTheDocument();
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
it('should handle progress with empty requestParams array', () => {
|
|
465
|
+
renderWithProviders(
|
|
466
|
+
<DetectSection
|
|
467
|
+
annotationType="highlight"
|
|
468
|
+
isDetecting={true}
|
|
469
|
+
detectionProgress={{
|
|
470
|
+
status: 'analyzing',
|
|
471
|
+
message: 'Processing...',
|
|
472
|
+
requestParams: [],
|
|
473
|
+
}}
|
|
474
|
+
/>
|
|
475
|
+
);
|
|
476
|
+
|
|
477
|
+
expect(screen.queryByText('Request Parameters:')).not.toBeInTheDocument();
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
});
|