@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
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semiont/react-ui",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
|
+
"engines": {
|
|
5
|
+
"node": ">=24.0.0"
|
|
6
|
+
},
|
|
4
7
|
"description": "React components and hooks for Semiont",
|
|
5
8
|
"type": "module",
|
|
6
9
|
"main": "./dist/index.js",
|
|
@@ -74,25 +77,26 @@
|
|
|
74
77
|
"test:split:coverage": "npm run test:coverage"
|
|
75
78
|
},
|
|
76
79
|
"peerDependencies": {
|
|
77
|
-
"react": "^
|
|
78
|
-
"react-dom": "^
|
|
80
|
+
"react": "^19.0.0",
|
|
81
|
+
"react-dom": "^19.0.0"
|
|
79
82
|
},
|
|
80
83
|
"devDependencies": {
|
|
81
84
|
"@testing-library/jest-dom": "^6.1.5",
|
|
82
85
|
"@testing-library/react": "^16.1.0",
|
|
83
|
-
"@types/react": "^19",
|
|
86
|
+
"@types/react": "^19.2.16",
|
|
84
87
|
"@types/react-dom": "^19",
|
|
85
|
-
"@vitest/coverage-v8": "^4.1.
|
|
86
|
-
"autoprefixer": "^10.
|
|
87
|
-
"axe-core": "^4.11.
|
|
88
|
-
"cssnano": "^
|
|
88
|
+
"@vitest/coverage-v8": "^4.1.8",
|
|
89
|
+
"autoprefixer": "^10.5.0",
|
|
90
|
+
"axe-core": "^4.11.4",
|
|
91
|
+
"cssnano": "^8.0.1",
|
|
89
92
|
"jest-axe": "^10.0.0",
|
|
90
|
-
"jsdom": "^
|
|
93
|
+
"jsdom": "^29.1.1",
|
|
91
94
|
"postcss-import": "^16.1.1",
|
|
92
|
-
"rollup": "^4.
|
|
95
|
+
"rollup": "^4.61.0",
|
|
93
96
|
"rollup-plugin-dts": "^6.4.1",
|
|
94
97
|
"tsup": "^8.0.1",
|
|
95
|
-
"typescript": "^6.0.2"
|
|
98
|
+
"typescript": "^6.0.2",
|
|
99
|
+
"vitest": "^4.1.8"
|
|
96
100
|
},
|
|
97
101
|
"publishConfig": {
|
|
98
102
|
"access": "public"
|
|
@@ -108,6 +112,6 @@
|
|
|
108
112
|
"@semiont/api-client": "*",
|
|
109
113
|
"@semiont/core": "*",
|
|
110
114
|
"@semiont/sdk": "*",
|
|
111
|
-
"react-error-boundary": "^
|
|
115
|
+
"react-error-boundary": "^6.1.2"
|
|
112
116
|
}
|
|
113
117
|
}
|
|
@@ -157,7 +157,6 @@ describe('Button Component', () => {
|
|
|
157
157
|
const icon = <span data-testid="left-icon">←</span>;
|
|
158
158
|
render(<Button leftIcon={icon}>Button</Button>);
|
|
159
159
|
|
|
160
|
-
const button = screen.getByRole('button');
|
|
161
160
|
const leftIcon = screen.getByTestId('left-icon');
|
|
162
161
|
const iconWrapper = leftIcon.parentElement;
|
|
163
162
|
|
|
@@ -169,7 +168,6 @@ describe('Button Component', () => {
|
|
|
169
168
|
const icon = <span data-testid="right-icon">→</span>;
|
|
170
169
|
render(<Button rightIcon={icon}>Button</Button>);
|
|
171
170
|
|
|
172
|
-
const button = screen.getByRole('button');
|
|
173
171
|
const rightIcon = screen.getByTestId('right-icon');
|
|
174
172
|
const iconWrapper = rightIcon.parentElement;
|
|
175
173
|
|
|
@@ -81,6 +81,8 @@ function buildAnnotationDecorations(
|
|
|
81
81
|
attributes: {
|
|
82
82
|
'data-annotation-id': meta.annotationId,
|
|
83
83
|
'data-annotation-type': meta.annotationType,
|
|
84
|
+
...(meta.strategy ? { 'data-anchor-strategy': meta.strategy } : {}),
|
|
85
|
+
...(meta.confidence ? { 'data-anchor-confidence': meta.confidence } : {}),
|
|
84
86
|
title: meta.tooltip,
|
|
85
87
|
},
|
|
86
88
|
});
|
|
@@ -11,7 +11,6 @@ interface Props {
|
|
|
11
11
|
interface State {
|
|
12
12
|
hasError: boolean;
|
|
13
13
|
error: Error | null;
|
|
14
|
-
errorInfo: ErrorInfo | null;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
/**
|
|
@@ -24,7 +23,6 @@ export class ErrorBoundary extends Component<Props, State> {
|
|
|
24
23
|
this.state = {
|
|
25
24
|
hasError: false,
|
|
26
25
|
error: null,
|
|
27
|
-
errorInfo: null,
|
|
28
26
|
};
|
|
29
27
|
}
|
|
30
28
|
|
|
@@ -33,7 +31,6 @@ export class ErrorBoundary extends Component<Props, State> {
|
|
|
33
31
|
return {
|
|
34
32
|
hasError: true,
|
|
35
33
|
error,
|
|
36
|
-
errorInfo: null,
|
|
37
34
|
};
|
|
38
35
|
}
|
|
39
36
|
|
|
@@ -48,11 +45,6 @@ export class ErrorBoundary extends Component<Props, State> {
|
|
|
48
45
|
this.props.onError(error, errorInfo);
|
|
49
46
|
}
|
|
50
47
|
|
|
51
|
-
// Update state with error info
|
|
52
|
-
this.setState({
|
|
53
|
-
errorInfo,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
48
|
// In production, you might want to log to an error reporting service
|
|
57
49
|
// Example: logErrorToService(error, errorInfo);
|
|
58
50
|
}
|
|
@@ -61,7 +53,6 @@ export class ErrorBoundary extends Component<Props, State> {
|
|
|
61
53
|
this.setState({
|
|
62
54
|
hasError: false,
|
|
63
55
|
error: null,
|
|
64
|
-
errorInfo: null,
|
|
65
56
|
});
|
|
66
57
|
};
|
|
67
58
|
|
|
@@ -45,6 +45,10 @@ export function ProtectedErrorBoundary({
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function ProtectedErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
|
|
48
|
+
// react-error-boundary v6 types `error` as `unknown` — a thrown value can be
|
|
49
|
+
// anything, so narrow before reading Error fields.
|
|
50
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
51
|
+
const stack = error instanceof Error ? error.stack : undefined;
|
|
48
52
|
return (
|
|
49
53
|
<div className="min-h-[400px] flex items-center justify-center p-4">
|
|
50
54
|
<div className="max-w-md w-full bg-white dark:bg-gray-800 rounded-lg shadow-lg p-6">
|
|
@@ -69,8 +73,8 @@ function ProtectedErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
|
|
|
69
73
|
Error details (development only)
|
|
70
74
|
</summary>
|
|
71
75
|
<pre className="mt-2 text-xs bg-gray-100 dark:bg-gray-900 p-2 rounded-sm overflow-auto">
|
|
72
|
-
{
|
|
73
|
-
{
|
|
76
|
+
{message}
|
|
77
|
+
{stack}
|
|
74
78
|
</pre>
|
|
75
79
|
</details>
|
|
76
80
|
)}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
3
|
import { render, screen, fireEvent } from '@testing-library/react';
|
|
4
4
|
import '@testing-library/jest-dom';
|
|
5
5
|
import { ErrorBoundary, AsyncErrorBoundary } from '../ErrorBoundary';
|
|
@@ -146,7 +146,7 @@ describe('ErrorBoundary Component', () => {
|
|
|
146
146
|
});
|
|
147
147
|
|
|
148
148
|
it('should not render default fallback when custom fallback is provided', () => {
|
|
149
|
-
const customFallback = (
|
|
149
|
+
const customFallback = () => <div>Custom Fallback</div>;
|
|
150
150
|
|
|
151
151
|
render(
|
|
152
152
|
<ErrorBoundary fallback={customFallback}>
|
|
@@ -223,7 +223,7 @@ describe('ErrorBoundary Component', () => {
|
|
|
223
223
|
|
|
224
224
|
it('should call custom reset handler in custom fallback', () => {
|
|
225
225
|
const resetHandler = vi.fn();
|
|
226
|
-
const customFallback = (
|
|
226
|
+
const customFallback = (_error: Error, reset: () => void) => (
|
|
227
227
|
<div>
|
|
228
228
|
<button onClick={() => { resetHandler(); reset(); }}>Reset</button>
|
|
229
229
|
</div>
|
|
@@ -242,9 +242,9 @@ describe('ErrorBoundary Component', () => {
|
|
|
242
242
|
});
|
|
243
243
|
|
|
244
244
|
it('should clear error state when reset is called', () => {
|
|
245
|
-
|
|
245
|
+
const resetRef: { current: (() => void) | null } = { current: null };
|
|
246
246
|
const customFallback = (error: Error, reset: () => void) => {
|
|
247
|
-
|
|
247
|
+
resetRef.current = reset;
|
|
248
248
|
return <div>Error: {error.message}</div>;
|
|
249
249
|
};
|
|
250
250
|
|
|
@@ -255,11 +255,11 @@ describe('ErrorBoundary Component', () => {
|
|
|
255
255
|
);
|
|
256
256
|
|
|
257
257
|
expect(screen.getByText('Error: Initial error')).toBeInTheDocument();
|
|
258
|
-
expect(
|
|
258
|
+
expect(resetRef.current).not.toBeNull();
|
|
259
259
|
|
|
260
260
|
// Call reset
|
|
261
|
-
if (
|
|
262
|
-
|
|
261
|
+
if (resetRef.current) {
|
|
262
|
+
resetRef.current();
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
// Rerender with non-throwing component after reset
|
|
@@ -286,8 +286,11 @@ describe('ErrorBoundary Component', () => {
|
|
|
286
286
|
|
|
287
287
|
it('should navigate to home when Go Home button clicked', () => {
|
|
288
288
|
const originalLocation = window.location;
|
|
289
|
-
|
|
290
|
-
|
|
289
|
+
Object.defineProperty(window, 'location', {
|
|
290
|
+
value: { href: '' },
|
|
291
|
+
writable: true,
|
|
292
|
+
configurable: true,
|
|
293
|
+
});
|
|
291
294
|
|
|
292
295
|
render(
|
|
293
296
|
<ErrorBoundary>
|
|
@@ -300,7 +303,11 @@ describe('ErrorBoundary Component', () => {
|
|
|
300
303
|
|
|
301
304
|
expect(window.location.href).toBe('/');
|
|
302
305
|
|
|
303
|
-
window
|
|
306
|
+
Object.defineProperty(window, 'location', {
|
|
307
|
+
value: originalLocation,
|
|
308
|
+
writable: true,
|
|
309
|
+
configurable: true,
|
|
310
|
+
});
|
|
304
311
|
});
|
|
305
312
|
});
|
|
306
313
|
|
|
@@ -336,7 +343,7 @@ describe('ErrorBoundary Component', () => {
|
|
|
336
343
|
|
|
337
344
|
describe('Edge Cases', () => {
|
|
338
345
|
it('should handle error with no message', () => {
|
|
339
|
-
function ThrowEmptyError() {
|
|
346
|
+
function ThrowEmptyError(): ReactNode {
|
|
340
347
|
throw new Error();
|
|
341
348
|
}
|
|
342
349
|
|
|
@@ -433,7 +440,7 @@ describe('AsyncErrorBoundary Component', () => {
|
|
|
433
440
|
});
|
|
434
441
|
|
|
435
442
|
it('should handle error with no message', () => {
|
|
436
|
-
function ThrowEmptyError() {
|
|
443
|
+
function ThrowEmptyError(): ReactNode {
|
|
437
444
|
throw new Error();
|
|
438
445
|
}
|
|
439
446
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { renderHook, act } from '@testing-library/react';
|
|
4
|
-
import { render
|
|
4
|
+
import { render } from '@testing-library/react';
|
|
5
5
|
import '@testing-library/jest-dom';
|
|
6
6
|
import {
|
|
7
7
|
LiveRegionProvider,
|
|
@@ -186,7 +186,8 @@ describe('ProtectedErrorBoundary', () => {
|
|
|
186
186
|
// Multiple console.error calls happen (React's own logs, plus ours).
|
|
187
187
|
// Look for the boundary's prefix specifically.
|
|
188
188
|
const ourCall = consoleErrorSpy.mock.calls.find(
|
|
189
|
-
call
|
|
189
|
+
(call: Parameters<typeof console.error>) =>
|
|
190
|
+
typeof call[0] === 'string' && call[0].includes('ProtectedErrorBoundary caught:')
|
|
190
191
|
);
|
|
191
192
|
expect(ourCall).toBeDefined();
|
|
192
193
|
} finally {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { render, screen
|
|
3
|
-
import
|
|
4
|
-
import { ToastProvider, useToast, ToastContainer, type ToastMessage } from '../Toast';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import { ToastProvider, useToast } from '../Toast';
|
|
5
4
|
|
|
6
5
|
describe('Toast System', () => {
|
|
7
6
|
beforeEach(() => {
|
|
@@ -36,6 +36,20 @@
|
|
|
36
36
|
position: relative;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/* Low-confidence anchor affordance.
|
|
40
|
+
*
|
|
41
|
+
* Annotations whose anchor was resolved by something other than a clean
|
|
42
|
+
* fast-path or unique-occurrence match (i.e. `confidence !== 'high'`)
|
|
43
|
+
* get a dotted underline so operators can see at a glance which
|
|
44
|
+
* highlights were rescued by score-resolved tiebreaking, fuzzy matching,
|
|
45
|
+
* or a position-fallback. The hover tooltip (added by
|
|
46
|
+
* `getAnnotationDecorationMeta`) names the strategy. */
|
|
47
|
+
.annotation-low-confidence {
|
|
48
|
+
text-decoration: underline dotted var(--semiont-color-warning-500, #d97706);
|
|
49
|
+
text-decoration-thickness: 2px;
|
|
50
|
+
text-underline-offset: 2px;
|
|
51
|
+
}
|
|
52
|
+
|
|
39
53
|
/* Print styles */
|
|
40
54
|
@media print {
|
|
41
55
|
.annotation-highlight,
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
-
import React from 'react';
|
|
3
2
|
import { screen, fireEvent, waitFor } from '@testing-library/react';
|
|
4
3
|
import userEvent from '@testing-library/user-event';
|
|
5
4
|
import '@testing-library/jest-dom';
|
|
6
|
-
import type { components } from '@semiont/core';
|
|
7
5
|
|
|
8
|
-
import type { Annotation } from '@semiont/core';
|
|
6
|
+
import type { Annotation, AnnotationId } from '@semiont/core';
|
|
9
7
|
|
|
10
8
|
// Mock CodeMirror modules
|
|
11
9
|
vi.mock('@codemirror/view', () => {
|
|
@@ -57,10 +55,10 @@ import { JsonLdView } from '../JsonLdView';
|
|
|
57
55
|
|
|
58
56
|
const createMockAnnotation = (overrides?: Partial<Annotation>): Annotation => ({
|
|
59
57
|
'@context': 'http://www.w3.org/ns/anno.jsonld',
|
|
60
|
-
id: 'anno-1',
|
|
58
|
+
id: 'anno-1' as AnnotationId,
|
|
61
59
|
type: 'Annotation',
|
|
62
60
|
motivation: 'highlighting',
|
|
63
|
-
creator: { name: 'user@example.com' },
|
|
61
|
+
creator: { '@type': 'Person', name: 'user@example.com' },
|
|
64
62
|
created: '2024-01-01T10:00:00Z',
|
|
65
63
|
target: {
|
|
66
64
|
source: 'resource-1',
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } 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 { SemiontBranding } from '../SemiontBranding';
|
|
@@ -305,7 +304,7 @@ describe('SemiontBranding Component', () => {
|
|
|
305
304
|
|
|
306
305
|
describe('Edge Cases', () => {
|
|
307
306
|
it('should handle missing translation gracefully', () => {
|
|
308
|
-
const emptyTranslate = vi.fn((
|
|
307
|
+
const emptyTranslate = vi.fn(() => '');
|
|
309
308
|
|
|
310
309
|
render(<SemiontBranding t={emptyTranslate} />);
|
|
311
310
|
|
|
@@ -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 { LeftSidebar } from '../LeftSidebar';
|
|
@@ -159,7 +158,7 @@ describe('LeftSidebar Component', () => {
|
|
|
159
158
|
});
|
|
160
159
|
|
|
161
160
|
it('should save collapsed state to localStorage', () => {
|
|
162
|
-
const mockChildren = vi.fn((
|
|
161
|
+
const mockChildren = vi.fn((_isCollapsed, toggleCollapsed) => (
|
|
163
162
|
<button onClick={toggleCollapsed} data-testid="toggle-btn">Toggle</button>
|
|
164
163
|
));
|
|
165
164
|
|
|
@@ -183,7 +182,7 @@ describe('LeftSidebar Component', () => {
|
|
|
183
182
|
});
|
|
184
183
|
|
|
185
184
|
it('should not collapse when collapsible is false', () => {
|
|
186
|
-
const mockChildren = vi.fn((
|
|
185
|
+
const mockChildren = vi.fn((_isCollapsed, toggleCollapsed) => (
|
|
187
186
|
<button onClick={toggleCollapsed} data-testid="toggle-btn">Toggle</button>
|
|
188
187
|
));
|
|
189
188
|
|
|
@@ -208,7 +207,7 @@ describe('LeftSidebar Component', () => {
|
|
|
208
207
|
});
|
|
209
208
|
|
|
210
209
|
it('should use default storage key', () => {
|
|
211
|
-
const mockChildren = vi.fn((
|
|
210
|
+
const mockChildren = vi.fn((_isCollapsed, toggleCollapsed) => (
|
|
212
211
|
<button onClick={toggleCollapsed} data-testid="toggle-btn">Toggle</button>
|
|
213
212
|
));
|
|
214
213
|
|
|
@@ -233,7 +232,7 @@ describe('LeftSidebar Component', () => {
|
|
|
233
232
|
|
|
234
233
|
describe('Navigation Menu Helper', () => {
|
|
235
234
|
it('should provide navigationMenu helper to function children', () => {
|
|
236
|
-
const mockChildren = vi.fn((
|
|
235
|
+
const mockChildren = vi.fn((_isCollapsed, _toggleCollapsed, navigationMenu) => {
|
|
237
236
|
// Test that navigationMenu helper returns NavigationMenu component
|
|
238
237
|
const menuElement = navigationMenu(() => {});
|
|
239
238
|
return <div data-testid="children-content">{menuElement}</div>;
|
|
@@ -259,7 +258,7 @@ describe('LeftSidebar Component', () => {
|
|
|
259
258
|
|
|
260
259
|
it('should pass onClose callback to NavigationMenu', () => {
|
|
261
260
|
const mockOnClose = vi.fn();
|
|
262
|
-
const mockChildren = vi.fn((
|
|
261
|
+
const mockChildren = vi.fn((_isCollapsed, _toggleCollapsed, navigationMenu) => {
|
|
263
262
|
const menuElement = navigationMenu(mockOnClose);
|
|
264
263
|
return <div>{menuElement}</div>;
|
|
265
264
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { describe, it, expect, 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 { PageLayout } from '../PageLayout';
|
|
@@ -247,7 +246,6 @@ describe('PageLayout Component', () => {
|
|
|
247
246
|
);
|
|
248
247
|
|
|
249
248
|
// Real Footer renders copyright with dynamic year
|
|
250
|
-
const currentYear = new Date().getFullYear();
|
|
251
249
|
expect(screen.getByText(`translated.copyright`)).toBeInTheDocument();
|
|
252
250
|
});
|
|
253
251
|
});
|
|
@@ -270,7 +268,7 @@ describe('PageLayout Component', () => {
|
|
|
270
268
|
});
|
|
271
269
|
|
|
272
270
|
it('should render with CookiePreferences component', () => {
|
|
273
|
-
const MockCookiePreferences = ({
|
|
271
|
+
const MockCookiePreferences = ({ }: any) => (
|
|
274
272
|
<div data-testid="cookie-prefs">Cookie Preferences</div>
|
|
275
273
|
);
|
|
276
274
|
|
|
@@ -63,7 +63,7 @@ describe('SkipLinks - Accessibility', () => {
|
|
|
63
63
|
|
|
64
64
|
it('should become visible on focus', async () => {
|
|
65
65
|
const user = userEvent.setup();
|
|
66
|
-
|
|
66
|
+
render(<SkipLinks />);
|
|
67
67
|
|
|
68
68
|
const firstLink = screen.getAllByRole('link')[0];
|
|
69
69
|
|
|
@@ -76,12 +76,12 @@ describe('SkipLinks - Accessibility', () => {
|
|
|
76
76
|
|
|
77
77
|
it('should hide when focus leaves', async () => {
|
|
78
78
|
const user = userEvent.setup();
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
render(
|
|
80
|
+
<div>
|
|
81
|
+
<SkipLinks />
|
|
82
|
+
<button>Next focusable element</button>
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
85
|
|
|
86
86
|
// Tab to first skip link
|
|
87
87
|
await user.tab();
|
|
@@ -239,7 +239,7 @@ describe('SkipLinks - Accessibility', () => {
|
|
|
239
239
|
|
|
240
240
|
it('should maintain focus management with multiple links', async () => {
|
|
241
241
|
const user = userEvent.setup();
|
|
242
|
-
|
|
242
|
+
render(<SkipLinks />);
|
|
243
243
|
|
|
244
244
|
// Tab to first link
|
|
245
245
|
await user.tab();
|
|
@@ -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 { UnifiedHeader } from '../UnifiedHeader';
|
|
@@ -9,6 +8,7 @@ vi.mock('@/hooks/useUI', () => ({
|
|
|
9
8
|
useDropdown: vi.fn(() => ({
|
|
10
9
|
isOpen: false,
|
|
11
10
|
toggle: vi.fn(),
|
|
11
|
+
open: vi.fn(),
|
|
12
12
|
close: vi.fn(),
|
|
13
13
|
dropdownRef: { current: null },
|
|
14
14
|
})),
|
|
@@ -37,6 +37,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
37
37
|
vi.mocked(useDropdown).mockReturnValue({
|
|
38
38
|
isOpen: false,
|
|
39
39
|
toggle: vi.fn(),
|
|
40
|
+
open: vi.fn(),
|
|
40
41
|
close: vi.fn(),
|
|
41
42
|
dropdownRef: { current: null },
|
|
42
43
|
});
|
|
@@ -216,6 +217,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
216
217
|
vi.mocked(useDropdown).mockReturnValue({
|
|
217
218
|
isOpen: false,
|
|
218
219
|
toggle: mockToggle,
|
|
220
|
+
open: vi.fn(),
|
|
219
221
|
close: vi.fn(),
|
|
220
222
|
dropdownRef: { current: null },
|
|
221
223
|
});
|
|
@@ -239,6 +241,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
239
241
|
vi.mocked(useDropdown).mockReturnValue({
|
|
240
242
|
isOpen: true,
|
|
241
243
|
toggle: vi.fn(),
|
|
244
|
+
open: vi.fn(),
|
|
242
245
|
close: vi.fn(),
|
|
243
246
|
dropdownRef: { current: null },
|
|
244
247
|
});
|
|
@@ -261,6 +264,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
261
264
|
vi.mocked(useDropdown).mockReturnValue({
|
|
262
265
|
isOpen: true,
|
|
263
266
|
toggle: vi.fn(),
|
|
267
|
+
open: vi.fn(),
|
|
264
268
|
close: vi.fn(),
|
|
265
269
|
dropdownRef: { current: null },
|
|
266
270
|
});
|
|
@@ -282,6 +286,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
282
286
|
vi.mocked(useDropdown).mockReturnValue({
|
|
283
287
|
isOpen: false,
|
|
284
288
|
toggle: vi.fn(),
|
|
289
|
+
open: vi.fn(),
|
|
285
290
|
close: vi.fn(),
|
|
286
291
|
dropdownRef: { current: null },
|
|
287
292
|
});
|
|
@@ -304,6 +309,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
304
309
|
vi.mocked(useDropdown).mockReturnValue({
|
|
305
310
|
isOpen: true,
|
|
306
311
|
toggle: vi.fn(),
|
|
312
|
+
open: vi.fn(),
|
|
307
313
|
close: mockClose,
|
|
308
314
|
dropdownRef: { current: null },
|
|
309
315
|
});
|
|
@@ -331,6 +337,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
331
337
|
vi.mocked(useDropdown).mockReturnValue({
|
|
332
338
|
isOpen: false,
|
|
333
339
|
toggle: vi.fn(),
|
|
340
|
+
open: vi.fn(),
|
|
334
341
|
close: vi.fn(),
|
|
335
342
|
dropdownRef: { current: null },
|
|
336
343
|
});
|
|
@@ -366,6 +373,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
366
373
|
vi.mocked(useDropdown).mockReturnValue({
|
|
367
374
|
isOpen: true,
|
|
368
375
|
toggle: vi.fn(),
|
|
376
|
+
open: vi.fn(),
|
|
369
377
|
close: vi.fn(),
|
|
370
378
|
dropdownRef: { current: null },
|
|
371
379
|
});
|
|
@@ -389,6 +397,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
389
397
|
vi.mocked(useDropdown).mockReturnValue({
|
|
390
398
|
isOpen: true,
|
|
391
399
|
toggle: vi.fn(),
|
|
400
|
+
open: vi.fn(),
|
|
392
401
|
close: vi.fn(),
|
|
393
402
|
dropdownRef: { current: null },
|
|
394
403
|
});
|
|
@@ -450,6 +459,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
450
459
|
vi.mocked(useDropdown).mockReturnValue({
|
|
451
460
|
isOpen: true,
|
|
452
461
|
toggle: vi.fn(),
|
|
462
|
+
open: vi.fn(),
|
|
453
463
|
close: vi.fn(),
|
|
454
464
|
dropdownRef: { current: null },
|
|
455
465
|
});
|
|
@@ -471,6 +481,7 @@ describe('UnifiedHeader Component', () => {
|
|
|
471
481
|
vi.mocked(useDropdown).mockReturnValue({
|
|
472
482
|
isOpen: true,
|
|
473
483
|
toggle: vi.fn(),
|
|
484
|
+
open: vi.fn(),
|
|
474
485
|
close: vi.fn(),
|
|
475
486
|
dropdownRef: { current: null },
|
|
476
487
|
});
|
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* `acknowledgePermissionDenied()` and navigate the window or history.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
10
|
-
import React from 'react';
|
|
9
|
+
import { describe, it, expect, beforeEach, afterEach, vi, type Mock } from 'vitest';
|
|
11
10
|
import { screen, fireEvent } from '@testing-library/react';
|
|
12
11
|
import '@testing-library/jest-dom';
|
|
13
12
|
import {
|
|
@@ -27,7 +26,7 @@ vi.mock('@headlessui/react', () => ({
|
|
|
27
26
|
const originalLocation = window.location;
|
|
28
27
|
const originalHistoryBack = window.history.back;
|
|
29
28
|
let mockLocation: { href: string; pathname: string };
|
|
30
|
-
let mockHistoryBack:
|
|
29
|
+
let mockHistoryBack: Mock<() => void>;
|
|
31
30
|
|
|
32
31
|
beforeEach(() => {
|
|
33
32
|
mockLocation = { href: '', pathname: '/admin/users' };
|
|
@@ -36,7 +35,7 @@ beforeEach(() => {
|
|
|
36
35
|
writable: true,
|
|
37
36
|
configurable: true,
|
|
38
37
|
});
|
|
39
|
-
mockHistoryBack = vi.fn();
|
|
38
|
+
mockHistoryBack = vi.fn<() => void>();
|
|
40
39
|
window.history.back = mockHistoryBack;
|
|
41
40
|
});
|
|
42
41
|
|
|
@@ -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 userEvent from '@testing-library/user-event';
|
|
8
8
|
import { SearchModal } from '../SearchModal';
|
|
9
9
|
|
|
@@ -52,11 +52,6 @@ describe.skip('SearchModal Component - Keyboard Navigation', () => {
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
it('should handle Arrow Down key to navigate results', async () => {
|
|
55
|
-
const mockResults = [
|
|
56
|
-
{ type: 'resource' as const, id: '1', name: 'Resource 1', content: 'Content 1' },
|
|
57
|
-
{ type: 'resource' as const, id: '2', name: 'Resource 2', content: 'Content 2' },
|
|
58
|
-
{ type: 'entity' as const, id: '3', name: 'Entity 1', entityType: 'Person' }
|
|
59
|
-
];
|
|
60
55
|
|
|
61
56
|
// TODO: Mock search results when API is integrated
|
|
62
57
|
render(<SearchModal {...defaultProps} />);
|