@vestra-player/sdk 1.5.31 → 1.5.34
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/CHANGELOG.md +23 -0
- package/dist/capabilities.d.ts +6 -0
- package/dist/capabilities.js +4 -0
- package/dist/commands.d.ts +18 -0
- package/dist/commands.js +14 -0
- package/dist/i18n.d.ts +9 -0
- package/dist/i18n.js +9 -0
- package/dist/palettes.d.ts +2 -0
- package/dist/palettes.js +2 -0
- package/dist/player-runtime.d.ts +1 -0
- package/dist/player-runtime.js +1 -0
- package/dist/plugin/bindings.d.ts +2 -0
- package/dist/plugin/bindings.js +2 -0
- package/dist/plugin/osd.d.ts +2 -0
- package/dist/plugin/osd.js +2 -0
- package/dist/plugin/services.d.ts +4 -0
- package/dist/plugin/services.js +4 -0
- package/dist/plugin/subtitles.d.ts +59 -0
- package/dist/plugin/subtitles.js +70 -4
- package/dist/plugin/testing.d.ts +538 -12
- package/dist/plugin/testing.js +458 -23
- package/dist/plugin/types.d.ts +1524 -64
- package/dist/plugin/values.d.ts +5 -0
- package/dist/plugin/values.js +5 -0
- package/dist/processing.d.ts +6 -0
- package/dist/source-resolvers.d.ts +3 -0
- package/dist/subtitles.d.ts +3 -0
- package/dist/wire.d.ts +16 -1
- package/dist/wire.js +10 -0
- package/llms-full.txt +1489 -55
- package/llms.txt +22 -22
- package/package.json +1 -1
package/dist/plugin/testing.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { CAPABILITY_INFO, MESSAGE_LIMIT } from "../capabilities.ts";
|
|
|
8
8
|
import type { CapabilityInfo } from "../capabilities.ts";
|
|
9
9
|
import { OSD_LIMITS } from "./osd.ts";
|
|
10
10
|
import { SECRET_LIMITS, SESSION_STORAGE_LIMITS } from "./services.ts";
|
|
11
|
+
import { SUBTITLE_LIMITS } from "./subtitles.ts";
|
|
11
12
|
import { BINDING_INPUTS } from "./bindings.ts";
|
|
12
13
|
import { THEME_PALETTES } from "../palettes.ts";
|
|
13
14
|
import { IMAGE_LIMITS, UI_VALUE_LIMITS } from "./values.ts";
|
|
@@ -38,6 +39,8 @@ export { OSD_LIMITS };
|
|
|
38
39
|
export { SECRET_LIMITS };
|
|
39
40
|
/** The player's limits on `plugin.storage.session`. */
|
|
40
41
|
export { SESSION_STORAGE_LIMITS };
|
|
42
|
+
/** The player's limits on loaded subtitle files, which the test host enforces as well. */
|
|
43
|
+
export { SUBTITLE_LIMITS };
|
|
41
44
|
/** The names bindings are made of. */
|
|
42
45
|
export { BINDING_INPUTS };
|
|
43
46
|
/** The colours of the player's palettes, by `Theme` token. */
|
|
@@ -116,6 +119,16 @@ type Call = {
|
|
|
116
119
|
* await host.settle();
|
|
117
120
|
* assert.equal(picture.props["brightness"], 40);
|
|
118
121
|
* ```
|
|
122
|
+
*
|
|
123
|
+
* @remarks
|
|
124
|
+
* A record, not a window: no Slint file is compiled and nothing is drawn.
|
|
125
|
+
* `props` holds what the plugin wrote, by Slint name; `emit` fires a
|
|
126
|
+
* callback the way the user's input would; `userClose` closes it the way
|
|
127
|
+
* the title-bar button would.
|
|
128
|
+
*
|
|
129
|
+
* @capability None.
|
|
130
|
+
* @since 1.0.0
|
|
131
|
+
* @category Testing
|
|
119
132
|
*/
|
|
120
133
|
export interface FakeWindow {
|
|
121
134
|
/** The `.slint` file the window was created from (package-relative). */
|
|
@@ -134,12 +147,48 @@ export interface FakeWindow {
|
|
|
134
147
|
* Fire a Slint callback as if the user triggered it in the window. The
|
|
135
148
|
* name may be kebab-case or camelCase; `args` are the callback arguments.
|
|
136
149
|
* Follow it with `await host.settle()` before asserting.
|
|
150
|
+
*
|
|
151
|
+
* @capability None.
|
|
152
|
+
*
|
|
153
|
+
* @example Type into a window's search field
|
|
154
|
+
* The test types "cat" into the window's search box and checks the
|
|
155
|
+
* plugin's results. `emit` delivers the Slint callback `search-changed`
|
|
156
|
+
* with its argument to the plugin's `on` handler; `settle()` waits for the
|
|
157
|
+
* properties the handler wrote.
|
|
158
|
+
* ```ts
|
|
159
|
+
* import assert from "node:assert/strict";
|
|
160
|
+
* declare const host: TestHost;
|
|
161
|
+
* // ---cut---
|
|
162
|
+
* const search = host.window("search");
|
|
163
|
+
* search.emit("searchChanged", "cat"); // camelCase or kebab-case
|
|
164
|
+
* await host.settle();
|
|
165
|
+
* assert.ok((search.props["results"] as unknown[]).length > 0);
|
|
166
|
+
* ```
|
|
167
|
+
*
|
|
168
|
+
* @since 1.0.0
|
|
137
169
|
*/
|
|
138
170
|
emit(callback: string, ...args: Json[]): void;
|
|
139
171
|
/**
|
|
140
172
|
* The user closes the window with its title-bar button: the window closes
|
|
141
173
|
* and the plugin's `window.onClose` listeners run (unlike the plugin's own
|
|
142
174
|
* `close()`).
|
|
175
|
+
*
|
|
176
|
+
* @capability None.
|
|
177
|
+
*
|
|
178
|
+
* @example Close a window the way the user does
|
|
179
|
+
* The test closes the plugin's window with its title-bar button and checks
|
|
180
|
+
* that the plugin stopped its timer. Unlike the plugin's own `close()`,
|
|
181
|
+
* `userClose` runs the plugin's `onClose` listeners.
|
|
182
|
+
* ```ts
|
|
183
|
+
* import assert from "node:assert/strict";
|
|
184
|
+
* declare const host: TestHost;
|
|
185
|
+
* // ---cut---
|
|
186
|
+
* host.window("clock").userClose();
|
|
187
|
+
* await host.settle();
|
|
188
|
+
* assert.equal(host.window("clock").visible, false);
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* @since 1.0.0
|
|
143
192
|
*/
|
|
144
193
|
userClose(): void;
|
|
145
194
|
}
|
|
@@ -147,6 +196,8 @@ export interface FakeWindow {
|
|
|
147
196
|
* A file dialog as the player shows it ({@link TestHost.fileDialogs}).
|
|
148
197
|
*
|
|
149
198
|
* @since 1.5.11
|
|
199
|
+
*
|
|
200
|
+
* @category Testing
|
|
150
201
|
*/
|
|
151
202
|
export interface FileDialogText {
|
|
152
203
|
/** Which dialog. */
|
|
@@ -177,6 +228,16 @@ export interface FileDialogText {
|
|
|
177
228
|
* await toggle.run();
|
|
178
229
|
* assert.equal(host.command("toggle-loop").state.checked, true);
|
|
179
230
|
* ```
|
|
231
|
+
*
|
|
232
|
+
* @remarks
|
|
233
|
+
* The host's record of one command: what the plugin declared, the state
|
|
234
|
+
* it last sent, and how the menu shows it in {@link TestHost.locale}.
|
|
235
|
+
* Read it again after `settle()` to see changes; `run` executes it as the
|
|
236
|
+
* menu would.
|
|
237
|
+
*
|
|
238
|
+
* @capability None.
|
|
239
|
+
* @since 1.0.0
|
|
240
|
+
* @category Testing
|
|
180
241
|
*/
|
|
181
242
|
export interface FakeCommand {
|
|
182
243
|
/**
|
|
@@ -227,6 +288,23 @@ export interface FakeCommand {
|
|
|
227
288
|
* Execute the command the way the menu would, then wait until the host is
|
|
228
289
|
* idle. Rejects (with a {@link HostError}) when the command is disabled or
|
|
229
290
|
* busy, like the player, which does not call `run` then.
|
|
291
|
+
*
|
|
292
|
+
* @capability None.
|
|
293
|
+
* @throws `command` (rejects) A `HostError`: the command is disabled or
|
|
294
|
+
* busy (the message says which).
|
|
295
|
+
*
|
|
296
|
+
* @example Check that a disabled item refuses to run
|
|
297
|
+
* The test checks that Export cannot run while nothing is open. Like the
|
|
298
|
+
* player, the host does not call `run` for a disabled or busy command;
|
|
299
|
+
* the promise rejects with a `HostError`.
|
|
300
|
+
* ```ts
|
|
301
|
+
* import assert from "node:assert/strict";
|
|
302
|
+
* declare const host: TestHost;
|
|
303
|
+
* // ---cut---
|
|
304
|
+
* await assert.rejects(host.command("export").run());
|
|
305
|
+
* ```
|
|
306
|
+
*
|
|
307
|
+
* @since 1.0.0
|
|
230
308
|
*/
|
|
231
309
|
run(): Promise<void>;
|
|
232
310
|
}
|
|
@@ -235,6 +313,29 @@ export interface FakeCommand {
|
|
|
235
313
|
* it: an entry of {@link TestHost.barButtons}.
|
|
236
314
|
*
|
|
237
315
|
* @since 1.5.29
|
|
316
|
+
*
|
|
317
|
+
* @remarks
|
|
318
|
+
* A bottom-bar button as the player would show it, derived from the
|
|
319
|
+
* command's declaration and state each time it is read: clickable while
|
|
320
|
+
* the command is enabled and not busy, accent-coloured while checked, with
|
|
321
|
+
* the command's title (and reason) as the tooltip.
|
|
322
|
+
*
|
|
323
|
+
* @capability None.
|
|
324
|
+
*
|
|
325
|
+
* @example Check a bar button's tooltip while it is disabled
|
|
326
|
+
* The test checks that the Export button shows why it cannot be clicked.
|
|
327
|
+
* The tooltip is the command's title; while the command is disabled or
|
|
328
|
+
* busy and has a non-empty `reason`, the reason follows on a second line.
|
|
329
|
+
* ```ts
|
|
330
|
+
* import assert from "node:assert/strict";
|
|
331
|
+
* declare const host: TestHost;
|
|
332
|
+
* // ---cut---
|
|
333
|
+
* const [button] = host.barButtons;
|
|
334
|
+
* assert.equal(button?.enabled, false);
|
|
335
|
+
* assert.match(button?.tooltip ?? "", /\n/); // the command declares a reason
|
|
336
|
+
* ```
|
|
337
|
+
*
|
|
338
|
+
* @category Testing
|
|
238
339
|
*/
|
|
239
340
|
export interface FakeBarButton {
|
|
240
341
|
/** The command's local id. */
|
|
@@ -258,6 +359,24 @@ export interface FakeBarButton {
|
|
|
258
359
|
* Click the button, then wait until the host is idle: runs the command
|
|
259
360
|
* as its menu item would. Rejects (with a {@link HostError}) while the
|
|
260
361
|
* button is disabled, and once the command is gone.
|
|
362
|
+
*
|
|
363
|
+
* @capability None.
|
|
364
|
+
* @throws `command` (rejects) A `HostError`: the command is disabled or
|
|
365
|
+
* busy.
|
|
366
|
+
* @throws `missing` (rejects) A `HostError`: the command is gone.
|
|
367
|
+
*
|
|
368
|
+
* @example Click the button and wait for its effect
|
|
369
|
+
* The test clicks the plugin's button and checks the OSD. `click` runs the
|
|
370
|
+
* command like its menu item and resolves once the host is idle.
|
|
371
|
+
* ```ts
|
|
372
|
+
* import assert from "node:assert/strict";
|
|
373
|
+
* declare const host: TestHost;
|
|
374
|
+
* // ---cut---
|
|
375
|
+
* await host.barButtons[0]?.click();
|
|
376
|
+
* assert.ok(host.osd.length > 0);
|
|
377
|
+
* ```
|
|
378
|
+
*
|
|
379
|
+
* @since 1.5.29
|
|
261
380
|
*/
|
|
262
381
|
click(): Promise<void>;
|
|
263
382
|
}
|
|
@@ -265,6 +384,31 @@ export interface FakeBarButton {
|
|
|
265
384
|
* A generated stream (`plugin.player.openStream`) as the test host sees it:
|
|
266
385
|
* the fake player end of the frame connection. Assertion surface; see
|
|
267
386
|
* {@link TestHost.producers}.
|
|
387
|
+
*
|
|
388
|
+
* @remarks
|
|
389
|
+
* The player's end of a generated stream's frame connection
|
|
390
|
+
* ({@link TestHost.producers}): how many frames arrived and whether the
|
|
391
|
+
* plugin released it or the player retired it. Tests assert on it; nothing
|
|
392
|
+
* is played.
|
|
393
|
+
*
|
|
394
|
+
* @capability None.
|
|
395
|
+
*
|
|
396
|
+
* @example Check that the stream delivers frames
|
|
397
|
+
* The test starts the plugin's generator and checks that video and audio
|
|
398
|
+
* arrive. The counters grow as the SDK pulls frames and sends them over
|
|
399
|
+
* the fake connection.
|
|
400
|
+
* ```ts
|
|
401
|
+
* import assert from "node:assert/strict";
|
|
402
|
+
* declare const host: TestHost;
|
|
403
|
+
* // ---cut---
|
|
404
|
+
* await host.command("start-generator").run();
|
|
405
|
+
* await host.settle(200); // let a few frames through
|
|
406
|
+
* const [producer] = host.producers.values();
|
|
407
|
+
* assert.ok((producer?.videoFrames ?? 0) > 0 && (producer?.receivedFrames ?? 0) > 0);
|
|
408
|
+
* ```
|
|
409
|
+
*
|
|
410
|
+
* @since 1.0.0
|
|
411
|
+
* @category Testing
|
|
268
412
|
*/
|
|
269
413
|
export interface FakeProducer {
|
|
270
414
|
/** The producer id the host assigned (`1`, `2`, … per host). */
|
|
@@ -289,7 +433,12 @@ export interface FakeProducer {
|
|
|
289
433
|
*/
|
|
290
434
|
droppedWhileSelected: boolean;
|
|
291
435
|
}
|
|
292
|
-
/**
|
|
436
|
+
/**
|
|
437
|
+
* A Markdown document as {@link TestHost.markdown} reads it back.
|
|
438
|
+
*
|
|
439
|
+
* @since 1.1.0
|
|
440
|
+
* @category Testing
|
|
441
|
+
*/
|
|
293
442
|
export interface MarkdownWire {
|
|
294
443
|
/** The Markdown text. */
|
|
295
444
|
text: string;
|
|
@@ -362,6 +511,19 @@ export interface MarkdownWire {
|
|
|
362
511
|
* await stop();
|
|
363
512
|
* });
|
|
364
513
|
* ```
|
|
514
|
+
*
|
|
515
|
+
* @remarks
|
|
516
|
+
* An in-memory player that speaks the real wire protocol, so the SDK's own
|
|
517
|
+
* logic runs as it does in the player; only the player side is simulated
|
|
518
|
+
* (no decoding, no Slint, no windows). Make one per test, preset it if the
|
|
519
|
+
* plugin reads something during activation, start the plugin with
|
|
520
|
+
* {@link startPlugin}, drive it, `settle()`, and assert on what it
|
|
521
|
+
* recorded.
|
|
522
|
+
*
|
|
523
|
+
* @capability None.
|
|
524
|
+
* @see [Test a plugin](../../docs/how-to/testing.md)
|
|
525
|
+
* @since 1.0.0
|
|
526
|
+
* @category Testing
|
|
365
527
|
*/
|
|
366
528
|
export declare class TestHost implements Transport {
|
|
367
529
|
#private;
|
|
@@ -479,6 +641,20 @@ export declare class TestHost implements Transport {
|
|
|
479
641
|
*
|
|
480
642
|
* @param directory - The package directory (holding `locales/`).
|
|
481
643
|
* @since 1.5.9
|
|
644
|
+
*
|
|
645
|
+
* @capability None.
|
|
646
|
+
*
|
|
647
|
+
* @example Load the translations after changing the language
|
|
648
|
+
* The test switches the host to German before starting the plugin and
|
|
649
|
+
* loads that catalog itself (`startPlugin` does the same). Texts are then
|
|
650
|
+
* shown in German.
|
|
651
|
+
* ```ts
|
|
652
|
+
* declare const host: TestHost;
|
|
653
|
+
* declare const directory: string;
|
|
654
|
+
* // ---cut---
|
|
655
|
+
* host.locale = "de";
|
|
656
|
+
* host.loadCatalog(directory); // locales/de.po (or de.json)
|
|
657
|
+
* ```
|
|
482
658
|
*/
|
|
483
659
|
loadCatalog(directory: string): void;
|
|
484
660
|
/**
|
|
@@ -502,6 +678,8 @@ export declare class TestHost implements Transport {
|
|
|
502
678
|
* ```
|
|
503
679
|
*
|
|
504
680
|
* @since 1.5.9
|
|
681
|
+
*
|
|
682
|
+
* @capability None.
|
|
505
683
|
*/
|
|
506
684
|
translate(text: TextValue, args?: TemplateArgs): string;
|
|
507
685
|
/**
|
|
@@ -517,6 +695,24 @@ export declare class TestHost implements Transport {
|
|
|
517
695
|
*
|
|
518
696
|
* @param language - `"system"` or a locale.
|
|
519
697
|
* @since 1.5.9
|
|
698
|
+
*
|
|
699
|
+
* @capability None.
|
|
700
|
+
*
|
|
701
|
+
* @example Simulate the user choosing French for the next start
|
|
702
|
+
* The plugin hears that the saved interface language changed. The host
|
|
703
|
+
* pushes `appearance.changed`, which a plugin with `events` sees in
|
|
704
|
+
* `appearance.language` once it has read it and subscribed; this run's
|
|
705
|
+
* language does not change.
|
|
706
|
+
* ```ts
|
|
707
|
+
* import assert from "node:assert/strict";
|
|
708
|
+
* declare const host: TestHost;
|
|
709
|
+
* // ---cut---
|
|
710
|
+
* void plugin.appearance.language; // read once: the SDK then follows it
|
|
711
|
+
* plugin.appearance.onChange(() => {}); // subscribes to appearance events
|
|
712
|
+
* host.setLanguage("fr");
|
|
713
|
+
* await host.settle();
|
|
714
|
+
* assert.equal(plugin.appearance.language, "fr");
|
|
715
|
+
* ```
|
|
520
716
|
*/
|
|
521
717
|
setLanguage(language: LanguagePreference): void;
|
|
522
718
|
/**
|
|
@@ -726,6 +922,9 @@ export declare class TestHost implements Transport {
|
|
|
726
922
|
* await host.settle();
|
|
727
923
|
* assert.equal(plugin.timeline.marks.length, 2);
|
|
728
924
|
* ```
|
|
925
|
+
*
|
|
926
|
+
* @capability None.
|
|
927
|
+
* @since 1.0.0
|
|
729
928
|
*/
|
|
730
929
|
setTimelineLayer(pluginId: string, marks: {
|
|
731
930
|
time: number;
|
|
@@ -766,6 +965,9 @@ export declare class TestHost implements Transport {
|
|
|
766
965
|
* join(plugin.dataDirectory, "cover.png"),
|
|
767
966
|
* );
|
|
768
967
|
* ```
|
|
968
|
+
*
|
|
969
|
+
* @capability None.
|
|
970
|
+
* @since 1.0.0
|
|
769
971
|
*/
|
|
770
972
|
imagePath(value: Json | undefined): string | null;
|
|
771
973
|
/** `drops.provide` registrations of this plugin, in order (`id` is the SDK's). */
|
|
@@ -806,6 +1008,10 @@ export declare class TestHost implements Transport {
|
|
|
806
1008
|
* modifiers: { alt: true },
|
|
807
1009
|
* });
|
|
808
1010
|
* ```
|
|
1011
|
+
*
|
|
1012
|
+
* @capability None.
|
|
1013
|
+
* @throws Never: files nobody takes are ignored, as in the player.
|
|
1014
|
+
* @since 1.0.0
|
|
809
1015
|
*/
|
|
810
1016
|
drop(paths: string[], options?: {
|
|
811
1017
|
target?: "video" | "panel";
|
|
@@ -824,6 +1030,24 @@ export declare class TestHost implements Transport {
|
|
|
824
1030
|
/**
|
|
825
1031
|
* Simulate another plugin switching the palette: updates
|
|
826
1032
|
* {@link TestHost.appearance} and pushes `appearance.changed`.
|
|
1033
|
+
*
|
|
1034
|
+
* @capability None.
|
|
1035
|
+
*
|
|
1036
|
+
* @example Simulate another plugin switching to the light palette
|
|
1037
|
+
* The plugin hears the palette change. The host updates `appearance` and
|
|
1038
|
+
* pushes `appearance.changed` to a plugin that listens with `events`.
|
|
1039
|
+
* ```ts
|
|
1040
|
+
* import assert from "node:assert/strict";
|
|
1041
|
+
* declare const host: TestHost;
|
|
1042
|
+
* // ---cut---
|
|
1043
|
+
* const themes: ThemeId[] = [];
|
|
1044
|
+
* plugin.appearance.onChange((theme) => themes.push(theme)); // subscribes (`events`)
|
|
1045
|
+
* host.setAppearance("vestra-light");
|
|
1046
|
+
* await host.settle();
|
|
1047
|
+
* assert.deepEqual(themes, ["vestra-light"]);
|
|
1048
|
+
* ```
|
|
1049
|
+
*
|
|
1050
|
+
* @since 1.0.0
|
|
827
1051
|
*/
|
|
828
1052
|
setAppearance(theme: ThemeId): void;
|
|
829
1053
|
/**
|
|
@@ -874,6 +1098,9 @@ export declare class TestHost implements Transport {
|
|
|
874
1098
|
* await host.settle();
|
|
875
1099
|
* assert.equal(page.props["step"], 10);
|
|
876
1100
|
* ```
|
|
1101
|
+
*
|
|
1102
|
+
* @capability None.
|
|
1103
|
+
* @since 1.0.0
|
|
877
1104
|
*/
|
|
878
1105
|
settingsPage(id: string): {
|
|
879
1106
|
/** The page's settings category. */
|
|
@@ -903,6 +1130,23 @@ export declare class TestHost implements Transport {
|
|
|
903
1130
|
/**
|
|
904
1131
|
* Simulate the backdrop's `effective` changing (`false`: a video frame
|
|
905
1132
|
* appeared; `true`: there is none again); pushed to the plugin.
|
|
1133
|
+
*
|
|
1134
|
+
* @capability None.
|
|
1135
|
+
*
|
|
1136
|
+
* @example Make a video picture replace the backdrop
|
|
1137
|
+
* The plugin's backdrop hears that a video frame now covers it. `false`
|
|
1138
|
+
* means a picture appeared; the change is pushed like the player's
|
|
1139
|
+
* `window.state`.
|
|
1140
|
+
* ```ts
|
|
1141
|
+
* import assert from "node:assert/strict";
|
|
1142
|
+
* declare const host: TestHost;
|
|
1143
|
+
* // ---cut---
|
|
1144
|
+
* host.setBackdropEffective(false);
|
|
1145
|
+
* await host.settle();
|
|
1146
|
+
* assert.equal(plugin.panels.backdrop.state?.effective, false);
|
|
1147
|
+
* ```
|
|
1148
|
+
*
|
|
1149
|
+
* @since 1.0.0
|
|
906
1150
|
*/
|
|
907
1151
|
setBackdropEffective(effective: boolean): void;
|
|
908
1152
|
/**
|
|
@@ -935,6 +1179,8 @@ export declare class TestHost implements Transport {
|
|
|
935
1179
|
* ```
|
|
936
1180
|
*
|
|
937
1181
|
* @since 1.5.2
|
|
1182
|
+
*
|
|
1183
|
+
* @capability None.
|
|
938
1184
|
*/
|
|
939
1185
|
mountOther(slot: "bottom" | "sidebar" | "backdrop", plugin: string, options?: {
|
|
940
1186
|
title?: string;
|
|
@@ -944,6 +1190,21 @@ export declare class TestHost implements Transport {
|
|
|
944
1190
|
* when its tab was current, the next tab (else the previous one) is.
|
|
945
1191
|
*
|
|
946
1192
|
* @since 1.5.2
|
|
1193
|
+
*
|
|
1194
|
+
* @capability None.
|
|
1195
|
+
*
|
|
1196
|
+
* @example Let the playlist's tab go away
|
|
1197
|
+
* The other plugin's sidebar tab disappears and the plugin's own tab
|
|
1198
|
+
* becomes current. When the removed tab was current, the next tab (else
|
|
1199
|
+
* the previous one) becomes current, as in the player.
|
|
1200
|
+
* ```ts
|
|
1201
|
+
* import assert from "node:assert/strict";
|
|
1202
|
+
* declare const host: TestHost;
|
|
1203
|
+
* // ---cut---
|
|
1204
|
+
* host.unmountOther("vestra.playlist");
|
|
1205
|
+
* await host.settle();
|
|
1206
|
+
* assert.equal(host.layout.sidebar?.panels?.length, 1);
|
|
1207
|
+
* ```
|
|
947
1208
|
*/
|
|
948
1209
|
unmountOther(plugin: string): void;
|
|
949
1210
|
/**
|
|
@@ -952,6 +1213,20 @@ export declare class TestHost implements Transport {
|
|
|
952
1213
|
* becomes the current tab. Pushed as a `window.state` change.
|
|
953
1214
|
*
|
|
954
1215
|
* @since 1.5.2
|
|
1216
|
+
*
|
|
1217
|
+
* @capability None.
|
|
1218
|
+
*
|
|
1219
|
+
* @example Click another plugin's sidebar tab
|
|
1220
|
+
* The user switches the sidebar to the playlist; the plugin's panel is in
|
|
1221
|
+
* a background tab now. The change is pushed as `window.state`.
|
|
1222
|
+
* ```ts
|
|
1223
|
+
* import assert from "node:assert/strict";
|
|
1224
|
+
* declare const host: TestHost;
|
|
1225
|
+
* // ---cut---
|
|
1226
|
+
* host.selectTab("vestra.playlist");
|
|
1227
|
+
* await host.settle();
|
|
1228
|
+
* assert.notEqual(host.layout.sidebar?.owner, 1); // the plugin under test is owner 1
|
|
1229
|
+
* ```
|
|
955
1230
|
*/
|
|
956
1231
|
selectTab(plugin: string): void;
|
|
957
1232
|
/**
|
|
@@ -968,6 +1243,24 @@ export declare class TestHost implements Transport {
|
|
|
968
1243
|
* Simulate another plugin taking the display layer first (the plugin's
|
|
969
1244
|
* `video.view()` then fails with `conflict`), or, with `null`, releasing
|
|
970
1245
|
* it (values reset to the defaults).
|
|
1246
|
+
*
|
|
1247
|
+
* @capability None.
|
|
1248
|
+
*
|
|
1249
|
+
* @example Let another plugin own the display layer
|
|
1250
|
+
* The plugin's `video.view()` fails with `conflict` because another plugin
|
|
1251
|
+
* took the display layer first. `null` releases it again.
|
|
1252
|
+
* ```ts
|
|
1253
|
+
* import assert from "node:assert/strict";
|
|
1254
|
+
* declare const host: TestHost;
|
|
1255
|
+
* // ---cut---
|
|
1256
|
+
* host.setVideoViewOwner("someone.zoom");
|
|
1257
|
+
* const view = plugin.video.view();
|
|
1258
|
+
* view.set({ zoom: 2 });
|
|
1259
|
+
* await host.settle();
|
|
1260
|
+
* assert.equal(view.status.state, "failed");
|
|
1261
|
+
* ```
|
|
1262
|
+
*
|
|
1263
|
+
* @since 1.0.0
|
|
971
1264
|
*/
|
|
972
1265
|
setVideoViewOwner(pluginId: string | null): void;
|
|
973
1266
|
/**
|
|
@@ -980,13 +1273,34 @@ export declare class TestHost implements Transport {
|
|
|
980
1273
|
owner: string | null;
|
|
981
1274
|
/** The values the player holds. */
|
|
982
1275
|
values: RenderSettings;
|
|
983
|
-
/**
|
|
1276
|
+
/**
|
|
1277
|
+
* `true`: GPU rendering; `false`: software rendering (`unsupported`).
|
|
1278
|
+
* `plugin.app.system()` reports it as `rendering`.
|
|
1279
|
+
*/
|
|
984
1280
|
gpu: boolean;
|
|
985
1281
|
};
|
|
986
1282
|
/**
|
|
987
1283
|
* Simulate another plugin owning the render options (the plugin's
|
|
988
1284
|
* `video.render()` then fails with `conflict`), or, with `null`, releasing
|
|
989
1285
|
* them (values reset to the defaults).
|
|
1286
|
+
*
|
|
1287
|
+
* @capability None.
|
|
1288
|
+
*
|
|
1289
|
+
* @example Let another plugin own the render options
|
|
1290
|
+
* The plugin's render options report `conflict` while another plugin owns
|
|
1291
|
+
* them; `null` releases them and resets the values to the defaults.
|
|
1292
|
+
* ```ts
|
|
1293
|
+
* import assert from "node:assert/strict";
|
|
1294
|
+
* declare const host: TestHost;
|
|
1295
|
+
* // ---cut---
|
|
1296
|
+
* host.setVideoRenderOwner("someone.hdr");
|
|
1297
|
+
* const render = plugin.video.render();
|
|
1298
|
+
* render.set({ toneMapping: "bt.2390" });
|
|
1299
|
+
* await host.settle();
|
|
1300
|
+
* assert.equal(render.status.state, "failed");
|
|
1301
|
+
* ```
|
|
1302
|
+
*
|
|
1303
|
+
* @since 1.0.0
|
|
990
1304
|
*/
|
|
991
1305
|
setVideoRenderOwner(pluginId: string | null): void;
|
|
992
1306
|
/**
|
|
@@ -1010,6 +1324,9 @@ export declare class TestHost implements Transport {
|
|
|
1010
1324
|
* await host.settle();
|
|
1011
1325
|
* assert.equal(render.status.state, "failed");
|
|
1012
1326
|
* ```
|
|
1327
|
+
*
|
|
1328
|
+
* @capability None.
|
|
1329
|
+
* @since 1.0.0
|
|
1013
1330
|
*/
|
|
1014
1331
|
failVideoRender(code: "failed" | "unsupported", message: string): void;
|
|
1015
1332
|
/**
|
|
@@ -1074,6 +1391,13 @@ export declare class TestHost implements Transport {
|
|
|
1074
1391
|
bytes: Buffer[];
|
|
1075
1392
|
/** The announced total size in bytes. */
|
|
1076
1393
|
expected: number;
|
|
1394
|
+
/**
|
|
1395
|
+
* The source generation it was begun for; like the player, a new
|
|
1396
|
+
* source drops the uploads of the old one.
|
|
1397
|
+
*
|
|
1398
|
+
* @since 1.5.34
|
|
1399
|
+
*/
|
|
1400
|
+
generation?: number;
|
|
1077
1401
|
}>;
|
|
1078
1402
|
/** Snapshots taken with `media.capture`, by snapshot id. Wire-level. */
|
|
1079
1403
|
readonly snapshots: Map<number, Json>;
|
|
@@ -1145,6 +1469,21 @@ export declare class TestHost implements Transport {
|
|
|
1145
1469
|
* What `plugin.resolvers.fileTypes` reports: the extensions of this
|
|
1146
1470
|
* plugin's file resolvers and of {@link TestHost.otherResolvers}, sorted,
|
|
1147
1471
|
* each once.
|
|
1472
|
+
*
|
|
1473
|
+
* @capability None.
|
|
1474
|
+
*
|
|
1475
|
+
* @example Check the file types a resolver adds
|
|
1476
|
+
* The test checks the list the plugin will read as
|
|
1477
|
+
* `resolvers.fileTypes`: the extensions of its own file resolvers and of
|
|
1478
|
+
* `otherResolvers`, sorted, each once.
|
|
1479
|
+
* ```ts
|
|
1480
|
+
* import assert from "node:assert/strict";
|
|
1481
|
+
* declare const host: TestHost;
|
|
1482
|
+
* // ---cut---
|
|
1483
|
+
* assert.deepEqual(host.fileTypes(), ["ch8"]);
|
|
1484
|
+
* ```
|
|
1485
|
+
*
|
|
1486
|
+
* @since 1.5.8
|
|
1148
1487
|
*/
|
|
1149
1488
|
fileTypes(): string[];
|
|
1150
1489
|
/**
|
|
@@ -1167,6 +1506,9 @@ export declare class TestHost implements Transport {
|
|
|
1167
1506
|
* await host.settle();
|
|
1168
1507
|
* assert.deepEqual(plugin.resolvers.fileTypes, ["ch8"]);
|
|
1169
1508
|
* ```
|
|
1509
|
+
*
|
|
1510
|
+
* @capability None.
|
|
1511
|
+
* @since 1.5.8
|
|
1170
1512
|
*/
|
|
1171
1513
|
updateFileTypes(): void;
|
|
1172
1514
|
/**
|
|
@@ -1266,8 +1608,12 @@ export declare class TestHost implements Transport {
|
|
|
1266
1608
|
* @since 1.5.25
|
|
1267
1609
|
*/
|
|
1268
1610
|
readonly sessionStorage: Map<string, Json>;
|
|
1269
|
-
/**
|
|
1270
|
-
|
|
1611
|
+
/**
|
|
1612
|
+
* What `plugin.app.system()` reports. Its `rendering` follows
|
|
1613
|
+
* {@link TestHost.videoRender | videoRender.gpu} (`"gpu"` or
|
|
1614
|
+
* `"software"`), so one switch covers the render options and the fact.
|
|
1615
|
+
*/
|
|
1616
|
+
systemInfo: Omit<WireSystemInfo, "rendering">;
|
|
1271
1617
|
/**
|
|
1272
1618
|
* What `plugin.app` reports. Set it before {@link startPlugin}: the plugin
|
|
1273
1619
|
* receives it once at start-up.
|
|
@@ -1305,6 +1651,11 @@ export declare class TestHost implements Transport {
|
|
|
1305
1651
|
* `"test.plugin"` by default).
|
|
1306
1652
|
*/
|
|
1307
1653
|
manifestId: string;
|
|
1654
|
+
/**
|
|
1655
|
+
* A fresh in-memory player: nothing open, no plugin, the player's core
|
|
1656
|
+
* actions registered. Preset what the plugin reads during activation, then
|
|
1657
|
+
* pass it to {@link startPlugin} as `host`.
|
|
1658
|
+
*/
|
|
1308
1659
|
constructor();
|
|
1309
1660
|
/** The `player.setStepSeek` value in effect (default 5). */
|
|
1310
1661
|
stepSeek: number;
|
|
@@ -1373,8 +1724,10 @@ export declare class TestHost implements Transport {
|
|
|
1373
1724
|
/**
|
|
1374
1725
|
* One of the 14 core actions (`play-pause`, `stop`, `seek-forward`, ...)
|
|
1375
1726
|
* that the test host registers like the player, as `host/<id>`. Throws for
|
|
1376
|
-
* an unknown id. `run()` executes it
|
|
1377
|
-
*
|
|
1727
|
+
* an unknown id. `run()` executes it like its menu item: a disabled
|
|
1728
|
+
* action rejects with `command`, as in the player (`plugin.host.run`
|
|
1729
|
+
* rejects with `unavailable` instead); otherwise it runs with the
|
|
1730
|
+
* player's checks and writes its on-screen text to {@link TestHost.osd}.
|
|
1378
1731
|
*
|
|
1379
1732
|
* @example Pause through the player's own action
|
|
1380
1733
|
* The test pauses playback the way the Space key does and checks that the
|
|
@@ -1390,6 +1743,9 @@ export declare class TestHost implements Transport {
|
|
|
1390
1743
|
* assert.equal(host.source.paused, true);
|
|
1391
1744
|
* assert.deepEqual(host.coreRuns, ["play-pause"]);
|
|
1392
1745
|
* ```
|
|
1746
|
+
*
|
|
1747
|
+
* @capability None.
|
|
1748
|
+
* @since 1.0.0
|
|
1393
1749
|
*/
|
|
1394
1750
|
coreAction(id: string): FakeCommand;
|
|
1395
1751
|
/**
|
|
@@ -1431,9 +1787,34 @@ export declare class TestHost implements Transport {
|
|
|
1431
1787
|
* assert.deepEqual(host.osd, ["Folder not found"]);
|
|
1432
1788
|
* host.reset("system.openPath");
|
|
1433
1789
|
* ```
|
|
1790
|
+
*
|
|
1791
|
+
* @capability None.
|
|
1792
|
+
* @since 1.0.0
|
|
1434
1793
|
*/
|
|
1435
1794
|
handle(method: string, handler: Handler): void;
|
|
1436
|
-
/**
|
|
1795
|
+
/**
|
|
1796
|
+
* Restore the default behaviour of a method replaced with {@link TestHost.handle}.
|
|
1797
|
+
*
|
|
1798
|
+
* @capability None.
|
|
1799
|
+
*
|
|
1800
|
+
* @example Restore the default answer after a simulated failure
|
|
1801
|
+
* The first write fails, the second succeeds. `reset` removes the handler
|
|
1802
|
+
* that `handle` installed, so the method is answered by the test host
|
|
1803
|
+
* again.
|
|
1804
|
+
* ```ts
|
|
1805
|
+
* import assert from "node:assert/strict";
|
|
1806
|
+
* declare const host: TestHost;
|
|
1807
|
+
* // ---cut---
|
|
1808
|
+
* host.handle("clipboard.writeText", () => {
|
|
1809
|
+
* throw new HostError("failed", "denied");
|
|
1810
|
+
* });
|
|
1811
|
+
* await assert.rejects(plugin.clipboard.writeText("x"));
|
|
1812
|
+
* host.reset("clipboard.writeText");
|
|
1813
|
+
* await plugin.clipboard.writeText("x"); // the default handler again
|
|
1814
|
+
* ```
|
|
1815
|
+
*
|
|
1816
|
+
* @since 1.0.0
|
|
1817
|
+
*/
|
|
1437
1818
|
reset(method: string): void;
|
|
1438
1819
|
/**
|
|
1439
1820
|
* Deliver a host event to the plugin. Like the player, subscription-based
|
|
@@ -1444,6 +1825,22 @@ export declare class TestHost implements Transport {
|
|
|
1444
1825
|
*
|
|
1445
1826
|
* @param event - The wire event name.
|
|
1446
1827
|
* @param data - The event payload (wire-level shape).
|
|
1828
|
+
*
|
|
1829
|
+
* @capability None.
|
|
1830
|
+
*
|
|
1831
|
+
* @example Deliver a raw event the helpers do not cover
|
|
1832
|
+
* The test pushes a `window.state` event after changing `layout` by hand.
|
|
1833
|
+
* Like the player, the host delivers it only when the plugin subscribed;
|
|
1834
|
+
* most tests use `setSource`, `setMainWindow` and the other helpers
|
|
1835
|
+
* instead.
|
|
1836
|
+
* ```ts
|
|
1837
|
+
* declare const host: TestHost;
|
|
1838
|
+
* // ---cut---
|
|
1839
|
+
* host.emit("window.state", {}); // no facts: the SDK reads window.state again
|
|
1840
|
+
* await host.settle();
|
|
1841
|
+
* ```
|
|
1842
|
+
*
|
|
1843
|
+
* @since 1.0.0
|
|
1447
1844
|
*/
|
|
1448
1845
|
emit(event: string, data: unknown): void;
|
|
1449
1846
|
/**
|
|
@@ -1471,6 +1868,9 @@ export declare class TestHost implements Transport {
|
|
|
1471
1868
|
* host.setSource({ phase: "ended", terminalReason: "natural" });
|
|
1472
1869
|
* await host.settle();
|
|
1473
1870
|
* ```
|
|
1871
|
+
*
|
|
1872
|
+
* @capability None.
|
|
1873
|
+
* @since 1.0.0
|
|
1474
1874
|
*/
|
|
1475
1875
|
setSource(patch: Partial<SourceState>): void;
|
|
1476
1876
|
/**
|
|
@@ -1495,6 +1895,9 @@ export declare class TestHost implements Transport {
|
|
|
1495
1895
|
* assert.equal(plugin.window.state.fullscreen, true);
|
|
1496
1896
|
* host.setMainWindow({ pictureInPicture: { supported: true, active: false } });
|
|
1497
1897
|
* ```
|
|
1898
|
+
*
|
|
1899
|
+
* @capability None.
|
|
1900
|
+
* @since 1.0.0
|
|
1498
1901
|
*/
|
|
1499
1902
|
setMainWindow(patch: Partial<{
|
|
1500
1903
|
fullscreen: boolean;
|
|
@@ -1511,6 +1914,22 @@ export declare class TestHost implements Transport {
|
|
|
1511
1914
|
* The pointer reached the right edge in fullscreen (`true`) or left the
|
|
1512
1915
|
* popped-out sidebar (`false`): the attached sidebar pops out or collapses
|
|
1513
1916
|
* (reference §6.3). No effect outside fullscreen, when hidden or floating.
|
|
1917
|
+
*
|
|
1918
|
+
* @capability None.
|
|
1919
|
+
*
|
|
1920
|
+
* @example Pop the sidebar out in fullscreen
|
|
1921
|
+
* The pointer reaches the right edge in fullscreen and the attached
|
|
1922
|
+
* sidebar pops out over the video. Outside fullscreen, or with the
|
|
1923
|
+
* sidebar hidden or floating, nothing happens.
|
|
1924
|
+
* ```ts
|
|
1925
|
+
* declare const host: TestHost;
|
|
1926
|
+
* // ---cut---
|
|
1927
|
+
* host.setMainWindow({ fullscreen: true });
|
|
1928
|
+
* host.popSidebar(true);
|
|
1929
|
+
* await host.settle();
|
|
1930
|
+
* ```
|
|
1931
|
+
*
|
|
1932
|
+
* @since 1.0.0
|
|
1514
1933
|
*/
|
|
1515
1934
|
popSidebar(popped: boolean): void;
|
|
1516
1935
|
/**
|
|
@@ -1536,6 +1955,9 @@ export declare class TestHost implements Transport {
|
|
|
1536
1955
|
* await host.settle();
|
|
1537
1956
|
* assert.equal(plugin.player.isCurrent(before), false);
|
|
1538
1957
|
* ```
|
|
1958
|
+
*
|
|
1959
|
+
* @capability None.
|
|
1960
|
+
* @since 1.0.0
|
|
1539
1961
|
*/
|
|
1540
1962
|
openElsewhere(source: string, phase?: SourceState["phase"]): void;
|
|
1541
1963
|
/**
|
|
@@ -1558,6 +1980,9 @@ export declare class TestHost implements Transport {
|
|
|
1558
1980
|
* const [producer] = host.producers.values();
|
|
1559
1981
|
* host.failStream(producer!.id, "producer transport closed");
|
|
1560
1982
|
* ```
|
|
1983
|
+
*
|
|
1984
|
+
* @capability None.
|
|
1985
|
+
* @since 1.5.7
|
|
1561
1986
|
*/
|
|
1562
1987
|
failStream(producerId: number, message: string): void;
|
|
1563
1988
|
/**
|
|
@@ -1567,11 +1992,12 @@ export declare class TestHost implements Transport {
|
|
|
1567
1992
|
* the conflict rule orders them. A disabled command lets the key pass to
|
|
1568
1993
|
* the next command bound to it (SDK 1.5.12, as player 0.4.3): the one it
|
|
1569
1994
|
* shadowed, then the global scope. The first enabled one runs; `press`
|
|
1570
|
-
* resolves after it ran (`"ran"`)
|
|
1571
|
-
*
|
|
1572
|
-
* reason on the OSD and eats the key (`"reason"`, see
|
|
1573
|
-
* without
|
|
1574
|
-
* nothing runs).
|
|
1995
|
+
* resolves after it ran (`"ran"`). When only disabled commands hold the
|
|
1996
|
+
* key, the first of them decides, as in the player: with a `reason` it
|
|
1997
|
+
* shows the reason on the OSD and eats the key (`"reason"`, see
|
|
1998
|
+
* `host.osd`); without one the key goes on to the focused control
|
|
1999
|
+
* (`"passed"`, nothing runs). Unlike the player, which only logs a key
|
|
2000
|
+
* that reaches a busy command, `press` then rejects, so a test notices. Rejects when nothing is bound. Bindings use the
|
|
1575
2001
|
* reference syntax (`"Space"`, `"Ctrl+O"`, `"Mouse:WheelUp"`), and user
|
|
1576
2002
|
* overrides in `bindings.overlay` apply.
|
|
1577
2003
|
*
|
|
@@ -1588,6 +2014,12 @@ export declare class TestHost implements Transport {
|
|
|
1588
2014
|
* await host.press("Ctrl+B"); // a global binding
|
|
1589
2015
|
* await host.press("Delete", { panel: true }); // while the panel has focus
|
|
1590
2016
|
* ```
|
|
2017
|
+
*
|
|
2018
|
+
* @capability None.
|
|
2019
|
+
* @throws `command` (rejects) A `HostError`: the command that would run is
|
|
2020
|
+
* busy (the player only logs this).
|
|
2021
|
+
* @throws `Error` (rejects) Nothing is bound to the key.
|
|
2022
|
+
* @since 1.0.0
|
|
1591
2023
|
*/
|
|
1592
2024
|
press(binding: string, options?: {
|
|
1593
2025
|
panel?: boolean;
|
|
@@ -1705,6 +2137,9 @@ export declare class TestHost implements Transport {
|
|
|
1705
2137
|
* const rows = host.window("chat").props["messages"] as { body: Json }[];
|
|
1706
2138
|
* assert.equal(host.markdown(rows[0]!.body)?.text, "**Hello**");
|
|
1707
2139
|
* ```
|
|
2140
|
+
*
|
|
2141
|
+
* @capability None.
|
|
2142
|
+
* @since 1.1.0
|
|
1708
2143
|
*/
|
|
1709
2144
|
markdown(value: Json | undefined): MarkdownWire | null;
|
|
1710
2145
|
/**
|
|
@@ -1720,17 +2155,68 @@ export declare class TestHost implements Transport {
|
|
|
1720
2155
|
/**
|
|
1721
2156
|
* Replace the plugin list and push `packages.changed` (another plugin
|
|
1722
2157
|
* started, stopped, was installed or removed).
|
|
2158
|
+
*
|
|
2159
|
+
* @capability None.
|
|
2160
|
+
*
|
|
2161
|
+
* @example Simulate another plugin starting
|
|
2162
|
+
* The plugin's store window hears that a plugin is running now. The list
|
|
2163
|
+
* replaces `packages` and is pushed as `packages.changed`, which the
|
|
2164
|
+
* plugin's `packages.onChange` listeners receive.
|
|
2165
|
+
* ```ts
|
|
2166
|
+
* declare const host: TestHost;
|
|
2167
|
+
* // ---cut---
|
|
2168
|
+
* host.setPackages([...host.packages]); // edit a copy, then push it
|
|
2169
|
+
* await host.settle();
|
|
2170
|
+
* ```
|
|
2171
|
+
*
|
|
2172
|
+
* @since 1.0.0
|
|
1723
2173
|
*/
|
|
1724
2174
|
setPackages(list: TestHost["packages"]): void;
|
|
1725
2175
|
/**
|
|
1726
2176
|
* Simulate another plugin calling `player.next()` / `previous()`: the host
|
|
1727
2177
|
* asks this plugin's sequence provider. Rejects with `unavailable` when
|
|
1728
2178
|
* there is no provider or its flag is false.
|
|
2179
|
+
*
|
|
2180
|
+
* @capability None.
|
|
2181
|
+
* @throws `unavailable` (rejects) A `HostError`: there is no sequence
|
|
2182
|
+
* provider, or its flag is false.
|
|
2183
|
+
*
|
|
2184
|
+
* @example Ask the plugin's provider for the next item
|
|
2185
|
+
* Another plugin calls `player.next()`; the host asks the plugin under
|
|
2186
|
+
* test, which is the sequence provider, and the test checks what it
|
|
2187
|
+
* opened.
|
|
2188
|
+
* ```ts
|
|
2189
|
+
* import assert from "node:assert/strict";
|
|
2190
|
+
* declare const host: TestHost;
|
|
2191
|
+
* // ---cut---
|
|
2192
|
+
* await host.step("next");
|
|
2193
|
+
* await host.settle();
|
|
2194
|
+
* assert.equal(host.source.source, "/media/b.mp4");
|
|
2195
|
+
* ```
|
|
2196
|
+
*
|
|
2197
|
+
* @since 1.0.0
|
|
1729
2198
|
*/
|
|
1730
2199
|
step(direction: "next" | "previous"): Promise<unknown>;
|
|
1731
2200
|
/**
|
|
1732
2201
|
* The plugin's command with this local id. Throws when it is not
|
|
1733
2202
|
* registered (never added, or disposed).
|
|
2203
|
+
*
|
|
2204
|
+
* @capability None.
|
|
2205
|
+
*
|
|
2206
|
+
* @example Read a command's state after a change
|
|
2207
|
+
* The test checks that Export becomes enabled once a file is ready. The
|
|
2208
|
+
* record is updated as the plugin sends new state; read it after
|
|
2209
|
+
* `settle()`.
|
|
2210
|
+
* ```ts
|
|
2211
|
+
* import assert from "node:assert/strict";
|
|
2212
|
+
* declare const host: TestHost;
|
|
2213
|
+
* // ---cut---
|
|
2214
|
+
* host.setSource({ phase: "ready", duration: 60 });
|
|
2215
|
+
* await host.settle();
|
|
2216
|
+
* assert.equal(host.command("export").state.enabled, true); // throws if not registered
|
|
2217
|
+
* ```
|
|
2218
|
+
*
|
|
2219
|
+
* @since 1.0.0
|
|
1734
2220
|
*/
|
|
1735
2221
|
command(id: string): FakeCommand;
|
|
1736
2222
|
/**
|
|
@@ -1777,6 +2263,9 @@ export declare class TestHost implements Transport {
|
|
|
1777
2263
|
* await host.settle();
|
|
1778
2264
|
* assert.equal(host.window("picture").props["brightness"], 0);
|
|
1779
2265
|
* ```
|
|
2266
|
+
*
|
|
2267
|
+
* @capability None.
|
|
2268
|
+
* @since 1.0.0
|
|
1780
2269
|
*/
|
|
1781
2270
|
window(id: string): FakeWindow;
|
|
1782
2271
|
/**
|
|
@@ -1797,6 +2286,9 @@ export declare class TestHost implements Transport {
|
|
|
1797
2286
|
* panel.emit("select", 2);
|
|
1798
2287
|
* await host.settle();
|
|
1799
2288
|
* ```
|
|
2289
|
+
*
|
|
2290
|
+
* @capability None.
|
|
2291
|
+
* @since 1.0.0
|
|
1800
2292
|
*/
|
|
1801
2293
|
mounted(): Omit<FakeWindow, "callbacks" | "userClose"> & {
|
|
1802
2294
|
/** `"bottom"`, `"sidebar"` or `"backdrop"`. */
|
|
@@ -1819,6 +2311,9 @@ export declare class TestHost implements Transport {
|
|
|
1819
2311
|
* // ---cut---
|
|
1820
2312
|
* assert.deepEqual(host.sent("osd.show").at(-1), { text: "Saved" });
|
|
1821
2313
|
* ```
|
|
2314
|
+
*
|
|
2315
|
+
* @capability None.
|
|
2316
|
+
* @since 1.0.0
|
|
1822
2317
|
*/
|
|
1823
2318
|
sent(method: string): Record<string, Json>[];
|
|
1824
2319
|
/**
|
|
@@ -1864,11 +2359,32 @@ export declare class TestHost implements Transport {
|
|
|
1864
2359
|
* await host.settle(20);
|
|
1865
2360
|
* assert.equal(window.props["status-text"], expected);
|
|
1866
2361
|
* ```
|
|
2362
|
+
*
|
|
2363
|
+
* @capability None.
|
|
2364
|
+
* @throws Never.
|
|
2365
|
+
* @since 1.0.0
|
|
1867
2366
|
*/
|
|
1868
2367
|
settle(ms?: number): Promise<void>;
|
|
1869
2368
|
/**
|
|
1870
2369
|
* Close the fake stream servers and delete the host's temporary
|
|
1871
2370
|
* directories. `stop()` from {@link startPlugin} calls it.
|
|
2371
|
+
*
|
|
2372
|
+
* @capability None.
|
|
2373
|
+
*
|
|
2374
|
+
* @example Clean up a host that was never started
|
|
2375
|
+
* A test that made a host but failed before `startPlugin` removes the
|
|
2376
|
+
* host's temporary directories itself. `stop()` from `startPlugin` calls
|
|
2377
|
+
* `close` for you otherwise.
|
|
2378
|
+
* ```ts
|
|
2379
|
+
* const host = new TestHost();
|
|
2380
|
+
* try {
|
|
2381
|
+
* // … preset the host; the test fails here …
|
|
2382
|
+
* } finally {
|
|
2383
|
+
* host.close(); // deletes the host's temporary data
|
|
2384
|
+
* }
|
|
2385
|
+
* ```
|
|
2386
|
+
*
|
|
2387
|
+
* @since 1.0.0
|
|
1872
2388
|
*/
|
|
1873
2389
|
close(): void;
|
|
1874
2390
|
}
|
|
@@ -1934,6 +2450,16 @@ export declare class TestHost implements Transport {
|
|
|
1934
2450
|
* }
|
|
1935
2451
|
* });
|
|
1936
2452
|
* ```
|
|
2453
|
+
*
|
|
2454
|
+
* @remarks
|
|
2455
|
+
* The way into a plugin's tests: one call starts the plugin the way the
|
|
2456
|
+
* player's runner does and returns the host to drive, the `plugin` object
|
|
2457
|
+
* to call directly, and `stop` to end it like the player.
|
|
2458
|
+
*
|
|
2459
|
+
* @capability None.
|
|
2460
|
+
* @see [Test a plugin](../../docs/how-to/testing.md)
|
|
2461
|
+
* @since 1.0.0
|
|
2462
|
+
* @category Testing
|
|
1937
2463
|
*/
|
|
1938
2464
|
export declare function startPlugin(activate: (plugin: Plugin) => unknown, options?: {
|
|
1939
2465
|
/**
|