@semiont/react-ui 0.5.26 → 0.5.28
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 +28 -4
- package/dist/{PdfAnnotationCanvas.client-6ZSF6ZTJ.js → PdfAnnotationCanvas.client-C2IGG4SW.js} +33 -6
- package/dist/{PdfAnnotationCanvas.client-JCJMXWWJ.css → PdfAnnotationCanvas.client-TGDPPGXJ.css} +6 -1
- package/dist/{ar-YTUUGK2O.js → ar-FABPTJVB.js} +88 -26
- package/dist/{bn-ASGNGPMD.js → bn-LKP6BDMH.js} +88 -26
- package/dist/{chunk-L3WKRWP3.js → chunk-2GOHTTHW.js} +88 -26
- package/dist/{chunk-OBQOZCJE.js → chunk-2YHEE63S.js} +31 -31
- package/dist/{cs-WMYVAOZY.js → cs-YQYNWHRG.js} +88 -26
- package/dist/{da-FSHHN4D6.js → da-QHZOYKRY.js} +88 -26
- package/dist/{de-FJFO3TPT.js → de-GKA7RD7J.js} +88 -26
- package/dist/{el-XOH4QIAG.js → el-45T257AL.js} +88 -26
- package/dist/{en-3FCBW3YD.js → en-RVW5EQ66.js} +4 -2
- package/dist/{es-HDX4QI7E.js → es-AVER7RU4.js} +88 -26
- package/dist/{fa-DJ6WTFTJ.js → fa-K3VPK3O2.js} +88 -26
- package/dist/{fi-4S7H7W7U.js → fi-5NEKF7EB.js} +88 -26
- package/dist/{fr-6UJSYHXC.js → fr-FUMNDLBZ.js} +88 -26
- package/dist/{he-ZZJOHJX2.js → he-3JGNA3PR.js} +88 -26
- package/dist/{hi-HZJTAW7U.js → hi-IJY375DF.js} +88 -26
- package/dist/{id-E3I6ILEM.js → id-LWHKJ7ZD.js} +88 -26
- package/dist/index.css +380 -524
- package/dist/index.d.ts +318 -192
- package/dist/index.js +2960 -2421
- package/dist/integrations/css-modules-helper.js +1 -3
- package/dist/{it-ULAPAD7U.js → it-EBVOV4RW.js} +88 -26
- package/dist/{ja-SAHZQ4CZ.js → ja-KWRIX2NF.js} +88 -26
- package/dist/{ko-DFU2ADQ4.js → ko-L5CJMFDS.js} +88 -26
- package/dist/{ms-NWL76XNT.js → ms-LSNMJDR2.js} +88 -26
- package/dist/{nl-ATCM76WN.js → nl-ZB32MB7U.js} +88 -26
- package/dist/{no-UIAQ5RJF.js → no-4GTNY7M5.js} +88 -26
- package/dist/{pl-NOECQDXD.js → pl-LUHBLTHB.js} +88 -26
- package/dist/{pt-SVWIIUPC.js → pt-C4H3UNQ6.js} +88 -26
- package/dist/{ro-NR2DRTZG.js → ro-GGITS5V4.js} +88 -26
- package/dist/{sv-STVJ37JP.js → sv-T56RTLBP.js} +88 -26
- package/dist/test-utils.css +1 -1
- package/dist/test-utils.d.ts +1 -1
- package/dist/test-utils.js +2 -2
- package/dist/{th-UWQR4K54.js → th-22X2IWCB.js} +88 -26
- package/dist/{tr-WNXZSD27.js → tr-77TFG62H.js} +88 -26
- package/dist/{uk-SJRMB47Y.js → uk-MIIL6NXT.js} +88 -26
- package/dist/{vi-TMRQFES2.js → vi-7JYOIGNV.js} +88 -26
- package/dist/{zh-QOL3LYEM.js → zh-ID6DRYU4.js} +88 -26
- package/package.json +11 -10
- package/src/components/AssistProgress.tsx +178 -134
- package/src/components/CodeMirrorRenderer.tsx +8 -8
- package/src/components/{EntityFoundLog.tsx → ItemFoundLog.tsx} +12 -7
- package/src/components/ProtectedErrorBoundary.css +3 -1
- package/src/components/StatusDisplay.css +1 -1
- package/src/components/Toast.css +3 -1
- package/src/components/__tests__/AssistProgress.test.tsx +268 -141
- package/src/components/annotation/annotation-entries.css +0 -4
- package/src/components/annotation/references.css +0 -4
- package/src/components/image-annotation/AnnotationOverlay.tsx +6 -6
- package/src/components/image-annotation/SvgDrawingCanvas.tsx +1 -1
- package/src/components/image-annotation/__tests__/AnnotationOverlay.click.test.tsx +7 -9
- package/src/components/image-annotation/__tests__/SvgDrawingCanvas.click.test.tsx +1 -2
- package/src/components/layout/Header.css +0 -4
- package/src/components/layout/LeftSidebar.css +0 -4
- package/src/components/modals/ComposeStep.tsx +218 -0
- package/src/components/modals/ConfigureGatherStep.tsx +10 -18
- package/src/components/modals/ConfigureGenerationStep.tsx +131 -54
- package/src/components/modals/ConfigureSearchStep.tsx +42 -40
- package/src/components/modals/ContextSummary.tsx +185 -72
- package/src/components/modals/CorpusPane.tsx +75 -0
- package/src/components/modals/DiscardPrompt.tsx +38 -0
- package/src/components/modals/GatherContextStep.tsx +237 -107
- package/src/components/modals/ReferenceWizardModal.tsx +287 -60
- package/src/components/modals/ResourceGenerateModal.tsx +233 -109
- package/src/components/modals/SearchModal.css +335 -111
- package/src/components/modals/SearchModal.tsx +1 -1
- package/src/components/modals/SearchResultsStep.tsx +63 -88
- package/src/components/modals/WizardFooter.tsx +69 -0
- package/src/components/modals/__tests__/ComposeStep.test.tsx +152 -0
- package/src/components/modals/__tests__/ConfigureGatherStep.test.tsx +14 -26
- package/src/components/modals/__tests__/ConfigureGenerationStep.test.tsx +290 -0
- package/src/components/modals/__tests__/ConfigureSearchStep.test.tsx +95 -0
- package/src/components/modals/__tests__/GatherContextStep.resource.test.tsx +463 -25
- package/src/components/modals/__tests__/ReferenceWizardModal.test.tsx +635 -0
- package/src/components/modals/__tests__/ResourceGenerateModal.test.tsx +277 -85
- package/src/components/modals/__tests__/SearchModal.search-wiring.test.tsx +6 -2
- package/src/components/modals/__tests__/SearchResultsStep.test.tsx +61 -0
- package/src/components/modals/__tests__/WizardFooter.test.tsx +344 -0
- package/src/components/modals/modals.css +16 -42
- package/src/components/navigation/NavigationTabs.css +0 -20
- package/src/components/pdf-annotation/PdfAnnotationCanvas.css +21 -2
- package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +36 -3
- package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +41 -6
- package/src/components/resource/AnnotateView.tsx +19 -8
- package/src/components/resource/AnnotationHistory.tsx +2 -0
- package/src/components/resource/BrowseView.tsx +20 -9
- package/src/components/resource/ResourceViewer.tsx +27 -28
- package/src/components/resource/__tests__/AnnotateView.embeddable.test.tsx +1 -1
- package/src/components/resource/__tests__/AnnotateView.focus.test.tsx +50 -0
- package/src/components/resource/__tests__/AnnotationHistory.test.tsx +2 -0
- package/src/components/resource/__tests__/BrowseView.embeddable.test.tsx +1 -1
- package/src/components/resource/__tests__/BrowseView.test.tsx +38 -12
- package/src/components/resource/__tests__/ResourceViewer.embeddable.test.tsx +47 -3
- package/src/components/resource/annotate-renderers.tsx +3 -3
- package/src/components/resource/event-formatting.ts +0 -3
- package/src/components/resource/panels/AssessmentEntry.tsx +1 -1
- package/src/components/resource/panels/AssessmentPanel.css +5 -6
- package/src/components/resource/panels/AssistSection.css +95 -263
- package/src/components/resource/panels/AssistSection.tsx +4 -4
- package/src/components/resource/panels/AssistShell.tsx +12 -4
- package/src/components/resource/panels/CollaborationPanel.css +47 -22
- package/src/components/resource/panels/CollaborationPanel.tsx +93 -2
- package/src/components/resource/panels/CommentEntry.tsx +1 -1
- package/src/components/resource/panels/CommentsPanel.css +0 -16
- package/src/components/resource/panels/HighlightEntry.tsx +1 -1
- package/src/components/resource/panels/HighlightPanel.css +0 -7
- package/src/components/resource/panels/JsonLdPanel.css +0 -4
- package/src/components/resource/panels/ReferenceEntry.tsx +10 -3
- package/src/components/resource/panels/ReferencesPanel.css +0 -12
- package/src/components/resource/panels/ReferencesPanel.tsx +16 -20
- package/src/components/resource/panels/ResourceInfoPanel.css +0 -32
- package/src/components/resource/panels/ResourceInfoPanel.tsx +89 -20
- package/src/components/resource/panels/StatisticsPanel.css +0 -20
- package/src/components/resource/panels/TagEntry.tsx +1 -1
- package/src/components/resource/panels/TaggingPanel.css +0 -4
- package/src/components/resource/panels/TaggingPanel.tsx +2 -10
- package/src/components/resource/panels/UnifiedAnnotationsPanel.css +0 -4
- package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +7 -2
- package/src/components/resource/panels/__tests__/AssessmentEntry.test.tsx +0 -1
- package/src/components/resource/panels/__tests__/AssistSection.test.tsx +48 -50
- package/src/components/resource/panels/__tests__/AssistShell.test.tsx +11 -6
- package/src/components/resource/panels/__tests__/CollaborationPanel.test.tsx +89 -0
- package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +1 -2
- package/src/components/resource/panels/__tests__/HighlightEntry.test.tsx +0 -1
- package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +44 -36
- package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +41 -1
- package/src/components/resource/panels/__tests__/ReferencesPanel.headless.test.tsx +1 -1
- package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +67 -54
- package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +185 -7
- package/src/components/resource/panels/__tests__/TagEntry.test.tsx +0 -1
- package/src/components/settings/SettingsPanel.css +0 -4
- package/src/features/auth/auth.css +2 -26
- package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +0 -65
- package/src/features/resource-compose/components/ResourceComposePage.tsx +17 -130
- package/src/features/resource-compose/state/__tests__/compose-page-state-unit.test.ts +1 -76
- package/src/features/resource-compose/state/compose-page-state-unit.ts +5 -48
- package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +55 -0
- package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +29 -0
- package/src/features/resource-discovery/state/__tests__/discover-state-unit.test.ts +53 -3
- package/src/features/resource-discovery/state/discover-state-unit.ts +29 -8
- package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +71 -15
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +166 -71
- package/src/features/resource-viewer/hooks/__tests__/useResourceViewedReport.test.tsx +63 -0
- package/src/features/resource-viewer/hooks/useResourceViewedReport.ts +33 -0
- package/src/features/resource-viewer/state/__tests__/resource-viewer-page-state-unit.test.ts +2 -2
- package/src/features/resource-viewer/state/resource-viewer-page-state-unit.ts +1 -1
- package/src/styles/core/buttons.css +3 -1
- package/src/styles/core/forms.css +35 -29
- package/src/styles/core/indicators.css +0 -4
- package/src/styles/core/inputs.css +0 -4
- package/src/styles/core/progress.css +2 -34
- package/src/styles/core/sliders.css +0 -4
- package/src/styles/core/toggles.css +0 -4
- package/src/styles/features/resource-discovery.css +13 -0
- package/src/styles/features/resource-viewer.css +0 -42
- package/src/styles/features/resource.css +0 -4
- package/src/styles/motivations/motivation-assessment.css +2 -2
- package/src/styles/panels/history-panel.css +0 -40
- package/src/styles/panels/user-panel.css +0 -3
- package/src/styles/patterns/panel-helpers.css +0 -27
- package/src/styles/patterns/panel-sections.css +0 -59
- package/src/styles/patterns/panels-base.css +0 -32
- package/translations/ar.json +84 -24
- package/translations/bn.json +84 -24
- package/translations/cs.json +84 -24
- package/translations/da.json +84 -24
- package/translations/de.json +84 -24
- package/translations/el.json +84 -24
- package/translations/en.json +84 -24
- package/translations/es.json +84 -24
- package/translations/fa.json +84 -24
- package/translations/fi.json +84 -24
- package/translations/fr.json +84 -24
- package/translations/he.json +84 -24
- package/translations/hi.json +84 -24
- package/translations/id.json +84 -24
- package/translations/it.json +84 -24
- package/translations/ja.json +84 -24
- package/translations/ko.json +84 -24
- package/translations/ms.json +84 -24
- package/translations/nl.json +84 -24
- package/translations/no.json +84 -24
- package/translations/pl.json +84 -24
- package/translations/pt.json +84 -24
- package/translations/ro.json +84 -24
- package/translations/sv.json +84 -24
- package/translations/th.json +84 -24
- package/translations/tr.json +84 -24
- package/translations/uk.json +84 -24
- package/translations/vi.json +84 -24
- package/translations/zh.json +84 -24
- package/dist/PdfAnnotationCanvas.client-6ZSF6ZTJ.js.map +0 -1
- package/dist/PdfAnnotationCanvas.client-JCJMXWWJ.css.map +0 -1
- package/dist/ar-YTUUGK2O.js.map +0 -1
- package/dist/bn-ASGNGPMD.js.map +0 -1
- package/dist/chunk-BTUG3VJJ.js.map +0 -1
- package/dist/chunk-L3WKRWP3.js.map +0 -1
- package/dist/chunk-O23TLLXW.js.map +0 -1
- package/dist/chunk-OBQOZCJE.js.map +0 -1
- package/dist/chunk-QT7LYM72.js.map +0 -1
- package/dist/chunk-VXASXU4K.js.map +0 -1
- package/dist/chunk-XUDKYAVC.js +0 -21
- package/dist/chunk-XUDKYAVC.js.map +0 -1
- package/dist/cs-WMYVAOZY.js.map +0 -1
- package/dist/da-FSHHN4D6.js.map +0 -1
- package/dist/de-FJFO3TPT.js.map +0 -1
- package/dist/el-XOH4QIAG.js.map +0 -1
- package/dist/en-3FCBW3YD.js.map +0 -1
- package/dist/es-HDX4QI7E.js.map +0 -1
- package/dist/fa-DJ6WTFTJ.js.map +0 -1
- package/dist/fi-4S7H7W7U.js.map +0 -1
- package/dist/fr-6UJSYHXC.js.map +0 -1
- package/dist/he-ZZJOHJX2.js.map +0 -1
- package/dist/hi-HZJTAW7U.js.map +0 -1
- package/dist/id-E3I6ILEM.js.map +0 -1
- package/dist/index.css.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/integrations/css-modules-helper.js.map +0 -1
- package/dist/integrations/styled-components-theme.js.map +0 -1
- package/dist/it-ULAPAD7U.js.map +0 -1
- package/dist/ja-SAHZQ4CZ.js.map +0 -1
- package/dist/ko-DFU2ADQ4.js.map +0 -1
- package/dist/ms-NWL76XNT.js.map +0 -1
- package/dist/nl-ATCM76WN.js.map +0 -1
- package/dist/no-UIAQ5RJF.js.map +0 -1
- package/dist/pl-NOECQDXD.js.map +0 -1
- package/dist/pt-SVWIIUPC.js.map +0 -1
- package/dist/ro-NR2DRTZG.js.map +0 -1
- package/dist/sv-STVJ37JP.js.map +0 -1
- package/dist/test-utils.css.map +0 -1
- package/dist/test-utils.js.map +0 -1
- package/dist/th-UWQR4K54.js.map +0 -1
- package/dist/tr-WNXZSD27.js.map +0 -1
- package/dist/uk-SJRMB47Y.js.map +0 -1
- package/dist/vi-TMRQFES2.js.map +0 -1
- package/dist/zh-QOL3LYEM.js.map +0 -1
- package/src/components/modals/ResourceSearchModal.tsx +0 -224
- package/src/components/modals/__tests__/ResourceSearchModal.test.tsx +0 -159
- package/src/integrations/tailwind-plugin.cjs +0 -224
|
@@ -2,8 +2,10 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
4
4
|
import '@testing-library/jest-dom';
|
|
5
|
-
import
|
|
6
|
-
import type {
|
|
5
|
+
import { BehaviorSubject } from 'rxjs';
|
|
6
|
+
import type { EventBus, ResourceDescriptor } from '@semiont/core';
|
|
7
|
+
import { resourceId as makeResourceId } from '@semiont/core';
|
|
8
|
+
import type { CacheObservable, CacheState, SemiontClient, SemiontSession } from '@semiont/sdk';
|
|
7
9
|
import { ResourceInfoPanel } from '../ResourceInfoPanel';
|
|
8
10
|
import { createTestSemiontWrapper } from '../../../../test-utils';
|
|
9
11
|
|
|
@@ -95,7 +97,9 @@ const renderWithEventBus = (component: React.ReactElement<{ session: SemiontSess
|
|
|
95
97
|
);
|
|
96
98
|
// The component is provider-free: inject the factory session so it is the
|
|
97
99
|
// SAME session whose client the tracker spies on / whose bus it subscribes.
|
|
98
|
-
|
|
100
|
+
// The injected session/client are returned too: a test that spies on what the
|
|
101
|
+
// panel calls has to spy on THIS client, not a second factory's.
|
|
102
|
+
return { ...render(React.cloneElement(component, { session }), { wrapper: Wrapper }), session, client };
|
|
99
103
|
};
|
|
100
104
|
|
|
101
105
|
describe('ResourceInfoPanel Component', () => {
|
|
@@ -279,17 +283,19 @@ describe('ResourceInfoPanel Component', () => {
|
|
|
279
283
|
});
|
|
280
284
|
|
|
281
285
|
describe('Generate Action', () => {
|
|
286
|
+
// The shell's collapsible header is ALSO a button named "Generate", so the
|
|
287
|
+
// form control is targeted by its exact accessible name (the ✨ is part of it).
|
|
282
288
|
it('renders the Generate button when onGenerate is provided', () => {
|
|
283
289
|
renderWithEventBus(
|
|
284
290
|
<ResourceInfoPanel {...defaultProps} onGenerate={() => {}} />
|
|
285
291
|
);
|
|
286
|
-
expect(screen.getByRole('button', { name:
|
|
292
|
+
expect(screen.getByRole('button', { name: '✨ Generate' })).toBeInTheDocument();
|
|
287
293
|
expect(screen.getByText("Generate a new resource from this one's context")).toBeInTheDocument();
|
|
288
294
|
});
|
|
289
295
|
|
|
290
296
|
it('hides the Generate button when onGenerate is omitted', () => {
|
|
291
297
|
renderWithEventBus(<ResourceInfoPanel {...defaultProps} />);
|
|
292
|
-
expect(screen.queryByRole('button', { name:
|
|
298
|
+
expect(screen.queryByRole('button', { name: '✨ Generate' })).not.toBeInTheDocument();
|
|
293
299
|
});
|
|
294
300
|
|
|
295
301
|
it('calls onGenerate when clicked', () => {
|
|
@@ -297,9 +303,117 @@ describe('ResourceInfoPanel Component', () => {
|
|
|
297
303
|
renderWithEventBus(
|
|
298
304
|
<ResourceInfoPanel {...defaultProps} onGenerate={onGenerate} />
|
|
299
305
|
);
|
|
300
|
-
fireEvent.click(screen.getByRole('button', { name:
|
|
306
|
+
fireEvent.click(screen.getByRole('button', { name: '✨ Generate' }));
|
|
301
307
|
expect(onGenerate).toHaveBeenCalledTimes(1);
|
|
302
308
|
});
|
|
309
|
+
|
|
310
|
+
// ── GENERATE-FROM-RESOURCE P2 (D7/D8): the panel is the progress surface ──
|
|
311
|
+
|
|
312
|
+
it('the Generate control lives inside the assist shell (D7)', () => {
|
|
313
|
+
const { container } = renderWithEventBus(
|
|
314
|
+
<ResourceInfoPanel {...defaultProps} onGenerate={() => {}}
|
|
315
|
+
isGenerating={false} generationProgress={null} />
|
|
316
|
+
);
|
|
317
|
+
const shell = container.querySelector('.semiont-assist-widget[data-type="generation"]');
|
|
318
|
+
expect(shell).not.toBeNull();
|
|
319
|
+
expect(shell!.querySelector('button')).not.toBeNull(); // the form IS the Generate control
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it('progress replaces the Generate form while a generation runs', () => {
|
|
323
|
+
const { container } = renderWithEventBus(
|
|
324
|
+
<ResourceInfoPanel {...defaultProps} onGenerate={() => {}}
|
|
325
|
+
isGenerating
|
|
326
|
+
generationProgress={{ percentage: 40, message: { code: 'generating-resource' } }} />
|
|
327
|
+
);
|
|
328
|
+
expect(container.querySelector('.semiont-assist-progress')).not.toBeNull();
|
|
329
|
+
expect(screen.queryByRole('button', { name: '✨ Generate' })).toBeNull();
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('the ended frame links the generated resource by name, and dismisses (D8)', () => {
|
|
333
|
+
const onDismissProgress = vi.fn();
|
|
334
|
+
const { client } = renderWithEventBus(
|
|
335
|
+
<ResourceInfoPanel {...defaultProps} onGenerate={() => {}}
|
|
336
|
+
isGenerating={false}
|
|
337
|
+
generationProgress={{ percentage: 100, message: { code: 'complete-generated', truncated: false } }}
|
|
338
|
+
generationOutcome={{
|
|
339
|
+
resourceId: makeResourceId('urn:semiont:resource:new1'),
|
|
340
|
+
resourceName: 'Summary of PB',
|
|
341
|
+
truncated: false,
|
|
342
|
+
}}
|
|
343
|
+
onDismissProgress={onDismissProgress} />
|
|
344
|
+
);
|
|
345
|
+
const openSpy = vi.spyOn(client.browse, 'openResource');
|
|
346
|
+
|
|
347
|
+
fireEvent.click(screen.getByRole('button', { name: 'Summary of PB' }));
|
|
348
|
+
expect(openSpy).toHaveBeenCalledTimes(1);
|
|
349
|
+
expect(String(openSpy.mock.calls[0]![0])).toBe('urn:semiont:resource:new1');
|
|
350
|
+
|
|
351
|
+
fireEvent.click(screen.getByTestId('semiont-assist-control'));
|
|
352
|
+
expect(onDismissProgress).toHaveBeenCalledTimes(1);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('a truncated completion says so; a natural stop does not (GFR P3b, D6)', () => {
|
|
356
|
+
// The mocked translator echoes unknown keys, so the assertion reads the
|
|
357
|
+
// KEY the real assistProgressCopy branch picked — structure, not copy.
|
|
358
|
+
const base = { ...defaultProps, onGenerate: () => {}, isGenerating: false };
|
|
359
|
+
const { unmount } = renderWithEventBus(
|
|
360
|
+
<ResourceInfoPanel {...base}
|
|
361
|
+
generationProgress={{ percentage: 100, message: { code: 'complete-generated', truncated: true } }} />
|
|
362
|
+
);
|
|
363
|
+
expect(screen.getByTestId('semiont-assist-status').textContent)
|
|
364
|
+
.toContain('codeCompleteGeneratedTruncated');
|
|
365
|
+
unmount();
|
|
366
|
+
|
|
367
|
+
renderWithEventBus(
|
|
368
|
+
<ResourceInfoPanel {...base}
|
|
369
|
+
generationProgress={{ percentage: 100, message: { code: 'complete-generated', truncated: false } }} />
|
|
370
|
+
);
|
|
371
|
+
expect(screen.getByTestId('semiont-assist-status').textContent)
|
|
372
|
+
.toContain('codeCompleteGenerated');
|
|
373
|
+
expect(screen.getByTestId('semiont-assist-status').textContent)
|
|
374
|
+
.not.toContain('Truncated');
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('the ended frame speaks completion even when the final progress frame lost the race (GENERATION-ARRIVAL D4/D5)', () => {
|
|
378
|
+
// The screenshot case: last frame is the 95% "creating" payload, the
|
|
379
|
+
// terminal 100% frame never arrived — but the outcome did. The sentence
|
|
380
|
+
// derives from the OUTCOME, not the racing frame.
|
|
381
|
+
renderWithEventBus(
|
|
382
|
+
<ResourceInfoPanel {...defaultProps} onGenerate={() => {}}
|
|
383
|
+
isGenerating={false}
|
|
384
|
+
generationProgress={{ percentage: 95, message: { code: 'creating-resource' } }}
|
|
385
|
+
generationOutcome={{
|
|
386
|
+
resourceId: makeResourceId('urn:semiont:resource:new1'),
|
|
387
|
+
resourceName: 'Summary of PB',
|
|
388
|
+
truncated: false,
|
|
389
|
+
}} />
|
|
390
|
+
);
|
|
391
|
+
expect(screen.getByTestId('semiont-assist-status').textContent).toBe('codeCompleteGenerated');
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it('a truncated outcome says so — the bit rides the outcome, not the racing frame (D5)', () => {
|
|
395
|
+
renderWithEventBus(
|
|
396
|
+
<ResourceInfoPanel {...defaultProps} onGenerate={() => {}}
|
|
397
|
+
isGenerating={false}
|
|
398
|
+
generationProgress={{ percentage: 95, message: { code: 'creating-resource' } }}
|
|
399
|
+
generationOutcome={{
|
|
400
|
+
resourceId: makeResourceId('urn:semiont:resource:new1'),
|
|
401
|
+
resourceName: 'Summary of PB',
|
|
402
|
+
truncated: true,
|
|
403
|
+
}} />
|
|
404
|
+
);
|
|
405
|
+
expect(screen.getByTestId('semiont-assist-status').textContent).toBe('codeCompleteGeneratedTruncated');
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('no outcome, no link: the ended frame renders without one until job:complete arrives', () => {
|
|
409
|
+
renderWithEventBus(
|
|
410
|
+
<ResourceInfoPanel {...defaultProps} onGenerate={() => {}}
|
|
411
|
+
isGenerating={false}
|
|
412
|
+
generationProgress={{ percentage: 100, message: { code: 'complete-generated', truncated: false } }}
|
|
413
|
+
generationOutcome={null} />
|
|
414
|
+
);
|
|
415
|
+
expect(screen.queryByText('Summary of PB')).toBeNull();
|
|
416
|
+
});
|
|
303
417
|
});
|
|
304
418
|
|
|
305
419
|
describe('Provenance Section', () => {
|
|
@@ -348,7 +462,9 @@ describe('ResourceInfoPanel Component', () => {
|
|
|
348
462
|
expect(screen.getByText('Alice, Bob')).toBeInTheDocument();
|
|
349
463
|
});
|
|
350
464
|
|
|
351
|
-
it('should render wasDerivedFrom when provided', () => {
|
|
465
|
+
it('should render wasDerivedFrom when provided — the id is the unresolved fallback', () => {
|
|
466
|
+
// The factory client's fetch fails in jsdom (no server), so the
|
|
467
|
+
// descriptor never resolves and the raw id stays as the honest label.
|
|
352
468
|
renderWithEventBus(
|
|
353
469
|
<ResourceInfoPanel
|
|
354
470
|
{...defaultProps}
|
|
@@ -359,6 +475,68 @@ describe('ResourceInfoPanel Component', () => {
|
|
|
359
475
|
expect(screen.getByText('urn:semiont:resource:abc123')).toBeInTheDocument();
|
|
360
476
|
});
|
|
361
477
|
|
|
478
|
+
it('a derived-from id is a LINK, and clicking it opens that resource', () => {
|
|
479
|
+
// Rendering the id is half the feature; the provenance chain is only
|
|
480
|
+
// walkable if the id navigates. The click goes through the session's
|
|
481
|
+
// client, so a panel handed no session must not throw either — the
|
|
482
|
+
// optional chain below is load-bearing, not defensive noise.
|
|
483
|
+
// `renderWithEventBus` injects its own per-test session via cloneElement,
|
|
484
|
+
// so the spy has to go on THAT client — one created here would never be
|
|
485
|
+
// the one the button calls.
|
|
486
|
+
const { client } = renderWithEventBus(
|
|
487
|
+
<ResourceInfoPanel
|
|
488
|
+
{...defaultProps}
|
|
489
|
+
wasDerivedFrom="urn:semiont:resource:abc123"
|
|
490
|
+
/>
|
|
491
|
+
);
|
|
492
|
+
const openSpy = vi.spyOn(client.browse, 'openResource');
|
|
493
|
+
|
|
494
|
+
fireEvent.click(screen.getByText('urn:semiont:resource:abc123'));
|
|
495
|
+
expect(openSpy).toHaveBeenCalledTimes(1);
|
|
496
|
+
expect(String(openSpy.mock.calls[0]![0])).toBe('urn:semiont:resource:abc123');
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
it('resolves the derived-from id to its resource NAME; clicks still navigate by id', () => {
|
|
500
|
+
// The id is wire identity, not presentation. Once `browse.resource`
|
|
501
|
+
// serves the source's descriptor, the link wears its name — the raw
|
|
502
|
+
// hash only survives while the descriptor is unresolved (pin below).
|
|
503
|
+
const { SemiontWrapper, session, client } = createTestSemiontWrapper();
|
|
504
|
+
vi.spyOn(client.browse, 'resource').mockReturnValue(
|
|
505
|
+
new BehaviorSubject<CacheState<ResourceDescriptor>>({
|
|
506
|
+
status: 'ready',
|
|
507
|
+
value: { '@id': 'urn:semiont:resource:abc123', name: 'Source Doc' } as ResourceDescriptor,
|
|
508
|
+
}) as unknown as CacheObservable<ResourceDescriptor>,
|
|
509
|
+
);
|
|
510
|
+
const openSpy = vi.spyOn(client.browse, 'openResource');
|
|
511
|
+
render(
|
|
512
|
+
<ResourceInfoPanel
|
|
513
|
+
{...defaultProps}
|
|
514
|
+
session={session}
|
|
515
|
+
wasDerivedFrom="urn:semiont:resource:abc123"
|
|
516
|
+
/>,
|
|
517
|
+
{ wrapper: ({ children }) => <SemiontWrapper>{children}</SemiontWrapper> },
|
|
518
|
+
);
|
|
519
|
+
|
|
520
|
+
expect(screen.getByText('Source Doc')).toBeInTheDocument();
|
|
521
|
+
expect(screen.queryByText('urn:semiont:resource:abc123')).toBeNull();
|
|
522
|
+
|
|
523
|
+
fireEvent.click(screen.getByText('Source Doc'));
|
|
524
|
+
expect(String(openSpy.mock.calls[0]![0])).toBe('urn:semiont:resource:abc123');
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
it('renders every id when the resource derives from several', () => {
|
|
528
|
+
renderWithEventBus(
|
|
529
|
+
<ResourceInfoPanel
|
|
530
|
+
{...defaultProps}
|
|
531
|
+
wasDerivedFrom={['urn:semiont:resource:a', 'urn:semiont:resource:b'] as never}
|
|
532
|
+
/>
|
|
533
|
+
);
|
|
534
|
+
// The separator lives inside the button (`{i > 0 && ', '}{id}`), so the
|
|
535
|
+
// second one's text node is ", urn:…:b" — matched loosely on purpose.
|
|
536
|
+
expect(screen.getByText(/urn:semiont:resource:a/)).toBeInTheDocument();
|
|
537
|
+
expect(screen.getByText(/urn:semiont:resource:b/)).toBeInTheDocument();
|
|
538
|
+
});
|
|
539
|
+
|
|
362
540
|
it('falls back to generator for attribution when wasAttributedTo is absent', () => {
|
|
363
541
|
renderWithEventBus(
|
|
364
542
|
<ResourceInfoPanel
|
|
@@ -53,19 +53,11 @@
|
|
|
53
53
|
margin-bottom: 0.5rem;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
[data-theme="dark"] .semiont-auth__welcome {
|
|
57
|
-
color: var(--semiont-text-primary);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
56
|
.semiont-auth__subtitle {
|
|
61
57
|
font-size: 1rem;
|
|
62
58
|
color: var(--semiont-text-secondary);
|
|
63
59
|
}
|
|
64
60
|
|
|
65
|
-
[data-theme="dark"] .semiont-auth__subtitle {
|
|
66
|
-
color: var(--semiont-text-secondary);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
61
|
/* Error display */
|
|
70
62
|
.semiont-auth__error-container {
|
|
71
63
|
margin-bottom: 1.5rem;
|
|
@@ -129,10 +121,6 @@
|
|
|
129
121
|
letter-spacing: 0.05em;
|
|
130
122
|
}
|
|
131
123
|
|
|
132
|
-
[data-theme="dark"] .semiont-auth__divider-text {
|
|
133
|
-
color: var(--semiont-text-secondary);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
124
|
/* Info text */
|
|
137
125
|
.semiont-auth__info {
|
|
138
126
|
text-align: center;
|
|
@@ -227,10 +215,6 @@
|
|
|
227
215
|
margin-bottom: 0.5rem;
|
|
228
216
|
}
|
|
229
217
|
|
|
230
|
-
[data-theme="dark"] .semiont-auth__signup-title {
|
|
231
|
-
color: var(--semiont-text-primary);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
218
|
.semiont-auth__signup-content {
|
|
235
219
|
display: flex;
|
|
236
220
|
flex-direction: column;
|
|
@@ -244,10 +228,6 @@
|
|
|
244
228
|
line-height: 1.5;
|
|
245
229
|
}
|
|
246
230
|
|
|
247
|
-
[data-theme="dark"] .semiont-auth__signup-info {
|
|
248
|
-
color: var(--semiont-text-secondary);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
231
|
.semiont-auth__signup-footer {
|
|
252
232
|
text-align: center;
|
|
253
233
|
padding-top: 1rem;
|
|
@@ -350,16 +330,12 @@
|
|
|
350
330
|
display: inline-block;
|
|
351
331
|
}
|
|
352
332
|
|
|
353
|
-
[data-theme="dark"] .semiont-form__url-status--checking {
|
|
354
|
-
color: var(--semiont-text-tertiary);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
333
|
.semiont-form__url-status--ok {
|
|
358
334
|
color: var(--semiont-color-success);
|
|
359
335
|
}
|
|
360
336
|
|
|
361
337
|
[data-theme="dark"] .semiont-form__url-status--ok {
|
|
362
|
-
color: var(--semiont-color-success);
|
|
338
|
+
color: var(--semiont-color-success-light);
|
|
363
339
|
}
|
|
364
340
|
|
|
365
341
|
.semiont-form__url-status--error {
|
|
@@ -367,5 +343,5 @@
|
|
|
367
343
|
}
|
|
368
344
|
|
|
369
345
|
[data-theme="dark"] .semiont-form__url-status--error {
|
|
370
|
-
color: var(--semiont-color-error);
|
|
346
|
+
color: var(--semiont-color-error-light);
|
|
371
347
|
}
|
|
@@ -28,10 +28,7 @@ vi.mock('../../../components/CodeMirrorRenderer', () => ({
|
|
|
28
28
|
const createMockTranslations = () => ({
|
|
29
29
|
title: 'Compose Resource',
|
|
30
30
|
titleEditClone: 'Edit Cloned Resource',
|
|
31
|
-
titleCompleteReference: 'Complete Reference',
|
|
32
31
|
subtitleClone: 'Editing a cloned resource',
|
|
33
|
-
subtitleReference: 'Creating a new resource for reference',
|
|
34
|
-
linkedNoticePrefix: 'This resource will be linked',
|
|
35
32
|
resourceName: 'Resource Name',
|
|
36
33
|
resourceNamePlaceholder: 'Enter resource name',
|
|
37
34
|
entityTypes: 'Entity Types',
|
|
@@ -53,9 +50,7 @@ const createMockTranslations = () => ({
|
|
|
53
50
|
cancel: 'Cancel',
|
|
54
51
|
saving: 'Saving...',
|
|
55
52
|
creating: 'Creating...',
|
|
56
|
-
creatingAndLinking: 'Creating and linking...',
|
|
57
53
|
saveClonedResource: 'Save Cloned Resource',
|
|
58
|
-
createAndLinkResource: 'Create and Link Resource',
|
|
59
54
|
createResource: 'Create Resource',
|
|
60
55
|
});
|
|
61
56
|
|
|
@@ -207,66 +202,6 @@ describe('ResourceComposePage', () => {
|
|
|
207
202
|
});
|
|
208
203
|
});
|
|
209
204
|
|
|
210
|
-
describe('Reference Completion Mode', () => {
|
|
211
|
-
it('shows reference completion title', () => {
|
|
212
|
-
const props = createMockProps({
|
|
213
|
-
mode: 'reference',
|
|
214
|
-
referenceData: {
|
|
215
|
-
annotationUri: 'http://localhost:8080/annotations/ref-1',
|
|
216
|
-
sourceDocumentId: 'doc-1',
|
|
217
|
-
name: 'Referenced Resource',
|
|
218
|
-
entityTypes: ['Document'],
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
renderWithProviders(<ResourceComposePage {...props} />);
|
|
222
|
-
|
|
223
|
-
expect(screen.getByText('Complete Reference')).toBeInTheDocument();
|
|
224
|
-
expect(screen.getByText('Creating a new resource for reference')).toBeInTheDocument();
|
|
225
|
-
expect(screen.getByText('This resource will be linked')).toBeInTheDocument();
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it('initializes with reference data', () => {
|
|
229
|
-
const props = createMockProps({
|
|
230
|
-
mode: 'reference',
|
|
231
|
-
referenceData: {
|
|
232
|
-
annotationUri: 'http://localhost:8080/annotations/ref-1',
|
|
233
|
-
sourceDocumentId: 'doc-1',
|
|
234
|
-
name: 'Referenced Resource',
|
|
235
|
-
entityTypes: ['Document', 'Article'],
|
|
236
|
-
},
|
|
237
|
-
});
|
|
238
|
-
renderWithProviders(<ResourceComposePage {...props} />);
|
|
239
|
-
|
|
240
|
-
const nameInput = screen.getByLabelText('Resource Name') as HTMLInputElement;
|
|
241
|
-
expect(nameInput.value).toBe('Referenced Resource');
|
|
242
|
-
|
|
243
|
-
expect(screen.getByText('Document')).toBeInTheDocument();
|
|
244
|
-
expect(screen.getByText('Article')).toBeInTheDocument();
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('shows entity types as read-only when provided', () => {
|
|
248
|
-
const props = createMockProps({
|
|
249
|
-
mode: 'reference',
|
|
250
|
-
referenceData: {
|
|
251
|
-
annotationUri: 'http://localhost:8080/annotations/ref-1',
|
|
252
|
-
sourceDocumentId: 'doc-1',
|
|
253
|
-
name: 'Referenced Resource',
|
|
254
|
-
entityTypes: ['Document'],
|
|
255
|
-
},
|
|
256
|
-
});
|
|
257
|
-
renderWithProviders(<ResourceComposePage {...props} />);
|
|
258
|
-
|
|
259
|
-
// Should show read-only entity types
|
|
260
|
-
expect(screen.getByText('Document')).toBeInTheDocument();
|
|
261
|
-
|
|
262
|
-
// Should not show selectable buttons
|
|
263
|
-
expect(screen.queryByRole('button', { name: /Document entity type/ })).not.toBeInTheDocument();
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
// Entity Type Selection tests removed - functionality not present in current component
|
|
268
|
-
// The component only displays entity types in reference mode, doesn't have selection buttons
|
|
269
|
-
|
|
270
205
|
describe('Content Input Method', () => {
|
|
271
206
|
it('defaults to write mode', () => {
|
|
272
207
|
const props = createMockProps();
|