@happyvertical/smrt-svelte 0.53.1 → 0.53.3
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/package.json +15 -15
- package/dist/__tests__/app-state.test.js +0 -156
- package/dist/__tests__/data-surface-bridge.test.js +0 -351
- package/dist/__tests__/provider-mode-harness.svelte +0 -14
- package/dist/__tests__/provider-mode-harness.svelte.d.ts +0 -11
- package/dist/__tests__/provider-mode-harness.svelte.d.ts.map +0 -1
- package/dist/__tests__/provider-mode-probe.svelte +0 -13
- package/dist/__tests__/provider-mode-probe.svelte.d.ts +0 -8
- package/dist/__tests__/provider-mode-probe.svelte.d.ts.map +0 -1
- package/dist/__tests__/provider-webmcp-harness.svelte +0 -14
- package/dist/__tests__/provider-webmcp-harness.svelte.d.ts +0 -8
- package/dist/__tests__/provider-webmcp-harness.svelte.d.ts.map +0 -1
- package/dist/__tests__/success-never-text.test.js +0 -100
- package/dist/__tests__/warm-clients.test.js +0 -186
- package/dist/browser-ai/adapters/llm/bitgpu-inference-backend.test.js +0 -464
- package/dist/browser-ai/adapters/llm/webllm-inference-backend.test.js +0 -646
- package/dist/browser-ai/adapters/stt/browser-speech.test.js +0 -113
- package/dist/browser-ai/adapters/stt/dictation-source.test.js +0 -52
- package/dist/browser-ai/svelte/components/__tests__/ModelStatusControl.test.js +0 -172
- package/dist/components/board/__tests__/Board.test.js +0 -498
- package/dist/components/board/__tests__/BoardSsrHarness.svelte +0 -30
- package/dist/components/board/__tests__/BoardSsrHarness.svelte.d.ts +0 -19
- package/dist/components/board/__tests__/BoardSsrHarness.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/AddressInput.behavior.test.js +0 -216
- package/dist/components/forms/__tests__/CheckboxInput.test.js +0 -92
- package/dist/components/forms/__tests__/DateRangeInput.behavior.test.js +0 -135
- package/dist/components/forms/__tests__/DateTimeInput.behavior.test.js +0 -113
- package/dist/components/forms/__tests__/FileUpload.error-alert.test.js +0 -37
- package/dist/components/forms/__tests__/FileUpload.native-form.test.js +0 -249
- package/dist/components/forms/__tests__/FileUpload.test.js +0 -90
- package/dist/components/forms/__tests__/FileUploadReset.fixture.svelte +0 -24
- package/dist/components/forms/__tests__/FileUploadReset.fixture.svelte.d.ts +0 -10
- package/dist/components/forms/__tests__/FileUploadReset.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/Form.behavior.test.js +0 -137
- package/dist/components/forms/__tests__/Form.extraction.test.js +0 -68
- package/dist/components/forms/__tests__/Form.stt-error.test.js +0 -57
- package/dist/components/forms/__tests__/Form.test.js +0 -86
- package/dist/components/forms/__tests__/Form.ui-controls.test.js +0 -119
- package/dist/components/forms/__tests__/Form.webmcp.test.js +0 -2336
- package/dist/components/forms/__tests__/FormMicButton.test.js +0 -92
- package/dist/components/forms/__tests__/FormScope.test.js +0 -39
- package/dist/components/forms/__tests__/MeasurementInput.behavior.test.js +0 -129
- package/dist/components/forms/__tests__/MoneyInput.behavior.test.js +0 -124
- package/dist/components/forms/__tests__/NumberInput.behavior.test.js +0 -151
- package/dist/components/forms/__tests__/PhoneInput.behavior.test.js +0 -96
- package/dist/components/forms/__tests__/SearchInput.test.js +0 -79
- package/dist/components/forms/__tests__/SelectInput.behavior.test.js +0 -132
- package/dist/components/forms/__tests__/TextInput.behavior.test.js +0 -131
- package/dist/components/forms/__tests__/TextareaInput.behavior.test.js +0 -96
- package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte +0 -30
- package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte.d.ts +0 -7
- package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/async-validation-form.fixture.svelte +0 -19
- package/dist/components/forms/__tests__/async-validation-form.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/async-validation-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte +0 -21
- package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/composite-inputs-a11y.test.js +0 -69
- package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte +0 -27
- package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte +0 -48
- package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte.d.ts +0 -10
- package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte +0 -26
- package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte.d.ts +0 -13
- package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte +0 -52
- package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte.d.ts +0 -16
- package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-scope.fixture.svelte +0 -30
- package/dist/components/forms/__tests__/form-scope.fixture.svelte.d.ts +0 -10
- package/dist/components/forms/__tests__/form-scope.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-with-fields.fixture.svelte +0 -158
- package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts +0 -51
- package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte +0 -24
- package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte.d.ts +0 -11
- package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte +0 -105
- package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte.d.ts +0 -42
- package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-with-ui-controls.fixture.svelte +0 -84
- package/dist/components/forms/__tests__/form-with-ui-controls.fixture.svelte.d.ts +0 -14
- package/dist/components/forms/__tests__/form-with-ui-controls.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte +0 -44
- package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/mic-keyboard-a11y.test.js +0 -74
- package/dist/components/forms/__tests__/policy-field.fixture.svelte +0 -35
- package/dist/components/forms/__tests__/policy-field.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/policy-field.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/rich-inputs-a11y.test.js +0 -87
- package/dist/components/settings/__tests__/SettingsCatalog.test.js +0 -69
- package/dist/components/settings/__tests__/catalog.test.js +0 -46
- package/dist/components/workspace/__tests__/AdminShell.responsive.test.js +0 -597
- package/dist/components/workspace/__tests__/AdminShell.test.js +0 -572
- package/dist/components/workspace/__tests__/RoleShell.test.js +0 -772
- package/dist/components/workspace/__tests__/TenantNav.test.js +0 -208
- package/dist/components/workspace/__tests__/WorkspaceAccountMenu.test.js +0 -79
- package/dist/components/workspace/__tests__/WorkspaceShell.test.js +0 -630
- package/dist/components/workspace/__tests__/admin-shell-header-overflow.test.js +0 -25
- package/dist/components/workspace/__tests__/admin-shell-hotkeys.test.js +0 -34
- package/dist/components/workspace/__tests__/admin-shell-mobile.test.js +0 -217
- package/dist/components/workspace/__tests__/admin-shell-mutation-effect-harness.svelte +0 -52
- package/dist/components/workspace/__tests__/admin-shell-mutation-effect-harness.svelte.d.ts +0 -23
- package/dist/components/workspace/__tests__/admin-shell-mutation-effect-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/admin-shell-page-contracts.test.js +0 -30
- package/dist/components/workspace/__tests__/admin-shell-responsive-state.test.js +0 -184
- package/dist/components/workspace/__tests__/admin-shell-settings.test.js +0 -25
- package/dist/components/workspace/__tests__/admin-shell-state.test.js +0 -286
- package/dist/components/workspace/__tests__/admin-shell-theme-hooks.test.js +0 -36
- package/dist/components/workspace/__tests__/breadcrumbs-helpers.test.js +0 -141
- package/dist/components/workspace/__tests__/context-forwarding-harness.svelte +0 -45
- package/dist/components/workspace/__tests__/context-forwarding-harness.svelte.d.ts +0 -21
- package/dist/components/workspace/__tests__/context-forwarding-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/define-tools-dock.test.js +0 -1188
- package/dist/components/workspace/__tests__/harness.svelte +0 -25
- package/dist/components/workspace/__tests__/harness.svelte.d.ts +0 -14
- package/dist/components/workspace/__tests__/harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/index.test.js +0 -28
- package/dist/components/workspace/__tests__/legacy-index.test.js +0 -9
- package/dist/components/workspace/__tests__/manifest-nav-helpers.test.js +0 -24
- package/dist/components/workspace/__tests__/manifest-nav.test.js +0 -599
- package/dist/components/workspace/__tests__/nav-helpers.test.js +0 -95
- package/dist/components/workspace/__tests__/render-harness.svelte +0 -66
- package/dist/components/workspace/__tests__/render-harness.svelte.d.ts +0 -32
- package/dist/components/workspace/__tests__/render-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/render-tools-dock.test.js +0 -260
- package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte +0 -58
- package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte.d.ts +0 -16
- package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte +0 -41
- package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte.d.ts +0 -13
- package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/shell-chrome-components.test.js +0 -108
- package/dist/components/workspace/__tests__/system-feed.test.js +0 -327
- package/dist/components/workspace/__tests__/test-icon.svelte +0 -17
- package/dist/components/workspace/__tests__/test-icon.svelte.d.ts +0 -19
- package/dist/components/workspace/__tests__/test-icon.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte +0 -38
- package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte.d.ts +0 -22
- package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts +0 -66
- package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.js +0 -115
- package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.d.ts +0 -15
- package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.js +0 -7
- package/dist/components/workspace/__tests__/typed-tool-fixture.test.js +0 -115
- package/dist/components/workspace/__tests__/use-harness-orphan.svelte +0 -9
- package/dist/components/workspace/__tests__/use-harness-orphan.svelte.d.ts +0 -19
- package/dist/components/workspace/__tests__/use-harness-orphan.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/use-harness.svelte +0 -23
- package/dist/components/workspace/__tests__/use-harness.svelte.d.ts +0 -8
- package/dist/components/workspace/__tests__/use-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/use-tools-dock.test.js +0 -33
- package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte +0 -43
- package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte.d.ts +0 -11
- package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/server/__tests__/compose-availability.test.js +0 -383
- package/dist/components/workspace/server/__tests__/typed-context-fixture.d.ts +0 -78
- package/dist/components/workspace/server/__tests__/typed-context-fixture.d.ts.map +0 -1
- package/dist/components/workspace/server/__tests__/typed-context-fixture.js +0 -104
- package/dist/hooks/__tests__/stt-consumer.fixture.svelte +0 -25
- package/dist/hooks/__tests__/stt-consumer.fixture.svelte.d.ts +0 -15
- package/dist/hooks/__tests__/stt-consumer.fixture.svelte.d.ts.map +0 -1
- package/dist/hooks/__tests__/stt-ownership-harness.svelte +0 -42
- package/dist/hooks/__tests__/stt-ownership-harness.svelte.d.ts +0 -20
- package/dist/hooks/__tests__/stt-ownership-harness.svelte.d.ts.map +0 -1
- package/dist/hooks/__tests__/useSTT-ownership.test.js +0 -102
- package/dist/i18n/__tests__/server.spec.js +0 -57
- package/dist/internal/logger.test.js +0 -54
- package/dist/provider-mode.test.js +0 -86
- package/dist/provider-webmcp.test.js +0 -244
- package/dist/state/__tests__/app-state-ai-lifecycle.test.js +0 -240
- package/dist/state/__tests__/warm-clients.test.js +0 -40
- package/dist/web/__tests__/activity-feed-harness.svelte +0 -32
- package/dist/web/__tests__/activity-feed-harness.svelte.d.ts +0 -18
- package/dist/web/__tests__/activity-feed-harness.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/activity-feed.integration.svelte.test.js +0 -190
- package/dist/web/__tests__/activity-feed.svelte.test.js +0 -235
- package/dist/web/__tests__/assistant-dock.integration.svelte.test.js +0 -204
- package/dist/web/__tests__/data-surface-conformance.integration.svelte.test.js +0 -1392
- package/dist/web/__tests__/harness.svelte +0 -25
- package/dist/web/__tests__/harness.svelte.d.ts +0 -15
- package/dist/web/__tests__/harness.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/list-data-surface.fixture.svelte +0 -59
- package/dist/web/__tests__/list-data-surface.fixture.svelte.d.ts +0 -14
- package/dist/web/__tests__/list-data-surface.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/list-data-surface.svelte.test.js +0 -106
- package/dist/web/__tests__/list-data-surface.test.js +0 -651
- package/dist/web/__tests__/list-sort-surface.fixture.svelte +0 -41
- package/dist/web/__tests__/list-sort-surface.fixture.svelte.d.ts +0 -15
- package/dist/web/__tests__/list-sort-surface.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/list-sort-surface.svelte.test.js +0 -59
- package/dist/web/__tests__/live-collection.svelte.test.js +0 -185
- package/dist/web/__tests__/provider-ui-registry.fixture.svelte +0 -43
- package/dist/web/__tests__/provider-ui-registry.fixture.svelte.d.ts +0 -13
- package/dist/web/__tests__/provider-ui-registry.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/provider-ui-registry.test.js +0 -235
- package/dist/web/__tests__/remote-query-harness.svelte +0 -27
- package/dist/web/__tests__/remote-query-harness.svelte.d.ts +0 -11
- package/dist/web/__tests__/remote-query-harness.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/remote-query.svelte.test.js +0 -101
- package/dist/web/__tests__/surfaces.child.fixture.svelte +0 -69
- package/dist/web/__tests__/surfaces.child.fixture.svelte.d.ts +0 -16
- package/dist/web/__tests__/surfaces.child.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/surfaces.fixture.svelte +0 -26
- package/dist/web/__tests__/surfaces.fixture.svelte.d.ts +0 -18
- package/dist/web/__tests__/surfaces.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/surfaces.svelte.test.js +0 -140
- package/dist/web/__tests__/update-available-harness.svelte +0 -46
- package/dist/web/__tests__/update-available-harness.svelte.d.ts +0 -22
- package/dist/web/__tests__/update-available-harness.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/update-available.svelte.test.js +0 -137
- package/dist/web/__tests__/view-intent-provider.fixture.svelte +0 -28
- package/dist/web/__tests__/view-intent-provider.fixture.svelte.d.ts +0 -13
- package/dist/web/__tests__/view-intent-provider.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/view-intent.fixture.svelte +0 -33
- package/dist/web/__tests__/view-intent.fixture.svelte.d.ts +0 -15
- package/dist/web/__tests__/view-intent.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/view-intent.intents.d.ts +0 -14
- package/dist/web/__tests__/view-intent.intents.d.ts.map +0 -1
- package/dist/web/__tests__/view-intent.intents.js +0 -38
- package/dist/web/__tests__/view-intent.svelte.test.js +0 -244
- package/dist/web/__tests__/webmcp-composed.child.fixture.svelte +0 -73
- package/dist/web/__tests__/webmcp-composed.child.fixture.svelte.d.ts +0 -8
- package/dist/web/__tests__/webmcp-composed.child.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-composed.fixture.svelte +0 -52
- package/dist/web/__tests__/webmcp-composed.fixture.svelte.d.ts +0 -12
- package/dist/web/__tests__/webmcp-composed.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-composed.integration.svelte.test.js +0 -251
- package/dist/web/__tests__/webmcp-effects-reactivity.child.fixture.svelte +0 -16
- package/dist/web/__tests__/webmcp-effects-reactivity.child.fixture.svelte.d.ts +0 -19
- package/dist/web/__tests__/webmcp-effects-reactivity.child.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-effects-reactivity.fixture.svelte +0 -11
- package/dist/web/__tests__/webmcp-effects-reactivity.fixture.svelte.d.ts +0 -8
- package/dist/web/__tests__/webmcp-effects-reactivity.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-harness-reactive-samename.svelte +0 -20
- package/dist/web/__tests__/webmcp-harness-reactive-samename.svelte.d.ts +0 -7
- package/dist/web/__tests__/webmcp-harness-reactive-samename.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-harness-unannotated.svelte +0 -14
- package/dist/web/__tests__/webmcp-harness-unannotated.svelte.d.ts +0 -19
- package/dist/web/__tests__/webmcp-harness-unannotated.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-harness.svelte +0 -18
- package/dist/web/__tests__/webmcp-harness.svelte.d.ts +0 -7
- package/dist/web/__tests__/webmcp-harness.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-ssr.fixture.svelte +0 -13
- package/dist/web/__tests__/webmcp-ssr.fixture.svelte.d.ts +0 -19
- package/dist/web/__tests__/webmcp-ssr.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-ui.test.js +0 -723
- package/dist/web/__tests__/webmcp.test.js +0 -234
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for the AdminShell activity feed adapter's reconciliation core
|
|
3
|
-
* (#1779).
|
|
4
|
-
*
|
|
5
|
-
* These exercise {@link ActivityFeedReconciler} — the pure diff between a set of
|
|
6
|
-
* live rows and the shell activity registry — against a REAL {@link ShellState}.
|
|
7
|
-
* Per repo policy nothing here is mocked: the shell, its activity events, and
|
|
8
|
-
* the mapping are all real; the reconciler is fed plain row arrays that stand in
|
|
9
|
-
* for successive live-collection ticks (`liveCollection`'s engine is exercised
|
|
10
|
-
* separately in `activity-feed.integration.svelte.test.ts`). This isolates the
|
|
11
|
-
* mapping / create-update-remove / ownership behavior the adapter guarantees.
|
|
12
|
-
*/
|
|
13
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
14
|
-
import { createShellState } from '../../components/workspace/admin-shell/state.svelte.js';
|
|
15
|
-
import { ActivityFeedReconciler, } from '../activity-feed.svelte.js';
|
|
16
|
-
/** Editorial map: a job row → focus-scope activity, or `null` for a draft. */
|
|
17
|
-
const mapJob = (row) => {
|
|
18
|
-
if (row.draft)
|
|
19
|
-
return null;
|
|
20
|
-
return {
|
|
21
|
-
kind: 'render-job',
|
|
22
|
-
scope: 'focus',
|
|
23
|
-
label: row.title,
|
|
24
|
-
status: row.state,
|
|
25
|
-
progress: row.progress ?? null,
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
/** Record every activity event the shell emits, for sequence assertions. */
|
|
29
|
-
function recordEvents(shell) {
|
|
30
|
-
const events = [];
|
|
31
|
-
const stop = shell.watchActivities((event) => events.push(event));
|
|
32
|
-
return { events, stop };
|
|
33
|
-
}
|
|
34
|
-
describe('ActivityFeedReconciler', () => {
|
|
35
|
-
const teardown = [];
|
|
36
|
-
afterEach(() => {
|
|
37
|
-
for (const fn of teardown.splice(0))
|
|
38
|
-
fn();
|
|
39
|
-
});
|
|
40
|
-
function setup() {
|
|
41
|
-
const shell = createShellState();
|
|
42
|
-
const recorded = recordEvents(shell);
|
|
43
|
-
teardown.push(recorded.stop);
|
|
44
|
-
const reconciler = new ActivityFeedReconciler(shell, mapJob);
|
|
45
|
-
return { shell, reconciler, events: recorded.events };
|
|
46
|
-
}
|
|
47
|
-
it('upserts a shell activity when a row first appears', () => {
|
|
48
|
-
const { shell, reconciler, events } = setup();
|
|
49
|
-
reconciler.reconcile([
|
|
50
|
-
{ id: 'job-1', title: 'Render intro', state: 'running', progress: 20 },
|
|
51
|
-
]);
|
|
52
|
-
const activities = shell.listActivities();
|
|
53
|
-
expect(activities).toHaveLength(1);
|
|
54
|
-
expect(activities[0]).toMatchObject({
|
|
55
|
-
id: 'job-1',
|
|
56
|
-
kind: 'render-job',
|
|
57
|
-
scope: 'focus',
|
|
58
|
-
label: 'Render intro',
|
|
59
|
-
status: 'running',
|
|
60
|
-
progress: 20,
|
|
61
|
-
});
|
|
62
|
-
// The activity id defaults to the row id, and the shell stamped createdAt.
|
|
63
|
-
expect(activities[0].createdAt).toBeTruthy();
|
|
64
|
-
// A single create event (upsert), no transition/remove.
|
|
65
|
-
expect(events.map((e) => e.type)).toEqual(['upsert']);
|
|
66
|
-
});
|
|
67
|
-
it('updates the activity in place when a row changes (status transition)', () => {
|
|
68
|
-
const { shell, reconciler, events } = setup();
|
|
69
|
-
reconciler.reconcile([
|
|
70
|
-
{ id: 'job-1', title: 'Render intro', state: 'running', progress: 20 },
|
|
71
|
-
]);
|
|
72
|
-
const createdAt = shell.listActivities()[0].createdAt;
|
|
73
|
-
// Same row id, advanced progress + status flip → an UPDATE, not a second
|
|
74
|
-
// create, and the shell reports it as a `transition` (status changed).
|
|
75
|
-
reconciler.reconcile([
|
|
76
|
-
{ id: 'job-1', title: 'Render intro', state: 'completed', progress: 100 },
|
|
77
|
-
]);
|
|
78
|
-
const activities = shell.listActivities();
|
|
79
|
-
expect(activities).toHaveLength(1);
|
|
80
|
-
expect(activities[0]).toMatchObject({
|
|
81
|
-
id: 'job-1',
|
|
82
|
-
status: 'completed',
|
|
83
|
-
progress: 100,
|
|
84
|
-
});
|
|
85
|
-
// createdAt preserved across the update (update went through updateActivity,
|
|
86
|
-
// not a fresh upsert that would re-stamp it).
|
|
87
|
-
expect(activities[0].createdAt).toBe(createdAt);
|
|
88
|
-
expect(events.map((e) => e.type)).toEqual(['upsert', 'transition']);
|
|
89
|
-
});
|
|
90
|
-
it('performs no shell mutation when a reconcile tick is unchanged', () => {
|
|
91
|
-
const { reconciler, events } = setup();
|
|
92
|
-
const rows = [
|
|
93
|
-
{ id: 'job-1', title: 'Render intro', state: 'running', progress: 20 },
|
|
94
|
-
];
|
|
95
|
-
reconciler.reconcile(rows);
|
|
96
|
-
// Re-feed identical content (a common no-op reactive tick): a new array with
|
|
97
|
-
// an equal-but-distinct row object. Must not emit a second event.
|
|
98
|
-
reconciler.reconcile([{ ...rows[0] }]);
|
|
99
|
-
expect(events.map((e) => e.type)).toEqual(['upsert']);
|
|
100
|
-
});
|
|
101
|
-
it('removes the activity when its row vanishes from the collection', () => {
|
|
102
|
-
const { shell, reconciler, events } = setup();
|
|
103
|
-
reconciler.reconcile([
|
|
104
|
-
{ id: 'job-1', title: 'Render intro', state: 'running' },
|
|
105
|
-
{ id: 'job-2', title: 'Render outro', state: 'queued' },
|
|
106
|
-
]);
|
|
107
|
-
expect(shell.listActivities()).toHaveLength(2);
|
|
108
|
-
// job-1 gone from the next tick → removed; job-2 unchanged → left alone.
|
|
109
|
-
reconciler.reconcile([
|
|
110
|
-
{ id: 'job-2', title: 'Render outro', state: 'queued' },
|
|
111
|
-
]);
|
|
112
|
-
const remaining = shell.listActivities();
|
|
113
|
-
expect(remaining).toHaveLength(1);
|
|
114
|
-
expect(remaining[0].id).toBe('job-2');
|
|
115
|
-
expect(events.map((e) => e.type)).toEqual([
|
|
116
|
-
'upsert', // job-1 create
|
|
117
|
-
'upsert', // job-2 create
|
|
118
|
-
'remove', // job-1 removed
|
|
119
|
-
]);
|
|
120
|
-
});
|
|
121
|
-
it('treats a row that maps to null as absent (excluded, then removed when it flips)', () => {
|
|
122
|
-
const { shell, reconciler } = setup();
|
|
123
|
-
// A draft row maps to null → never becomes an activity.
|
|
124
|
-
reconciler.reconcile([
|
|
125
|
-
{ id: 'job-1', title: 'Draft', state: 'queued', draft: true },
|
|
126
|
-
]);
|
|
127
|
-
expect(shell.listActivities()).toHaveLength(0);
|
|
128
|
-
// It leaves draft → now an activity appears.
|
|
129
|
-
reconciler.reconcile([
|
|
130
|
-
{ id: 'job-1', title: 'Published', state: 'running' },
|
|
131
|
-
]);
|
|
132
|
-
expect(shell.listActivities()).toHaveLength(1);
|
|
133
|
-
// It goes back to draft (maps to null again) → activity is removed.
|
|
134
|
-
reconciler.reconcile([
|
|
135
|
-
{ id: 'job-1', title: 'Published', state: 'running', draft: true },
|
|
136
|
-
]);
|
|
137
|
-
expect(shell.listActivities()).toHaveLength(0);
|
|
138
|
-
});
|
|
139
|
-
it('lets the map decouple the activity id from the row id', () => {
|
|
140
|
-
const shell = createShellState();
|
|
141
|
-
const reconciler = new ActivityFeedReconciler(shell, (row) => ({
|
|
142
|
-
id: `activity:${row.id}`,
|
|
143
|
-
kind: 'render-job',
|
|
144
|
-
scope: 'system',
|
|
145
|
-
label: row.title,
|
|
146
|
-
status: row.state,
|
|
147
|
-
}));
|
|
148
|
-
reconciler.reconcile([{ id: 'job-1', title: 'Job', state: 'running' }]);
|
|
149
|
-
const activities = shell.listActivities();
|
|
150
|
-
expect(activities).toHaveLength(1);
|
|
151
|
-
expect(activities[0].id).toBe('activity:job-1');
|
|
152
|
-
});
|
|
153
|
-
it('routes an activity to the shell edge for its scope', () => {
|
|
154
|
-
const { shell, reconciler } = setup();
|
|
155
|
-
reconciler.reconcile([{ id: 'job-1', title: 'Job', state: 'running' }]);
|
|
156
|
-
// scope 'focus' homes to the right edge (SCOPE_EDGES.focus === 'right').
|
|
157
|
-
expect(shell.listActivities({ edge: 'right' })).toHaveLength(1);
|
|
158
|
-
});
|
|
159
|
-
it('re-homes the activity to the new edge when its scope changes (no explicit edge)', () => {
|
|
160
|
-
const shell = createShellState();
|
|
161
|
-
// Map keys scope off the row so a later tick can change it; no `edge` set.
|
|
162
|
-
const reconciler = new ActivityFeedReconciler(shell, (row) => ({
|
|
163
|
-
kind: 'render-job',
|
|
164
|
-
// Reuse the unused `draft` flag as a cheap "move to system scope" toggle.
|
|
165
|
-
scope: row.draft ? 'system' : 'focus',
|
|
166
|
-
label: row.title,
|
|
167
|
-
status: row.state,
|
|
168
|
-
}));
|
|
169
|
-
reconciler.reconcile([{ id: 'job-1', title: 'Job', state: 'running' }]);
|
|
170
|
-
// Focus → right edge.
|
|
171
|
-
expect(shell.listActivities({ edge: 'right' })).toHaveLength(1);
|
|
172
|
-
expect(shell.listActivities({ edge: 'bottom' })).toHaveLength(0);
|
|
173
|
-
// Scope flips to system; the map still sets no explicit edge. The activity
|
|
174
|
-
// must RE-DERIVE its edge from the new scope (system → bottom), not stay
|
|
175
|
-
// pinned to the old right edge.
|
|
176
|
-
reconciler.reconcile([
|
|
177
|
-
{ id: 'job-1', title: 'Job', state: 'running', draft: true },
|
|
178
|
-
]);
|
|
179
|
-
expect(shell.listActivities({ edge: 'right' })).toHaveLength(0);
|
|
180
|
-
expect(shell.listActivities({ edge: 'bottom' })).toHaveLength(1);
|
|
181
|
-
expect(shell.listActivities()[0].scope).toBe('system');
|
|
182
|
-
});
|
|
183
|
-
it('clears a previously-set optional field when a later mapping drops it', () => {
|
|
184
|
-
const shell = createShellState();
|
|
185
|
-
// Map emits `message`/`detailHref` only while the job is running.
|
|
186
|
-
const reconciler = new ActivityFeedReconciler(shell, (row) => ({
|
|
187
|
-
kind: 'render-job',
|
|
188
|
-
scope: 'focus',
|
|
189
|
-
label: row.title,
|
|
190
|
-
status: row.state,
|
|
191
|
-
...(row.state === 'running'
|
|
192
|
-
? { message: 'Rendering frames', detailHref: '/jobs/job-1' }
|
|
193
|
-
: {}),
|
|
194
|
-
}));
|
|
195
|
-
reconciler.reconcile([{ id: 'job-1', title: 'Job', state: 'running' }]);
|
|
196
|
-
let activity = shell.listActivities()[0];
|
|
197
|
-
expect(activity.message).toBe('Rendering frames');
|
|
198
|
-
expect(activity.detailHref).toBe('/jobs/job-1');
|
|
199
|
-
// The job completes → the map no longer emits message/detailHref. Those
|
|
200
|
-
// stale values must be CLEARED, not retained from the previous mapping.
|
|
201
|
-
reconciler.reconcile([{ id: 'job-1', title: 'Job', state: 'completed' }]);
|
|
202
|
-
activity = shell.listActivities()[0];
|
|
203
|
-
expect(activity.status).toBe('completed');
|
|
204
|
-
expect(activity.message).toBeUndefined();
|
|
205
|
-
expect(activity.detailHref).toBeUndefined();
|
|
206
|
-
});
|
|
207
|
-
it('dispose() removes exactly the feed activities and stops reconciling', () => {
|
|
208
|
-
const { shell, reconciler, events } = setup();
|
|
209
|
-
// An activity from ANOTHER source the feed must never touch.
|
|
210
|
-
shell.upsertActivity({
|
|
211
|
-
id: 'external-1',
|
|
212
|
-
label: 'External',
|
|
213
|
-
kind: 'other',
|
|
214
|
-
scope: 'app',
|
|
215
|
-
status: 'running',
|
|
216
|
-
});
|
|
217
|
-
reconciler.reconcile([
|
|
218
|
-
{ id: 'job-1', title: 'Render intro', state: 'running' },
|
|
219
|
-
]);
|
|
220
|
-
expect(shell.listActivities()).toHaveLength(2);
|
|
221
|
-
reconciler.dispose();
|
|
222
|
-
// Only the feed's own activity was retracted; the external one survives.
|
|
223
|
-
const remaining = shell.listActivities();
|
|
224
|
-
expect(remaining).toHaveLength(1);
|
|
225
|
-
expect(remaining[0].id).toBe('external-1');
|
|
226
|
-
expect(reconciler.isDisposed).toBe(true);
|
|
227
|
-
// Reconciling after dispose is a no-op (no new activities, no events).
|
|
228
|
-
const eventsBefore = events.length;
|
|
229
|
-
reconciler.reconcile([
|
|
230
|
-
{ id: 'job-2', title: 'Late job', state: 'running' },
|
|
231
|
-
]);
|
|
232
|
-
expect(shell.listActivities()).toHaveLength(1);
|
|
233
|
-
expect(events.length).toBe(eventsBefore);
|
|
234
|
-
});
|
|
235
|
-
});
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
/**
|
|
3
|
-
* AssistantDock conformance-style integration test (#2904).
|
|
4
|
-
*
|
|
5
|
-
* Mirrors `data-surface-conformance.integration.svelte.test.ts` in this
|
|
6
|
-
* directory: a real `DataSurfaceRegistry` and a real
|
|
7
|
-
* `createAssistantDockController`/`AssistantDock` are composed together;
|
|
8
|
-
* only the chat transport and the action client are in-process test doubles
|
|
9
|
-
* (`createInMemoryAssistantTransport`, and a thin `actionClient` adapter over
|
|
10
|
-
* the registry's own `execute()`), matching that file's stated scope of
|
|
11
|
-
* faking only the transport boundary.
|
|
12
|
-
*
|
|
13
|
-
* Scope note (disclosed deviation from the original test plan): the action
|
|
14
|
-
* preview/apply path here is driven directly through
|
|
15
|
-
* `createAssistantDockController` rather than by having a fake model reply
|
|
16
|
-
* trigger it through the rendered `AssistantDock` DOM — `AssistantDock` has
|
|
17
|
-
* no built-in "parse this assistant message as an action proposal" step (no
|
|
18
|
-
* such parsing is specified anywhere in #2904's binding decisions), so the
|
|
19
|
-
* host application is expected to call `controller.previewAction(...)` from
|
|
20
|
-
* its own message-rendering logic. This test still exercises the full
|
|
21
|
-
* dock (registry discovery, rendering, send/poll) through the DOM, and
|
|
22
|
-
* separately proves the action pathway (preview → confirm → apply → registry
|
|
23
|
-
* "command" event) end-to-end against the real registry.
|
|
24
|
-
*/
|
|
25
|
-
import { AssistantDock, createAssistantDockController, createInMemoryAssistantTransport, } from '@happyvertical/smrt-chat/svelte';
|
|
26
|
-
import { createDataSurfaceRegistry, } from '@happyvertical/smrt-ui/data-surface';
|
|
27
|
-
import { render, screen, waitFor } from '@testing-library/svelte';
|
|
28
|
-
import { describe, expect, it } from 'vitest';
|
|
29
|
-
const identity = {
|
|
30
|
-
surfaceId: 'assistant-dock-orders',
|
|
31
|
-
kind: 'table',
|
|
32
|
-
subject: { type: 'tenant', id: 'tenant-a' },
|
|
33
|
-
};
|
|
34
|
-
const descriptor = {
|
|
35
|
-
version: 1,
|
|
36
|
-
identity,
|
|
37
|
-
schemaVersion: 1,
|
|
38
|
-
label: 'Orders',
|
|
39
|
-
rowKey: 'id',
|
|
40
|
-
columns: [
|
|
41
|
-
{
|
|
42
|
-
id: 'id',
|
|
43
|
-
label: 'ID',
|
|
44
|
-
capabilities: ['read', 'project'],
|
|
45
|
-
role: 'row-key',
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
|
-
query: {
|
|
49
|
-
modes: ['rows'],
|
|
50
|
-
projectableColumnIds: ['id'],
|
|
51
|
-
searchableColumnIds: [],
|
|
52
|
-
filterableColumnIds: [],
|
|
53
|
-
sortableColumnIds: [],
|
|
54
|
-
},
|
|
55
|
-
actions: [
|
|
56
|
-
{
|
|
57
|
-
id: 'archive',
|
|
58
|
-
label: 'Archive',
|
|
59
|
-
selectionScopes: ['explicit-ids'],
|
|
60
|
-
requiresConfirmation: true,
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
controls: [{ id: 'data-surface.action.archive', label: 'Archive' }],
|
|
64
|
-
limits: { maxQueryRows: 100, maxQueryBytes: 100_000, maxSelectionSize: 100 },
|
|
65
|
-
};
|
|
66
|
-
function mountRegistryWithOneSurface() {
|
|
67
|
-
const registry = createDataSurfaceRegistry();
|
|
68
|
-
let revision = 1;
|
|
69
|
-
const state = { archived: false };
|
|
70
|
-
const unregister = registry.register({
|
|
71
|
-
descriptor,
|
|
72
|
-
getSnapshot: () => ({
|
|
73
|
-
version: 1,
|
|
74
|
-
descriptor,
|
|
75
|
-
revision,
|
|
76
|
-
state: { archived: state.archived },
|
|
77
|
-
}),
|
|
78
|
-
execute: async (command) => {
|
|
79
|
-
// A minimal real mutation: the "archive" action flips `archived` and
|
|
80
|
-
// bumps the snapshot revision, which is what makes the registry emit a
|
|
81
|
-
// 'command' event other mounted UI can react to.
|
|
82
|
-
state.archived = true;
|
|
83
|
-
revision += 1;
|
|
84
|
-
return {
|
|
85
|
-
version: 1,
|
|
86
|
-
commandId: command.commandId,
|
|
87
|
-
identity: command.identity,
|
|
88
|
-
ok: true,
|
|
89
|
-
revision,
|
|
90
|
-
};
|
|
91
|
-
},
|
|
92
|
-
});
|
|
93
|
-
return { registry, unregister, state: () => state.archived };
|
|
94
|
-
}
|
|
95
|
-
describe('AssistantDock integration (#2904)', () => {
|
|
96
|
-
it('fails closed and shows the no-surfaces notice with an empty registry', async () => {
|
|
97
|
-
const registry = createDataSurfaceRegistry();
|
|
98
|
-
const transport = createInMemoryAssistantTransport();
|
|
99
|
-
render(AssistantDock, { props: { transport, registry } });
|
|
100
|
-
await waitFor(() => {
|
|
101
|
-
expect(screen.getByText(/Nothing on this page can be changed from the chat/i)).toBeInTheDocument();
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
it('discovers a mounted surface via the registry and renders a sent conversation', async () => {
|
|
105
|
-
const { registry } = mountRegistryWithOneSurface();
|
|
106
|
-
const transport = createInMemoryAssistantTransport({
|
|
107
|
-
respond: (_threadId, userMessage) => ({
|
|
108
|
-
id: 'assistant-1',
|
|
109
|
-
threadId: userMessage.threadId,
|
|
110
|
-
content: 'Archived the order.',
|
|
111
|
-
role: 'assistant',
|
|
112
|
-
createdAt: new Date(),
|
|
113
|
-
}),
|
|
114
|
-
});
|
|
115
|
-
render(AssistantDock, { props: { transport, registry } });
|
|
116
|
-
await waitFor(() => {
|
|
117
|
-
expect(screen.queryByText(/Nothing on this page can be changed from the chat/i)).not.toBeInTheDocument();
|
|
118
|
-
});
|
|
119
|
-
const thread = await transport.createThread('Order question');
|
|
120
|
-
// Drive the same controller the component owns internally by exercising
|
|
121
|
-
// the transport directly (the composer's own send() path is covered at
|
|
122
|
-
// the unit level in packages/chat); here we assert the descriptor is
|
|
123
|
-
// visible to a controller built against this exact registry instance.
|
|
124
|
-
const controller = createAssistantDockController({ transport, registry });
|
|
125
|
-
await controller.openThread(thread.id);
|
|
126
|
-
// Cycle-3 second final finding 1: an attached file must round-trip onto
|
|
127
|
-
// the sent message, not just the message text — this is the surface
|
|
128
|
-
// that previously rendered nothing for message.attachments.
|
|
129
|
-
await controller.send('please archive this order', [
|
|
130
|
-
{ id: 'att-1', name: 'order-details.pdf' },
|
|
131
|
-
]);
|
|
132
|
-
await waitFor(() => {
|
|
133
|
-
expect(controller.messages.some((m) => m.content === 'Archived the order.')).toBe(true);
|
|
134
|
-
});
|
|
135
|
-
const sentMessage = controller.messages.find((m) => m.content === 'please archive this order');
|
|
136
|
-
expect(sentMessage?.attachments).toEqual([
|
|
137
|
-
{ id: 'att-1', name: 'order-details.pdf' },
|
|
138
|
-
]);
|
|
139
|
-
expect(controller.surfaces).toHaveLength(1);
|
|
140
|
-
expect(controller.surfaces[0].surfaceId).toBe('assistant-dock-orders');
|
|
141
|
-
controller.dispose();
|
|
142
|
-
});
|
|
143
|
-
it('drives preview → confirm → apply through the real registry and fires its "command" event', async () => {
|
|
144
|
-
const { registry, state } = mountRegistryWithOneSurface();
|
|
145
|
-
const events = [];
|
|
146
|
-
registry.subscribe((event) => events.push(event));
|
|
147
|
-
const actionClient = {
|
|
148
|
-
async preview(request) {
|
|
149
|
-
// A preview never mutates: assert the surface is untouched.
|
|
150
|
-
expect(state()).toBe(false);
|
|
151
|
-
return {
|
|
152
|
-
version: 1,
|
|
153
|
-
requestId: request.requestId,
|
|
154
|
-
identity: request.identity,
|
|
155
|
-
actionId: request.actionId,
|
|
156
|
-
phase: 'preview',
|
|
157
|
-
ok: true,
|
|
158
|
-
confirmationToken: 'token-1',
|
|
159
|
-
};
|
|
160
|
-
},
|
|
161
|
-
async apply(request) {
|
|
162
|
-
const result = await registry.execute({
|
|
163
|
-
version: 1,
|
|
164
|
-
commandId: request.requestId,
|
|
165
|
-
identity: request.identity,
|
|
166
|
-
expectedRevision: 1,
|
|
167
|
-
controlId: `data-surface.action.${request.actionId}`,
|
|
168
|
-
});
|
|
169
|
-
return {
|
|
170
|
-
version: 1,
|
|
171
|
-
requestId: request.requestId,
|
|
172
|
-
identity: request.identity,
|
|
173
|
-
actionId: request.actionId,
|
|
174
|
-
phase: 'apply',
|
|
175
|
-
ok: result.ok,
|
|
176
|
-
reason: result.ok ? undefined : result.reason,
|
|
177
|
-
};
|
|
178
|
-
},
|
|
179
|
-
};
|
|
180
|
-
const controller = createAssistantDockController({
|
|
181
|
-
transport: createInMemoryAssistantTransport(),
|
|
182
|
-
registry,
|
|
183
|
-
actionClient,
|
|
184
|
-
});
|
|
185
|
-
const requestId = 'archive-req-1';
|
|
186
|
-
await controller.previewAction({
|
|
187
|
-
version: 1,
|
|
188
|
-
requestId,
|
|
189
|
-
identity,
|
|
190
|
-
actionId: 'archive',
|
|
191
|
-
phase: 'preview',
|
|
192
|
-
selection: { scope: 'explicit-ids', rowIds: ['order-1'] },
|
|
193
|
-
});
|
|
194
|
-
expect(controller.actions.get(requestId)?.status).toBe('previewed');
|
|
195
|
-
expect(state()).toBe(false); // preview never mutated the surface
|
|
196
|
-
// applyAction now takes only requestId — it reuses the idempotencyKey
|
|
197
|
-
// minted once by previewAction (binding decision #2904, build phase 2).
|
|
198
|
-
await controller.applyAction(requestId);
|
|
199
|
-
expect(controller.actions.get(requestId)?.status).toBe('applied');
|
|
200
|
-
expect(state()).toBe(true);
|
|
201
|
-
expect(events.some((e) => e.type === 'command')).toBe(true);
|
|
202
|
-
controller.dispose();
|
|
203
|
-
});
|
|
204
|
-
});
|