@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.
Files changed (87) hide show
  1. package/README.md +59 -55
  2. package/dist/{PdfAnnotationCanvas.client-CN3C3S55.js → PdfAnnotationCanvas.client-NIMALXNZ.js} +7 -27
  3. package/dist/PdfAnnotationCanvas.client-NIMALXNZ.js.map +1 -0
  4. package/dist/index.css +6 -0
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.d.ts +243 -99
  7. package/dist/index.js +539 -405
  8. package/dist/index.js.map +1 -1
  9. package/package.json +16 -12
  10. package/src/components/Button/__tests__/Button.test.tsx +0 -2
  11. package/src/components/CodeMirrorRenderer.tsx +2 -0
  12. package/src/components/ErrorBoundary.tsx +0 -9
  13. package/src/components/ProtectedErrorBoundary.tsx +6 -2
  14. package/src/components/__tests__/AnnotateReferencesProgressWidget.test.tsx +0 -1
  15. package/src/components/__tests__/ErrorBoundary.test.tsx +20 -13
  16. package/src/components/__tests__/LiveRegion.hooks.test.tsx +1 -1
  17. package/src/components/__tests__/ProtectedErrorBoundary.test.tsx +2 -1
  18. package/src/components/__tests__/ResizeHandle.test.tsx +0 -1
  19. package/src/components/__tests__/SessionExpiryBanner.test.tsx +0 -1
  20. package/src/components/__tests__/StatusDisplay.test.tsx +0 -1
  21. package/src/components/__tests__/Toast.test.tsx +2 -3
  22. package/src/components/__tests__/Toolbar.test.tsx +0 -1
  23. package/src/components/annotation/annotations.css +14 -0
  24. package/src/components/annotation-popups/__tests__/JsonLdView.test.tsx +3 -5
  25. package/src/components/annotation-popups/__tests__/SharedPopupElements.test.tsx +0 -1
  26. package/src/components/branding/__tests__/SemiontBranding.test.tsx +1 -2
  27. package/src/components/layout/__tests__/LeftSidebar.test.tsx +5 -6
  28. package/src/components/layout/__tests__/PageLayout.test.tsx +1 -3
  29. package/src/components/layout/__tests__/SkipLinks.a11y.test.tsx +8 -8
  30. package/src/components/layout/__tests__/UnifiedHeader.test.tsx +12 -1
  31. package/src/components/modals/__tests__/KeyboardShortcutsHelpModal.test.tsx +0 -1
  32. package/src/components/modals/__tests__/PermissionDeniedModal.test.tsx +3 -4
  33. package/src/components/modals/__tests__/ResourceSearchModal.test.tsx +0 -1
  34. package/src/components/modals/__tests__/SearchModal.basic.test.tsx +1 -1
  35. package/src/components/modals/__tests__/SearchModal.keyboard.test.tsx +0 -5
  36. package/src/components/modals/__tests__/SearchModal.search-wiring.test.tsx +0 -1
  37. package/src/components/modals/__tests__/SearchModal.visual.test.tsx +2 -2
  38. package/src/components/modals/__tests__/SessionExpiredModal.test.tsx +0 -1
  39. package/src/components/navigation/NavigationMenu.tsx +1 -1
  40. package/src/components/navigation/__tests__/Footer.a11y.test.tsx +4 -0
  41. package/src/components/navigation/__tests__/Footer.test.tsx +3 -6
  42. package/src/components/navigation/__tests__/NavigationMenu.a11y.test.tsx +1 -1
  43. package/src/components/navigation/__tests__/NavigationMenu.test.tsx +7 -9
  44. package/src/components/navigation/__tests__/ObservableLink.test.tsx +0 -1
  45. package/src/components/navigation/__tests__/SimpleNavigation.test.tsx +1 -2
  46. package/src/components/navigation/__tests__/SortableResourceTab.test.tsx +0 -1
  47. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +6 -4
  48. package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +10 -19
  49. package/src/components/resource/__tests__/BrowseView.test.tsx +8 -6
  50. package/src/components/resource/__tests__/HistoryEvent.test.tsx +0 -4
  51. package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +4 -6
  52. package/src/components/resource/panels/ReferencesPanel.tsx +1 -1
  53. package/src/components/resource/panels/__tests__/AssessmentEntry.test.tsx +3 -4
  54. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +7 -6
  55. package/src/components/resource/panels/__tests__/AssistSection.test.tsx +14 -10
  56. package/src/components/resource/panels/__tests__/CollaborationPanel.test.tsx +0 -1
  57. package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +30 -17
  58. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +6 -5
  59. package/src/components/resource/panels/__tests__/HighlightEntry.test.tsx +4 -5
  60. package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +19 -13
  61. package/src/components/resource/panels/__tests__/JsonLdPanel.test.tsx +1 -3
  62. package/src/components/resource/panels/__tests__/PanelHeader.test.tsx +0 -1
  63. package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +5 -5
  64. package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +40 -7
  65. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +3 -3
  66. package/src/components/resource/panels/__tests__/StatisticsPanel.test.tsx +30 -32
  67. package/src/components/resource/panels/__tests__/TagEntry.test.tsx +5 -5
  68. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +6 -5
  69. package/src/components/settings/__tests__/SettingsPanel.test.tsx +0 -1
  70. package/src/components/viewers/__tests__/ImageViewer.test.tsx +0 -1
  71. package/src/features/auth/__tests__/SignInForm.a11y.test.tsx +2 -0
  72. package/src/features/auth/__tests__/SignUpForm.a11y.test.tsx +11 -12
  73. package/src/features/auth/__tests__/SignUpForm.test.tsx +3 -3
  74. package/src/features/moderate-tag-schemas/components/TagSchemasPage.tsx +1 -0
  75. package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +2 -1
  76. package/src/features/resource-discovery/__tests__/ResourceCard.test.tsx +0 -1
  77. package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +33 -35
  78. package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +12 -11
  79. package/src/features/resource-discovery/state/__tests__/discover-state-unit.test.ts +204 -11
  80. package/src/features/resource-discovery/state/discover-state-unit.ts +70 -11
  81. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +2 -2
  82. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +3 -2
  83. package/src/features/resource-viewer/state/__tests__/resource-viewer-page-state-unit.test.ts +0 -1
  84. package/src/features/resource-viewer/state/resource-viewer-page-state-unit.ts +5 -2
  85. package/src/integrations/__tests__/css-modules-helper.test.tsx +2 -3
  86. package/src/integrations/__tests__/styled-components-theme.test.ts +1 -3
  87. 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, waitFor } from '@testing-library/react';
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
  });
