@semiont/react-ui 0.5.5 → 0.5.6
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 +59 -55
- package/dist/{PdfAnnotationCanvas.client-CN3C3S55.js → PdfAnnotationCanvas.client-NIMALXNZ.js} +7 -27
- package/dist/PdfAnnotationCanvas.client-NIMALXNZ.js.map +1 -0
- package/dist/index.css +6 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +243 -99
- package/dist/index.js +539 -405
- package/dist/index.js.map +1 -1
- package/package.json +16 -12
- package/src/components/Button/__tests__/Button.test.tsx +0 -2
- package/src/components/CodeMirrorRenderer.tsx +2 -0
- package/src/components/ErrorBoundary.tsx +0 -9
- package/src/components/ProtectedErrorBoundary.tsx +6 -2
- package/src/components/__tests__/AnnotateReferencesProgressWidget.test.tsx +0 -1
- package/src/components/__tests__/ErrorBoundary.test.tsx +20 -13
- package/src/components/__tests__/LiveRegion.hooks.test.tsx +1 -1
- package/src/components/__tests__/ProtectedErrorBoundary.test.tsx +2 -1
- package/src/components/__tests__/ResizeHandle.test.tsx +0 -1
- package/src/components/__tests__/SessionExpiryBanner.test.tsx +0 -1
- package/src/components/__tests__/StatusDisplay.test.tsx +0 -1
- package/src/components/__tests__/Toast.test.tsx +2 -3
- package/src/components/__tests__/Toolbar.test.tsx +0 -1
- package/src/components/annotation/annotations.css +14 -0
- package/src/components/annotation-popups/__tests__/JsonLdView.test.tsx +3 -5
- package/src/components/annotation-popups/__tests__/SharedPopupElements.test.tsx +0 -1
- package/src/components/branding/__tests__/SemiontBranding.test.tsx +1 -2
- package/src/components/layout/__tests__/LeftSidebar.test.tsx +5 -6
- package/src/components/layout/__tests__/PageLayout.test.tsx +1 -3
- package/src/components/layout/__tests__/SkipLinks.a11y.test.tsx +8 -8
- package/src/components/layout/__tests__/UnifiedHeader.test.tsx +12 -1
- package/src/components/modals/__tests__/KeyboardShortcutsHelpModal.test.tsx +0 -1
- package/src/components/modals/__tests__/PermissionDeniedModal.test.tsx +3 -4
- package/src/components/modals/__tests__/ResourceSearchModal.test.tsx +0 -1
- package/src/components/modals/__tests__/SearchModal.basic.test.tsx +1 -1
- package/src/components/modals/__tests__/SearchModal.keyboard.test.tsx +0 -5
- package/src/components/modals/__tests__/SearchModal.search-wiring.test.tsx +0 -1
- package/src/components/modals/__tests__/SearchModal.visual.test.tsx +2 -2
- package/src/components/modals/__tests__/SessionExpiredModal.test.tsx +0 -1
- package/src/components/navigation/NavigationMenu.tsx +1 -1
- package/src/components/navigation/__tests__/Footer.a11y.test.tsx +4 -0
- package/src/components/navigation/__tests__/Footer.test.tsx +3 -6
- package/src/components/navigation/__tests__/NavigationMenu.a11y.test.tsx +1 -1
- package/src/components/navigation/__tests__/NavigationMenu.test.tsx +7 -9
- package/src/components/navigation/__tests__/ObservableLink.test.tsx +0 -1
- package/src/components/navigation/__tests__/SimpleNavigation.test.tsx +1 -2
- package/src/components/navigation/__tests__/SortableResourceTab.test.tsx +0 -1
- package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +6 -4
- package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +10 -19
- package/src/components/resource/__tests__/BrowseView.test.tsx +8 -6
- package/src/components/resource/__tests__/HistoryEvent.test.tsx +0 -4
- package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +4 -6
- package/src/components/resource/panels/ReferencesPanel.tsx +1 -1
- package/src/components/resource/panels/__tests__/AssessmentEntry.test.tsx +3 -4
- package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +7 -6
- package/src/components/resource/panels/__tests__/AssistSection.test.tsx +14 -10
- package/src/components/resource/panels/__tests__/CollaborationPanel.test.tsx +0 -1
- package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +30 -17
- package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +6 -5
- package/src/components/resource/panels/__tests__/HighlightEntry.test.tsx +4 -5
- package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +19 -13
- package/src/components/resource/panels/__tests__/JsonLdPanel.test.tsx +1 -3
- package/src/components/resource/panels/__tests__/PanelHeader.test.tsx +0 -1
- package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +5 -5
- package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +40 -7
- package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +3 -3
- package/src/components/resource/panels/__tests__/StatisticsPanel.test.tsx +30 -32
- package/src/components/resource/panels/__tests__/TagEntry.test.tsx +5 -5
- package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +6 -5
- package/src/components/settings/__tests__/SettingsPanel.test.tsx +0 -1
- package/src/components/viewers/__tests__/ImageViewer.test.tsx +0 -1
- package/src/features/auth/__tests__/SignInForm.a11y.test.tsx +2 -0
- package/src/features/auth/__tests__/SignUpForm.a11y.test.tsx +11 -12
- package/src/features/auth/__tests__/SignUpForm.test.tsx +3 -3
- package/src/features/moderate-tag-schemas/components/TagSchemasPage.tsx +1 -0
- package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +2 -1
- package/src/features/resource-discovery/__tests__/ResourceCard.test.tsx +0 -1
- package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +33 -35
- package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +12 -11
- package/src/features/resource-discovery/state/__tests__/discover-state-unit.test.ts +204 -11
- package/src/features/resource-discovery/state/discover-state-unit.ts +70 -11
- package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +2 -2
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +3 -2
- package/src/features/resource-viewer/state/__tests__/resource-viewer-page-state-unit.test.ts +0 -1
- package/src/features/resource-viewer/state/resource-viewer-page-state-unit.ts +5 -2
- package/src/integrations/__tests__/css-modules-helper.test.tsx +2 -3
- package/src/integrations/__tests__/styled-components-theme.test.ts +1 -3
- package/dist/PdfAnnotationCanvas.client-CN3C3S55.js.map +0 -1
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
15
|
-
import React from 'react';
|
|
16
15
|
import { screen, fireEvent, waitFor, act } from '@testing-library/react';
|
|
17
16
|
import { BehaviorSubject } from 'rxjs';
|
|
18
17
|
import { renderWithProviders } from '../../../test-utils';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
6
|
-
import { render, screen, fireEvent
|
|
6
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
7
7
|
import { SearchModal } from '../SearchModal';
|
|
8
8
|
|
|
9
9
|
// Mock the hooks
|
|
@@ -102,7 +102,7 @@ describe.skip('SearchModal Component - Visual States', () => {
|
|
|
102
102
|
rerender(<SearchModal {...defaultProps} isOpen={false} />);
|
|
103
103
|
rerender(<SearchModal {...defaultProps} isOpen={true} />);
|
|
104
104
|
|
|
105
|
-
const input = screen.getByPlaceholderText('Search resources, entities...');
|
|
105
|
+
const input = screen.getByPlaceholderText<HTMLInputElement>('Search resources, entities...');
|
|
106
106
|
expect(input).toBeInTheDocument();
|
|
107
107
|
expect(input.value).toBe('');
|
|
108
108
|
});
|
|
@@ -8,7 +8,7 @@ type TranslateFn = (key: string, params?: Record<string, any>) => string;
|
|
|
8
8
|
|
|
9
9
|
interface NavigationMenuProps {
|
|
10
10
|
Link: React.ComponentType<LinkComponentProps>;
|
|
11
|
-
routes: RouteBuilder
|
|
11
|
+
routes: Partial<RouteBuilder>;
|
|
12
12
|
t: TranslateFn;
|
|
13
13
|
isAdmin?: boolean;
|
|
14
14
|
isModerator?: boolean;
|
|
@@ -21,6 +21,10 @@ describe('Footer - Accessibility', () => {
|
|
|
21
21
|
));
|
|
22
22
|
|
|
23
23
|
const mockRoutes = {
|
|
24
|
+
resourceDetail: vi.fn((id: string) => `/resource/${id}`),
|
|
25
|
+
userProfile: vi.fn((id: string) => `/user/${id}`),
|
|
26
|
+
search: vi.fn((query: string) => `/search?q=${query}`),
|
|
27
|
+
home: vi.fn(() => '/'),
|
|
24
28
|
about: vi.fn(() => '/about'),
|
|
25
29
|
privacy: vi.fn(() => '/privacy'),
|
|
26
30
|
terms: vi.fn(() => '/terms'),
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import React from 'react';
|
|
3
2
|
import { render, screen, fireEvent } from '@testing-library/react';
|
|
4
3
|
import '@testing-library/jest-dom';
|
|
5
4
|
import { Footer } from '../Footer';
|
|
@@ -124,7 +123,7 @@ describe('Footer Component', () => {
|
|
|
124
123
|
});
|
|
125
124
|
|
|
126
125
|
it('should render Cookie Preferences button when provided', () => {
|
|
127
|
-
const MockCookiePrefs = ({
|
|
126
|
+
const MockCookiePrefs = ({ }: any) => null;
|
|
128
127
|
|
|
129
128
|
render(
|
|
130
129
|
<Footer
|
|
@@ -139,7 +138,7 @@ describe('Footer Component', () => {
|
|
|
139
138
|
});
|
|
140
139
|
|
|
141
140
|
it('should open Cookie Preferences modal when button clicked', () => {
|
|
142
|
-
const MockCookiePrefs = ({ isOpen
|
|
141
|
+
const MockCookiePrefs = ({ isOpen }: any) => (
|
|
143
142
|
isOpen ? <div data-testid="cookie-modal">Cookie Preferences</div> : null
|
|
144
143
|
);
|
|
145
144
|
|
|
@@ -161,9 +160,7 @@ describe('Footer Component', () => {
|
|
|
161
160
|
});
|
|
162
161
|
|
|
163
162
|
it('should close Cookie Preferences modal when onClose called', () => {
|
|
164
|
-
let closeHandler: (() => void) | null = null;
|
|
165
163
|
const MockCookiePrefs = ({ isOpen, onClose }: any) => {
|
|
166
|
-
closeHandler = onClose;
|
|
167
164
|
return isOpen ? (
|
|
168
165
|
<div data-testid="cookie-modal">
|
|
169
166
|
<button onClick={onClose}>Close</button>
|
|
@@ -387,7 +384,7 @@ describe('Footer Component', () => {
|
|
|
387
384
|
|
|
388
385
|
it('should have proper button elements for interactive features', () => {
|
|
389
386
|
const mockHandler = vi.fn();
|
|
390
|
-
const MockCookiePrefs = ({
|
|
387
|
+
const MockCookiePrefs = ({ }: any) => null;
|
|
391
388
|
|
|
392
389
|
render(
|
|
393
390
|
<Footer
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import React from 'react';
|
|
3
2
|
import { render, screen, fireEvent } from '@testing-library/react';
|
|
4
3
|
import '@testing-library/jest-dom';
|
|
5
4
|
import { NavigationMenu } from '../NavigationMenu';
|
|
@@ -287,14 +286,13 @@ describe('NavigationMenu Component', () => {
|
|
|
287
286
|
});
|
|
288
287
|
|
|
289
288
|
it('should not show extra divider after admin link', () => {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
);
|
|
289
|
+
render(
|
|
290
|
+
<NavigationMenu
|
|
291
|
+
Link={mockLink}
|
|
292
|
+
routes={mockRoutes}
|
|
293
|
+
t={mockTranslate}
|
|
294
|
+
isAdmin={true} />
|
|
295
|
+
);
|
|
298
296
|
|
|
299
297
|
const adminLink = screen.getByText('Administer').closest('a');
|
|
300
298
|
const nextSibling = adminLink?.nextElementSibling;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import React from 'react';
|
|
3
2
|
import { screen, fireEvent } from '@testing-library/react';
|
|
4
3
|
import '@testing-library/jest-dom';
|
|
5
4
|
import { renderWithProviders } from '../../../test-utils';
|
|
@@ -143,7 +142,7 @@ describe('SimpleNavigation', () => {
|
|
|
143
142
|
});
|
|
144
143
|
|
|
145
144
|
it('closes dropdown on outside click', () => {
|
|
146
|
-
const dropdownContent = (
|
|
145
|
+
const dropdownContent = () => (
|
|
147
146
|
<div data-testid="dropdown-content">Dropdown</div>
|
|
148
147
|
);
|
|
149
148
|
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { useRef, useState, useCallback, useEffect, useMemo } from 'react';
|
|
4
4
|
import type { Annotation } from '@semiont/core';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
getTargetSelector,
|
|
7
|
+
createFragmentSelector,
|
|
8
|
+
parseFragmentSelector,
|
|
9
|
+
getPageFromFragment,
|
|
10
|
+
} from '@semiont/core';
|
|
6
11
|
import { createHoverHandlers, type SemiontSession } from '@semiont/sdk';
|
|
7
12
|
import type { SelectionMotivation } from '../annotation/AnnotateToolbar';
|
|
8
13
|
import {
|
|
9
14
|
canvasToPdfCoordinates,
|
|
10
15
|
pdfToCanvasCoordinates,
|
|
11
|
-
createFragmentSelector,
|
|
12
|
-
parseFragmentSelector,
|
|
13
|
-
getPageFromFragment,
|
|
14
16
|
type CanvasRectangle
|
|
15
17
|
} from '../../lib/pdf-coordinates';
|
|
16
18
|
import {
|
|
@@ -11,8 +11,7 @@ import { describe, test, expect, vi, beforeEach } from 'vitest';
|
|
|
11
11
|
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
|
|
12
12
|
import userEvent from '@testing-library/user-event';
|
|
13
13
|
import { PdfAnnotationCanvas } from '../PdfAnnotationCanvas';
|
|
14
|
-
import { resourceId } from '@semiont/core';
|
|
15
|
-
import type { components } from '@semiont/core';
|
|
14
|
+
import { resourceId, annotationId } from '@semiont/core';
|
|
16
15
|
|
|
17
16
|
import type { Annotation } from '@semiont/core';
|
|
18
17
|
|
|
@@ -41,6 +40,7 @@ vi.mock('../../../lib/browser-pdfjs', () => ({
|
|
|
41
40
|
|
|
42
41
|
describe('PdfAnnotationCanvas', () => {
|
|
43
42
|
const mockResourceId = resourceId('123');
|
|
43
|
+
const mockPdfUrl = 'https://example.com/resources/123.pdf';
|
|
44
44
|
|
|
45
45
|
beforeEach(() => {
|
|
46
46
|
vi.clearAllMocks();
|
|
@@ -57,7 +57,7 @@ describe('PdfAnnotationCanvas', () => {
|
|
|
57
57
|
test('renders loading state initially', () => {
|
|
58
58
|
render(
|
|
59
59
|
<PdfAnnotationCanvas
|
|
60
|
-
|
|
60
|
+
pdfUrl={mockPdfUrl}
|
|
61
61
|
drawingMode={null}
|
|
62
62
|
/>
|
|
63
63
|
);
|
|
@@ -68,7 +68,7 @@ describe('PdfAnnotationCanvas', () => {
|
|
|
68
68
|
test('renders page navigation controls after loading', async () => {
|
|
69
69
|
render(
|
|
70
70
|
<PdfAnnotationCanvas
|
|
71
|
-
|
|
71
|
+
pdfUrl={mockPdfUrl}
|
|
72
72
|
drawingMode={null}
|
|
73
73
|
/>
|
|
74
74
|
);
|
|
@@ -84,7 +84,7 @@ describe('PdfAnnotationCanvas', () => {
|
|
|
84
84
|
test('previous button is disabled on first page', async () => {
|
|
85
85
|
render(
|
|
86
86
|
<PdfAnnotationCanvas
|
|
87
|
-
|
|
87
|
+
pdfUrl={mockPdfUrl}
|
|
88
88
|
drawingMode={null}
|
|
89
89
|
/>
|
|
90
90
|
);
|
|
@@ -100,7 +100,7 @@ describe('PdfAnnotationCanvas', () => {
|
|
|
100
100
|
test('next button is disabled on last page', async () => {
|
|
101
101
|
render(
|
|
102
102
|
<PdfAnnotationCanvas
|
|
103
|
-
|
|
103
|
+
pdfUrl={mockPdfUrl}
|
|
104
104
|
drawingMode={null}
|
|
105
105
|
/>
|
|
106
106
|
);
|
|
@@ -129,7 +129,7 @@ describe('PdfAnnotationCanvas', () => {
|
|
|
129
129
|
{
|
|
130
130
|
'@context': 'http://www.w3.org/ns/anno.jsonld',
|
|
131
131
|
type: 'Annotation',
|
|
132
|
-
id: 'ann-1',
|
|
132
|
+
id: annotationId('ann-1'),
|
|
133
133
|
target: {
|
|
134
134
|
source: mockResourceId,
|
|
135
135
|
selector: {
|
|
@@ -145,7 +145,7 @@ describe('PdfAnnotationCanvas', () => {
|
|
|
145
145
|
|
|
146
146
|
render(
|
|
147
147
|
<PdfAnnotationCanvas
|
|
148
|
-
|
|
148
|
+
pdfUrl={mockPdfUrl}
|
|
149
149
|
existingAnnotations={mockAnnotations}
|
|
150
150
|
drawingMode={null}
|
|
151
151
|
/>
|
|
@@ -177,21 +177,12 @@ describe('PdfAnnotationCanvas', () => {
|
|
|
177
177
|
});
|
|
178
178
|
});
|
|
179
179
|
|
|
180
|
-
test('
|
|
181
|
-
const mockSubject = { next: vi.fn(), subscribe: vi.fn() };
|
|
182
|
-
const mockEventBus = {
|
|
183
|
-
emit: vi.fn(),
|
|
184
|
-
on: vi.fn(),
|
|
185
|
-
off: vi.fn(),
|
|
186
|
-
get: vi.fn().mockReturnValue(mockSubject),
|
|
187
|
-
};
|
|
188
|
-
|
|
180
|
+
test('accepts a drawing gesture without throwing when drawing mode is active', async () => {
|
|
189
181
|
render(
|
|
190
182
|
<PdfAnnotationCanvas
|
|
191
|
-
|
|
183
|
+
pdfUrl={mockPdfUrl}
|
|
192
184
|
drawingMode="rectangle"
|
|
193
185
|
selectedMotivation="highlighting"
|
|
194
|
-
eventBus={mockEventBus as any}
|
|
195
186
|
/>
|
|
196
187
|
);
|
|
197
188
|
|
|
@@ -2,10 +2,10 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
4
4
|
import { BrowseView } from '../BrowseView';
|
|
5
|
-
import type {
|
|
5
|
+
import type { EventBus } from '@semiont/core';
|
|
6
6
|
import { createTestSemiontWrapper } from '../../../test-utils';
|
|
7
7
|
|
|
8
|
-
import type { Annotation } from '@semiont/core';
|
|
8
|
+
import type { Annotation, AnnotationId } from '@semiont/core';
|
|
9
9
|
|
|
10
10
|
// Mock ResourceAnnotationsContext - keep this simple
|
|
11
11
|
let mockNewAnnotationIds = new Set<string>();
|
|
@@ -151,12 +151,12 @@ const renderWithEventTracking = (
|
|
|
151
151
|
};
|
|
152
152
|
|
|
153
153
|
// Test data fixtures
|
|
154
|
-
const createMockAnnotation = (motivation:
|
|
154
|
+
const createMockAnnotation = (motivation: Annotation['motivation'], id: string): Annotation => ({
|
|
155
155
|
'@context': 'http://www.w3.org/ns/anno.jsonld',
|
|
156
|
-
id,
|
|
156
|
+
id: id as AnnotationId,
|
|
157
157
|
type: 'Annotation',
|
|
158
158
|
motivation,
|
|
159
|
-
creator: { name: 'user@example.com' },
|
|
159
|
+
creator: { '@type': 'Person', name: 'user@example.com' },
|
|
160
160
|
created: '2024-01-01T10:00:00Z',
|
|
161
161
|
target: {
|
|
162
162
|
source: 'resource-1',
|
|
@@ -197,7 +197,9 @@ describe('BrowseView Component', () => {
|
|
|
197
197
|
// Mock querySelector and querySelectorAll
|
|
198
198
|
if (typeof document !== 'undefined') {
|
|
199
199
|
document.querySelector = vi.fn();
|
|
200
|
-
|
|
200
|
+
// Return a real (empty) NodeList so the mock matches the DOM signature.
|
|
201
|
+
const emptyNodeList = document.createDocumentFragment().querySelectorAll('*');
|
|
202
|
+
document.querySelectorAll = vi.fn(() => emptyNodeList);
|
|
201
203
|
}
|
|
202
204
|
});
|
|
203
205
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import React from 'react';
|
|
3
2
|
import { screen, fireEvent, act } from '@testing-library/react';
|
|
4
3
|
import '@testing-library/jest-dom';
|
|
5
4
|
import { HistoryEvent } from '../HistoryEvent';
|
|
6
5
|
import { renderWithProviders } from '../../../test-utils';
|
|
7
|
-
import type { StoredEvent } from '@semiont/core';
|
|
8
6
|
|
|
9
7
|
// Mock @semiont/core - must use importOriginal to preserve EventBus etc.
|
|
10
8
|
vi.mock('@semiont/core', async (importOriginal) => {
|
|
@@ -37,8 +35,6 @@ vi.mock('../event-formatting', () => ({
|
|
|
37
35
|
import { getAnnotationUriFromEvent } from '@semiont/core';
|
|
38
36
|
import {
|
|
39
37
|
formatEventType,
|
|
40
|
-
getEventEmoji,
|
|
41
|
-
formatRelativeTime,
|
|
42
38
|
getEventDisplayContent,
|
|
43
39
|
getEventEntityTypes,
|
|
44
40
|
getResourceCreationDetails,
|
|
@@ -11,15 +11,13 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
14
|
-
import { render, screen
|
|
14
|
+
import { render, screen } from '@testing-library/react';
|
|
15
15
|
import { BehaviorSubject } from 'rxjs';
|
|
16
16
|
import { ResourceViewer } from '../ResourceViewer';
|
|
17
17
|
import { createTestSemiontWrapper } from '../../../test-utils';
|
|
18
18
|
import { TranslationProvider } from '../../../contexts/TranslationContext';
|
|
19
19
|
import { ResourceAnnotationsProvider } from '../../../contexts/ResourceAnnotationsContext';
|
|
20
|
-
import type {
|
|
21
|
-
|
|
22
|
-
type SemiontResource = components['schemas']['ResourceDescriptor'];
|
|
20
|
+
import type { ResourceDescriptor as SemiontResource, ResourceId } from '@semiont/core';
|
|
23
21
|
|
|
24
22
|
// Mock dependencies
|
|
25
23
|
vi.mock('../../../hooks/useObservableBrowse', () => ({
|
|
@@ -61,7 +59,7 @@ vi.mock('../../../session/SemiontProvider', async () => {
|
|
|
61
59
|
|
|
62
60
|
const mockResource: SemiontResource & { content: string } = {
|
|
63
61
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
|
64
|
-
'@id': 'test-123',
|
|
62
|
+
'@id': 'test-123' as ResourceId,
|
|
65
63
|
name: 'Test Document',
|
|
66
64
|
created: '2024-01-01T00:00:00Z',
|
|
67
65
|
entityTypes: [],
|
|
@@ -84,7 +82,7 @@ const mockAnnotations = {
|
|
|
84
82
|
};
|
|
85
83
|
|
|
86
84
|
const mockTranslationManager = {
|
|
87
|
-
t: (namespace: string, key: string
|
|
85
|
+
t: (namespace: string, key: string) => {
|
|
88
86
|
return `${namespace}.${key}`;
|
|
89
87
|
},
|
|
90
88
|
};
|
|
@@ -236,7 +236,7 @@ export function ReferencesPanel({
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
// When annotation is complete and we haven't saved yet, save the log
|
|
239
|
-
if (!
|
|
239
|
+
if (!hasSavedLogRef.current && progress?.completedEntityTypes) {
|
|
240
240
|
hasSavedLogRef.current = true;
|
|
241
241
|
setLastDetectionLog(progress.completedEntityTypes);
|
|
242
242
|
setSelectedEntityTypes([]);
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
-
import React from 'react';
|
|
3
2
|
import { screen } from '@testing-library/react';
|
|
4
3
|
import '@testing-library/jest-dom';
|
|
5
4
|
import { renderWithProviders } from '../../../../test-utils';
|
|
6
5
|
import userEvent from '@testing-library/user-event';
|
|
7
|
-
import type { components } from '@semiont/core';
|
|
8
6
|
|
|
9
|
-
import type { Annotation } from '@semiont/core';
|
|
7
|
+
import type { Annotation, AnnotationId } from '@semiont/core';
|
|
10
8
|
|
|
11
9
|
// Mock @semiont/api-client
|
|
12
10
|
vi.mock('@semiont/core', async () => {
|
|
@@ -25,10 +23,11 @@ const mockGetAnnotationExactText = getAnnotationExactText as MockedFunction<type
|
|
|
25
23
|
|
|
26
24
|
const createMockAssessment = (overrides?: Partial<Annotation>): Annotation => ({
|
|
27
25
|
'@context': 'http://www.w3.org/ns/anno.jsonld',
|
|
28
|
-
id: 'assessment-1',
|
|
26
|
+
id: 'assessment-1' as AnnotationId,
|
|
29
27
|
type: 'Annotation',
|
|
30
28
|
motivation: 'assessing',
|
|
31
29
|
creator: {
|
|
30
|
+
'@type': 'Person',
|
|
32
31
|
name: 'reviewer@example.com',
|
|
33
32
|
},
|
|
34
33
|
created: '2024-06-15T12:00:00Z',
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
2
|
import type { MockedFunction } from 'vitest';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import { render, screen,
|
|
4
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
5
5
|
import userEvent from '@testing-library/user-event';
|
|
6
6
|
import '@testing-library/jest-dom';
|
|
7
7
|
import { AssessmentPanel } from '../AssessmentPanel';
|
|
8
|
-
import type {
|
|
8
|
+
import type { EventBus } from '@semiont/core';
|
|
9
9
|
import { createTestSemiontWrapper } from '../../../../test-utils';
|
|
10
10
|
|
|
11
|
-
import type { Annotation } from '@semiont/core';
|
|
11
|
+
import type { Annotation, AnnotationId } from '@semiont/core';
|
|
12
12
|
|
|
13
13
|
// Composition-based event tracker
|
|
14
14
|
interface TrackedEvent {
|
|
@@ -69,7 +69,7 @@ vi.mock('@semiont/core', async () => {
|
|
|
69
69
|
|
|
70
70
|
// Mock AssessmentEntry component to simplify testing
|
|
71
71
|
vi.mock('../AssessmentEntry', () => ({
|
|
72
|
-
AssessmentEntry: ({ assessment
|
|
72
|
+
AssessmentEntry: ({ assessment }: any) => (
|
|
73
73
|
<div data-testid={`assessment-${assessment.id}`}>
|
|
74
74
|
<div>{assessment.id}</div>
|
|
75
75
|
</div>
|
|
@@ -78,7 +78,7 @@ vi.mock('../AssessmentEntry', () => ({
|
|
|
78
78
|
|
|
79
79
|
// Mock AssistSection component — just render a simplified version.
|
|
80
80
|
vi.mock('../AssistSection', () => ({
|
|
81
|
-
AssistSection: ({
|
|
81
|
+
AssistSection: ({ isAssisting }: any) => (
|
|
82
82
|
<div data-testid="detect-section">
|
|
83
83
|
<button>Start Detection</button>
|
|
84
84
|
{isAssisting && <div>Detecting...</div>}
|
|
@@ -93,10 +93,11 @@ const mockGetTargetSelector = getTargetSelector as MockedFunction<typeof getTarg
|
|
|
93
93
|
// Test data fixtures
|
|
94
94
|
const createMockAssessment = (id: string, start: number, end: number): Annotation => ({
|
|
95
95
|
'@context': 'http://www.w3.org/ns/anno.jsonld',
|
|
96
|
-
id,
|
|
96
|
+
id: id as AnnotationId,
|
|
97
97
|
type: 'Annotation',
|
|
98
98
|
motivation: 'assessing',
|
|
99
99
|
creator: {
|
|
100
|
+
'@type': 'Person',
|
|
100
101
|
name: `user${id}@example.com`,
|
|
101
102
|
},
|
|
102
103
|
created: `2024-01-0${id.slice(-1)}T10:00:00Z`,
|
|
@@ -17,7 +17,6 @@ import { screen } from '@testing-library/react';
|
|
|
17
17
|
import { renderWithProviders } from '../../../../test-utils';
|
|
18
18
|
import userEvent from '@testing-library/user-event';
|
|
19
19
|
import { AssistSection } from '../AssistSection';
|
|
20
|
-
import type { EventBus } from "@semiont/core"
|
|
21
20
|
|
|
22
21
|
// Mock translations
|
|
23
22
|
const mockT = vi.fn((key: string) => {
|
|
@@ -68,7 +67,7 @@ describe('AssistSection', () => {
|
|
|
68
67
|
annotationType="highlight"
|
|
69
68
|
isAssisting={true}
|
|
70
69
|
progress={{
|
|
71
|
-
|
|
70
|
+
stage: 'analyzing',
|
|
72
71
|
percentage: 30,
|
|
73
72
|
message: 'Analyzing text for highlights...',
|
|
74
73
|
}}
|
|
@@ -84,7 +83,8 @@ describe('AssistSection', () => {
|
|
|
84
83
|
annotationType="highlight"
|
|
85
84
|
isAssisting={true}
|
|
86
85
|
progress={{
|
|
87
|
-
|
|
86
|
+
stage: 'analyzing',
|
|
87
|
+
percentage: 0,
|
|
88
88
|
message: 'Processing...',
|
|
89
89
|
}}
|
|
90
90
|
/>
|
|
@@ -102,7 +102,8 @@ describe('AssistSection', () => {
|
|
|
102
102
|
annotationType="highlight"
|
|
103
103
|
isAssisting={true}
|
|
104
104
|
progress={{
|
|
105
|
-
|
|
105
|
+
stage: 'analyzing',
|
|
106
|
+
percentage: 0,
|
|
106
107
|
message: 'Analyzing...',
|
|
107
108
|
requestParams: [
|
|
108
109
|
{ label: 'Instructions', value: 'Find important points' },
|
|
@@ -125,7 +126,8 @@ describe('AssistSection', () => {
|
|
|
125
126
|
annotationType="highlight"
|
|
126
127
|
isAssisting={true}
|
|
127
128
|
progress={{
|
|
128
|
-
|
|
129
|
+
stage: 'analyzing',
|
|
130
|
+
percentage: 0,
|
|
129
131
|
message: 'Analyzing...',
|
|
130
132
|
}}
|
|
131
133
|
/>
|
|
@@ -170,7 +172,7 @@ describe('AssistSection', () => {
|
|
|
170
172
|
annotationType="highlight"
|
|
171
173
|
isAssisting={false}
|
|
172
174
|
progress={{
|
|
173
|
-
|
|
175
|
+
stage: 'complete',
|
|
174
176
|
percentage: 100,
|
|
175
177
|
message: 'Complete! Created 14 highlights',
|
|
176
178
|
}}
|
|
@@ -433,7 +435,8 @@ describe('AssistSection', () => {
|
|
|
433
435
|
annotationType="highlight"
|
|
434
436
|
isAssisting={true}
|
|
435
437
|
progress={{
|
|
436
|
-
|
|
438
|
+
stage: 'analyzing',
|
|
439
|
+
percentage: 0,
|
|
437
440
|
message: '',
|
|
438
441
|
}}
|
|
439
442
|
/>
|
|
@@ -450,9 +453,9 @@ describe('AssistSection', () => {
|
|
|
450
453
|
annotationType="highlight"
|
|
451
454
|
isAssisting={true}
|
|
452
455
|
progress={{
|
|
453
|
-
|
|
456
|
+
stage: 'analyzing',
|
|
457
|
+
percentage: 0,
|
|
454
458
|
message: 'Processing...',
|
|
455
|
-
// no percentage
|
|
456
459
|
}}
|
|
457
460
|
/>
|
|
458
461
|
);
|
|
@@ -466,7 +469,8 @@ describe('AssistSection', () => {
|
|
|
466
469
|
annotationType="highlight"
|
|
467
470
|
isAssisting={true}
|
|
468
471
|
progress={{
|
|
469
|
-
|
|
472
|
+
stage: 'analyzing',
|
|
473
|
+
percentage: 0,
|
|
470
474
|
message: 'Processing...',
|
|
471
475
|
requestParams: [],
|
|
472
476
|
}}
|
|
@@ -5,10 +5,8 @@ import { renderWithProviders } from '../../../../test-utils';
|
|
|
5
5
|
import userEvent from '@testing-library/user-event';
|
|
6
6
|
import '@testing-library/jest-dom';
|
|
7
7
|
import { CommentEntry } from '../CommentEntry';
|
|
8
|
-
import type { components } from '@semiont/core';
|
|
9
|
-
import type { EventBus } from "@semiont/core"
|
|
10
8
|
|
|
11
|
-
import type { Annotation } from '@semiont/core';
|
|
9
|
+
import type { Annotation, AnnotationId } from '@semiont/core';
|
|
12
10
|
|
|
13
11
|
// Mock TranslationContext
|
|
14
12
|
vi.mock('../../../../contexts/TranslationContext', () => ({
|
|
@@ -42,10 +40,11 @@ const mockGetAnnotationExactText = getAnnotationExactText as MockedFunction<type
|
|
|
42
40
|
// Test data fixtures
|
|
43
41
|
const createMockComment = (overrides?: Partial<Annotation>): Annotation => ({
|
|
44
42
|
'@context': 'http://www.w3.org/ns/anno.jsonld',
|
|
45
|
-
id: 'comment-1',
|
|
43
|
+
id: 'comment-1' as AnnotationId,
|
|
46
44
|
type: 'Annotation',
|
|
47
45
|
motivation: 'commenting',
|
|
48
46
|
creator: {
|
|
47
|
+
'@type': 'Person',
|
|
49
48
|
name: 'user@example.com',
|
|
50
49
|
},
|
|
51
50
|
created: '2024-01-01T10:00:00Z',
|
|
@@ -98,9 +97,6 @@ describe('CommentEntry Component', () => {
|
|
|
98
97
|
const defaultProps = {
|
|
99
98
|
comment: mockCommentStates.standard,
|
|
100
99
|
isFocused: false,
|
|
101
|
-
onClick: vi.fn(),
|
|
102
|
-
onCommentRef: vi.fn(),
|
|
103
|
-
onCommentHover: vi.fn(),
|
|
104
100
|
};
|
|
105
101
|
|
|
106
102
|
beforeEach(() => {
|
|
@@ -396,19 +392,26 @@ describe('CommentEntry Component', () => {
|
|
|
396
392
|
});
|
|
397
393
|
|
|
398
394
|
it('should stop event propagation when clicking textarea in edit mode', async () => {
|
|
399
|
-
const
|
|
400
|
-
|
|
395
|
+
const clickHandler = vi.fn();
|
|
396
|
+
const { eventBus } = renderWithProviders(
|
|
397
|
+
<CommentEntry {...defaultProps} />,
|
|
398
|
+
{ returnEventBus: true }
|
|
399
|
+
);
|
|
400
|
+
|
|
401
|
+
const subscription = eventBus!.get('browse:click').subscribe(clickHandler);
|
|
401
402
|
|
|
402
403
|
await userEvent.click(screen.getByText('Edit'));
|
|
403
404
|
|
|
404
|
-
// Clear
|
|
405
|
-
|
|
405
|
+
// Clear any browse:click emissions that happened during entering edit mode
|
|
406
|
+
clickHandler.mockClear();
|
|
406
407
|
|
|
407
408
|
const textarea = screen.getByRole('textbox');
|
|
408
409
|
await userEvent.click(textarea);
|
|
409
410
|
|
|
410
|
-
//
|
|
411
|
-
expect(
|
|
411
|
+
// browse:click should not be emitted for textarea click due to stopPropagation
|
|
412
|
+
expect(clickHandler).not.toHaveBeenCalled();
|
|
413
|
+
|
|
414
|
+
subscription.unsubscribe();
|
|
412
415
|
});
|
|
413
416
|
|
|
414
417
|
it('should update text in textarea', async () => {
|
|
@@ -484,14 +487,24 @@ describe('CommentEntry Component', () => {
|
|
|
484
487
|
expect(screen.getByText('This is a test comment')).toBeInTheDocument();
|
|
485
488
|
});
|
|
486
489
|
|
|
487
|
-
it('should not
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
+
it('should not emit any update when cancel is clicked', async () => {
|
|
491
|
+
const clickHandler = vi.fn();
|
|
492
|
+
const { eventBus } = renderWithProviders(
|
|
493
|
+
<CommentEntry {...defaultProps} />,
|
|
494
|
+
{ returnEventBus: true }
|
|
495
|
+
);
|
|
496
|
+
|
|
497
|
+
const subscription = eventBus!.get('browse:click').subscribe(clickHandler);
|
|
490
498
|
|
|
491
499
|
await userEvent.click(screen.getByText('Edit'));
|
|
500
|
+
clickHandler.mockClear();
|
|
501
|
+
|
|
492
502
|
await userEvent.click(screen.getByText('Cancel'));
|
|
493
503
|
|
|
494
|
-
|
|
504
|
+
// Cancel discards the edit without emitting any event
|
|
505
|
+
expect(clickHandler).not.toHaveBeenCalled();
|
|
506
|
+
|
|
507
|
+
subscription.unsubscribe();
|
|
495
508
|
});
|
|
496
509
|
});
|
|
497
510
|
|