@happyvertical/smrt-svelte 0.53.0 → 0.53.2
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,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BrowserSpeechSTTAdapter errors: every Web Speech error reaches `onError`
|
|
3
|
-
* with its code (`speechError`), including an `aborted` the adapter did not
|
|
4
|
-
* cause, and through smrt-ui's `Dictation` Brave's "starts, then `network`"
|
|
5
|
-
* becomes a plain error instead of a silent stop.
|
|
6
|
-
*/
|
|
7
|
-
import { Dictation } from '@happyvertical/smrt-ui/forms';
|
|
8
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
9
|
-
import { BrowserSpeechSTTAdapter, } from './browser-speech.js';
|
|
10
|
-
import { createSttDictationSource } from './dictation-source.js';
|
|
11
|
-
class FakeRecognition {
|
|
12
|
-
static last = null;
|
|
13
|
-
/** What the browser does after start(): Brave errors with `network`. */
|
|
14
|
-
static afterStart = null;
|
|
15
|
-
lang = '';
|
|
16
|
-
continuous = false;
|
|
17
|
-
interimResults = false;
|
|
18
|
-
maxAlternatives = 1;
|
|
19
|
-
onresult = null;
|
|
20
|
-
onerror = null;
|
|
21
|
-
onstart = null;
|
|
22
|
-
onend = null;
|
|
23
|
-
constructor() {
|
|
24
|
-
FakeRecognition.last = this;
|
|
25
|
-
}
|
|
26
|
-
start = vi.fn(() => {
|
|
27
|
-
this.onstart?.();
|
|
28
|
-
FakeRecognition.afterStart?.(this);
|
|
29
|
-
});
|
|
30
|
-
stop = vi.fn(() => this.onend?.());
|
|
31
|
-
abort = vi.fn(() => {
|
|
32
|
-
this.onerror?.({ error: 'aborted', message: '' });
|
|
33
|
-
this.onend?.();
|
|
34
|
-
});
|
|
35
|
-
fail(code) {
|
|
36
|
-
this.onerror?.({ error: code, message: '' });
|
|
37
|
-
this.onend?.();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function install() {
|
|
41
|
-
window.webkitSpeechRecognition =
|
|
42
|
-
FakeRecognition;
|
|
43
|
-
}
|
|
44
|
-
afterEach(() => {
|
|
45
|
-
delete window
|
|
46
|
-
.webkitSpeechRecognition;
|
|
47
|
-
FakeRecognition.last = null;
|
|
48
|
-
FakeRecognition.afterStart = null;
|
|
49
|
-
});
|
|
50
|
-
describe('BrowserSpeechSTTAdapter errors', () => {
|
|
51
|
-
it.each([
|
|
52
|
-
'network',
|
|
53
|
-
'not-allowed',
|
|
54
|
-
'service-not-allowed',
|
|
55
|
-
'no-speech',
|
|
56
|
-
'audio-capture',
|
|
57
|
-
'aborted',
|
|
58
|
-
'language-not-supported',
|
|
59
|
-
])('reports %s with its code', async (code) => {
|
|
60
|
-
install();
|
|
61
|
-
const adapter = new BrowserSpeechSTTAdapter();
|
|
62
|
-
const errors = [];
|
|
63
|
-
adapter.onError((error) => errors.push(error));
|
|
64
|
-
await adapter.start({ continuous: true });
|
|
65
|
-
FakeRecognition.last?.fail(code);
|
|
66
|
-
expect(errors).toHaveLength(1);
|
|
67
|
-
expect(errors[0].speechError).toBe(code);
|
|
68
|
-
});
|
|
69
|
-
it('does not report the abort it caused itself', async () => {
|
|
70
|
-
install();
|
|
71
|
-
const adapter = new BrowserSpeechSTTAdapter();
|
|
72
|
-
const onError = vi.fn();
|
|
73
|
-
adapter.onError(onError);
|
|
74
|
-
await adapter.start();
|
|
75
|
-
adapter.abort();
|
|
76
|
-
expect(onError).not.toHaveBeenCalled();
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
describe('Dictation over the browser adapter', () => {
|
|
80
|
-
it("Brave: it beeps, then 'network' — shown as unavailable, not a silent stop", async () => {
|
|
81
|
-
install();
|
|
82
|
-
FakeRecognition.afterStart = (r) => queueMicrotask(() => r.fail('network'));
|
|
83
|
-
const log = vi.fn();
|
|
84
|
-
const beep = vi.fn(async () => true);
|
|
85
|
-
const dictation = new Dictation({
|
|
86
|
-
source: createSttDictationSource(),
|
|
87
|
-
onText: () => { },
|
|
88
|
-
beep,
|
|
89
|
-
log,
|
|
90
|
-
requestMicrophone: false,
|
|
91
|
-
});
|
|
92
|
-
await dictation.start();
|
|
93
|
-
await vi.waitFor(() => expect(dictation.state).toBe('error'));
|
|
94
|
-
expect(beep).toHaveBeenCalled();
|
|
95
|
-
expect(dictation.errorKind).toBe('unsupported');
|
|
96
|
-
expect(dictation.errorCode).toBe('network');
|
|
97
|
-
expect(log).toHaveBeenCalledWith(expect.objectContaining({ kind: 'unsupported', code: 'network' }));
|
|
98
|
-
});
|
|
99
|
-
it('an end straight after starting with no error is a failure too', async () => {
|
|
100
|
-
install();
|
|
101
|
-
FakeRecognition.afterStart = (r) => queueMicrotask(() => r.onend?.());
|
|
102
|
-
const dictation = new Dictation({
|
|
103
|
-
source: createSttDictationSource(),
|
|
104
|
-
onText: () => { },
|
|
105
|
-
beep: false,
|
|
106
|
-
log: () => { },
|
|
107
|
-
requestMicrophone: false,
|
|
108
|
-
});
|
|
109
|
-
await dictation.start();
|
|
110
|
-
await vi.waitFor(() => expect(dictation.state).toBe('error'));
|
|
111
|
-
expect(dictation.errorKind).toBe('interrupted');
|
|
112
|
-
});
|
|
113
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* createSttDictationSource: the browser speech adapter, created once and
|
|
3
|
-
* lazily, and rejected plainly where the browser has no speech recognition.
|
|
4
|
-
*/
|
|
5
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
6
|
-
import { createSttDictationSource } from './dictation-source.js';
|
|
7
|
-
class FakeRecognition {
|
|
8
|
-
lang = '';
|
|
9
|
-
continuous = false;
|
|
10
|
-
interimResults = false;
|
|
11
|
-
maxAlternatives = 1;
|
|
12
|
-
onresult = null;
|
|
13
|
-
onerror = null;
|
|
14
|
-
onstart = null;
|
|
15
|
-
onend = null;
|
|
16
|
-
start = vi.fn(() => this.onstart?.());
|
|
17
|
-
stop = vi.fn(() => this.onend?.());
|
|
18
|
-
abort = vi.fn();
|
|
19
|
-
}
|
|
20
|
-
describe('createSttDictationSource', () => {
|
|
21
|
-
afterEach(() => {
|
|
22
|
-
delete window.SpeechRecognition;
|
|
23
|
-
delete window
|
|
24
|
-
.webkitSpeechRecognition;
|
|
25
|
-
});
|
|
26
|
-
it('creates one browser speech adapter, on first use', async () => {
|
|
27
|
-
window.webkitSpeechRecognition =
|
|
28
|
-
FakeRecognition;
|
|
29
|
-
const provide = createSttDictationSource();
|
|
30
|
-
const first = await provide();
|
|
31
|
-
const second = await provide();
|
|
32
|
-
expect(first).toBe(second);
|
|
33
|
-
expect(first.type).toBe('browser-speech');
|
|
34
|
-
const onStart = vi.fn();
|
|
35
|
-
first.onStart(onStart);
|
|
36
|
-
await first.start({
|
|
37
|
-
language: 'en-CA',
|
|
38
|
-
continuous: true,
|
|
39
|
-
interimResults: true,
|
|
40
|
-
});
|
|
41
|
-
expect(onStart).toHaveBeenCalled();
|
|
42
|
-
});
|
|
43
|
-
it('rejects with CapabilityNotAvailableError without speech recognition, then can retry', async () => {
|
|
44
|
-
const provide = createSttDictationSource();
|
|
45
|
-
await expect(provide()).rejects.toMatchObject({
|
|
46
|
-
name: 'CapabilityNotAvailableError',
|
|
47
|
-
});
|
|
48
|
-
window.SpeechRecognition =
|
|
49
|
-
FakeRecognition;
|
|
50
|
-
await expect(provide()).resolves.toBeTruthy();
|
|
51
|
-
});
|
|
52
|
-
});
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `ModelStatusControl` — the user-facing model lifecycle surface.
|
|
3
|
-
*
|
|
4
|
-
* The states that matter here are the ones a user acts on: whether the model is
|
|
5
|
-
* loaded, whether it can be loaded on this device at all, and what a download
|
|
6
|
-
* is doing. The `unavailable` case is asserted explicitly because offering a
|
|
7
|
-
* Load button on a device that cannot run the model is the failure this control
|
|
8
|
-
* exists to prevent.
|
|
9
|
-
*/
|
|
10
|
-
import { expectNoA11yViolations } from '@happyvertical/smrt-ui/test-support/a11y';
|
|
11
|
-
import { render, screen } from '@testing-library/svelte';
|
|
12
|
-
import userEvent from '@testing-library/user-event';
|
|
13
|
-
import { tick } from 'svelte';
|
|
14
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
15
|
-
import ModelStatusControl from '../ModelStatusControl.svelte';
|
|
16
|
-
function makeBackend(initial = {}) {
|
|
17
|
-
let status = initial.status ?? 'idle';
|
|
18
|
-
let progress;
|
|
19
|
-
const listeners = new Set();
|
|
20
|
-
const backend = {
|
|
21
|
-
id: 'local',
|
|
22
|
-
kind: 'local',
|
|
23
|
-
get status() {
|
|
24
|
-
return status;
|
|
25
|
-
},
|
|
26
|
-
get progress() {
|
|
27
|
-
return progress;
|
|
28
|
-
},
|
|
29
|
-
loadCalls: 0,
|
|
30
|
-
unloadCalls: 0,
|
|
31
|
-
loadImpl: async () => { },
|
|
32
|
-
setStatus(next) {
|
|
33
|
-
status = next;
|
|
34
|
-
for (const listener of [...listeners])
|
|
35
|
-
listener();
|
|
36
|
-
},
|
|
37
|
-
setProgress(next) {
|
|
38
|
-
progress = next;
|
|
39
|
-
for (const listener of [...listeners])
|
|
40
|
-
listener();
|
|
41
|
-
},
|
|
42
|
-
async load() {
|
|
43
|
-
backend.loadCalls += 1;
|
|
44
|
-
await backend.loadImpl();
|
|
45
|
-
},
|
|
46
|
-
async unload() {
|
|
47
|
-
backend.unloadCalls += 1;
|
|
48
|
-
status = 'idle';
|
|
49
|
-
for (const listener of [...listeners])
|
|
50
|
-
listener();
|
|
51
|
-
},
|
|
52
|
-
async chat() {
|
|
53
|
-
return { content: '' };
|
|
54
|
-
},
|
|
55
|
-
async *stream() {
|
|
56
|
-
yield '';
|
|
57
|
-
},
|
|
58
|
-
subscribe(listener) {
|
|
59
|
-
listeners.add(listener);
|
|
60
|
-
return () => {
|
|
61
|
-
listeners.delete(listener);
|
|
62
|
-
};
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
return backend;
|
|
66
|
-
}
|
|
67
|
-
describe('ModelStatusControl', () => {
|
|
68
|
-
it('offers a load action when the model is not loaded', async () => {
|
|
69
|
-
const backend = makeBackend({ status: 'idle' });
|
|
70
|
-
render(ModelStatusControl, { props: { backend } });
|
|
71
|
-
expect(screen.getByRole('status')).toHaveTextContent('Not loaded');
|
|
72
|
-
await userEvent.click(screen.getByRole('button', { name: 'Load model' }));
|
|
73
|
-
expect(backend.loadCalls).toBe(1);
|
|
74
|
-
});
|
|
75
|
-
it('offers a release action once the model is ready', async () => {
|
|
76
|
-
const backend = makeBackend({ status: 'ready' });
|
|
77
|
-
render(ModelStatusControl, { props: { backend } });
|
|
78
|
-
expect(screen.getByRole('status')).toHaveTextContent('Ready');
|
|
79
|
-
await userEvent.click(screen.getByRole('button', { name: 'Unload' }));
|
|
80
|
-
expect(backend.unloadCalls).toBe(1);
|
|
81
|
-
});
|
|
82
|
-
it('hides the release action when the host opts out', () => {
|
|
83
|
-
const backend = makeBackend({ status: 'ready' });
|
|
84
|
-
render(ModelStatusControl, {
|
|
85
|
-
props: { backend, allowUnload: false },
|
|
86
|
-
});
|
|
87
|
-
expect(screen.queryByRole('button', { name: 'Unload' })).toBeNull();
|
|
88
|
-
});
|
|
89
|
-
it('never offers a load action on a device that cannot run the model', () => {
|
|
90
|
-
const backend = makeBackend({ status: 'unavailable' });
|
|
91
|
-
render(ModelStatusControl, { props: { backend } });
|
|
92
|
-
expect(screen.getByRole('status')).toHaveTextContent('Not available on this device');
|
|
93
|
-
// The point of the state: no affordance that cannot succeed.
|
|
94
|
-
expect(screen.queryByRole('button')).toBeNull();
|
|
95
|
-
expect(screen.getByText(/will use the server route/)).toBeInTheDocument();
|
|
96
|
-
});
|
|
97
|
-
it('offers no action for a backend that cannot load or unload', () => {
|
|
98
|
-
// A route-kind backend defines neither method and always reports `ready`;
|
|
99
|
-
// offering an Unload that silently does nothing is the same defect as
|
|
100
|
-
// offering a Load on an unavailable device.
|
|
101
|
-
const backend = makeBackend({ status: 'ready' });
|
|
102
|
-
// "A backend with no unload" is not hypothetical: it is the route backend.
|
|
103
|
-
delete backend.load;
|
|
104
|
-
delete backend.unload;
|
|
105
|
-
render(ModelStatusControl, { props: { backend } });
|
|
106
|
-
expect(screen.getByRole('status')).toHaveTextContent('Ready');
|
|
107
|
-
expect(screen.queryByRole('button')).toBeNull();
|
|
108
|
-
});
|
|
109
|
-
it('offers no load action for an idle backend without load', () => {
|
|
110
|
-
const backend = makeBackend({ status: 'idle' });
|
|
111
|
-
delete backend.load;
|
|
112
|
-
render(ModelStatusControl, { props: { backend } });
|
|
113
|
-
expect(screen.getByRole('status')).toHaveTextContent('Not loaded');
|
|
114
|
-
expect(screen.queryByRole('button')).toBeNull();
|
|
115
|
-
});
|
|
116
|
-
it('renders download progress while loading', () => {
|
|
117
|
-
const backend = makeBackend({ status: 'loading' });
|
|
118
|
-
backend.setProgress({
|
|
119
|
-
state: 'downloading',
|
|
120
|
-
bytesLoaded: 250_000,
|
|
121
|
-
bytesTotal: 500_000,
|
|
122
|
-
percent: 50,
|
|
123
|
-
});
|
|
124
|
-
render(ModelStatusControl, { props: { backend } });
|
|
125
|
-
expect(screen.getByRole('status')).toHaveTextContent('Loading');
|
|
126
|
-
expect(screen.getByText('Downloading model')).toBeInTheDocument();
|
|
127
|
-
expect(screen.getByText('50%')).toBeInTheDocument();
|
|
128
|
-
});
|
|
129
|
-
it('offers a retry after a failed load', async () => {
|
|
130
|
-
const backend = makeBackend({ status: 'error' });
|
|
131
|
-
render(ModelStatusControl, { props: { backend } });
|
|
132
|
-
expect(screen.getByRole('status')).toHaveTextContent('Load failed');
|
|
133
|
-
await userEvent.click(screen.getByRole('button', { name: 'Retry' }));
|
|
134
|
-
expect(backend.loadCalls).toBe(1);
|
|
135
|
-
});
|
|
136
|
-
it('surfaces a rejected load inline and to the host', async () => {
|
|
137
|
-
const backend = makeBackend({ status: 'idle' });
|
|
138
|
-
backend.loadImpl = async () => {
|
|
139
|
-
throw new Error('out of memory');
|
|
140
|
-
};
|
|
141
|
-
const onerror = vi.fn();
|
|
142
|
-
render(ModelStatusControl, { props: { backend, onerror } });
|
|
143
|
-
await userEvent.click(screen.getByRole('button', { name: 'Load model' }));
|
|
144
|
-
await tick();
|
|
145
|
-
expect(await screen.findByRole('alert')).toHaveTextContent('out of memory');
|
|
146
|
-
expect(onerror).toHaveBeenCalledWith(expect.any(Error));
|
|
147
|
-
});
|
|
148
|
-
it('follows a backend status change without a host re-render', async () => {
|
|
149
|
-
const backend = makeBackend({ status: 'idle' });
|
|
150
|
-
render(ModelStatusControl, { props: { backend } });
|
|
151
|
-
expect(screen.getByRole('status')).toHaveTextContent('Not loaded');
|
|
152
|
-
backend.setStatus('ready');
|
|
153
|
-
await tick();
|
|
154
|
-
expect(screen.getByRole('status')).toHaveTextContent('Ready');
|
|
155
|
-
});
|
|
156
|
-
it('has no accessibility violations in any state', async () => {
|
|
157
|
-
for (const status of [
|
|
158
|
-
'unavailable',
|
|
159
|
-
'idle',
|
|
160
|
-
'loading',
|
|
161
|
-
'ready',
|
|
162
|
-
'error',
|
|
163
|
-
]) {
|
|
164
|
-
const backend = makeBackend({ status });
|
|
165
|
-
const { container, unmount } = render(ModelStatusControl, {
|
|
166
|
-
props: { backend },
|
|
167
|
-
});
|
|
168
|
-
await expectNoA11yViolations(container);
|
|
169
|
-
unmount();
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
});
|