@@ -7,7 +7,6 @@
7
7
  */
8
8
 
9
9
  import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
10
- import React from 'react';
11
10
  import { screen, fireEvent } from '@testing-library/react';
12
11
  import '@testing-library/jest-dom';
13
12
  import {
@@ -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 = ({ isOpen, onClose }: any) => null;
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, onClose }: any) => (
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 = ({ isOpen, onClose }: any) => null;
387
+ const MockCookiePrefs = ({ }: any) => null;
391
388
 
392
389
  render(
393
390
  <Footer
@@ -56,7 +56,7 @@ describe('NavigationMenu - Accessibility', () => {
56
56
  Link={mockLink}
57
57
  routes={mockRoutes}
58
58
  t={mockTranslate}
59
- activePath="/knowledge"
59
+ currentPath="/knowledge"
60
60
  />
61
61
  );
62
62
 
@@ -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
- const { container } = render(
291
- <NavigationMenu
292
- Link={mockLink}
293
- routes={mockRoutes}
294
- t={mockTranslate}
295
- isAdmin={true}
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';
@@ -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 = (onClose: () => void) => (
145
+ const dropdownContent = () => (
147
146
  <div data-testid="dropdown-content">Dropdown</div>
148
147
  );
149
148
 
@@ -1,5 +1,4 @@
1
1
  import { describe, it, expect, vi, beforeEach } 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';
@@ -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 { getTargetSelector } from '@semiont/core';
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
- resourceUri={mockResourceId}
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
- resourceUri={mockResourceId}
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
- resourceUri={mockResourceId}
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
- resourceUri={mockResourceId}
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
- resourceUri={mockResourceId}
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('emits annotate:requested via eventBus when drawing with sufficient drag', async () => {
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
- resourceUri={mockResourceId}
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 { components, EventBus } from '@semiont/core';
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: string, id: string): Annotation => ({
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
- document.querySelectorAll = vi.fn(() => []);
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, fireEvent, waitFor } from '@testing-library/react';
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 { components } from '@semiont/core';
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, params?: Record<string, any>) => {
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 (!isAssisting && !hasSavedLogRef.current && progress?.completedEntityTypes) {
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, fireEvent, waitFor } from '@testing-library/react';
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 { components, EventBus } from '@semiont/core';
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, onAssessmentRef }: any) => (
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: ({ annotationType, isAssisting }: any) => (
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
- status: 'analyzing',
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
- status: 'analyzing',
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
- status: 'analyzing',
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
- status: 'analyzing',
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
- status: 'complete',
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
- status: 'analyzing',
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
- status: 'analyzing',
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
- status: 'analyzing',
472
+ stage: 'analyzing',
473
+ percentage: 0,
470
474
  message: 'Processing...',
471
475
  requestParams: [],
472
476
  }}
@@ -1,5 +1,4 @@
1
1
  import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import React from 'react';
3
2
  import { render, screen } from '@testing-library/react';
4
3
  import '@testing-library/jest-dom';
5
4
  import { CollaborationPanel } from '../CollaborationPanel';
@@ -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 onClick = vi.fn();
400
- renderWithProviders(<CommentEntry {...defaultProps} onClick={onClick} />);
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 the onClick calls that happened during entering edit mode
405
- onClick.mockClear();
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
- // onClick should not be called for textarea click due to stopPropagation
411
- expect(onClick).not.toHaveBeenCalled();
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 call onUpdate when cancel is clicked', async () => {
488
- const onUpdate = vi.fn();
489
- renderWithProviders(<CommentEntry {...defaultProps} onUpdate={onUpdate} />);
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
- expect(onUpdate).not.toHaveBeenCalled();
504
+ // Cancel discards the edit without emitting any event
505
+ expect(clickHandler).not.toHaveBeenCalled();
506
+
507
+ subscription.unsubscribe();
495
508
  });
496
509
  });
497
510