@dolphy-app/extension-sdk 0.4.0 → 0.6.0

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/dist/testing.d.ts CHANGED
@@ -1,5 +1,7 @@
1
- import { t as AnswerView } from "./answer-view-D6wnyThb.js";
2
- import { AnswerChangeDetail, AnswerElementProps, CommandOutcome, ExportInput, ExportResult, ExtensionCommands, ExtensionEvents, ExtensionExporters, ExtensionImporters, ExtensionLogger, ExtensionModule, ExtensionNotification, ExtensionNotifications, ExtensionSchedule, ExtensionSecrets, ExtensionSettings, ExtensionStats, ExtensionStorage, GradePolicyInput, GradeResult, GradeValue, ImportInput, ImportResult, ImporterInputKind, JsonSchema, JsonValue, LearningEventName, LearningEventPayloads, LibraryReader, PanelContextInfo, PanelModule, SettingContribution, SettingValue, WidgetModule } from "@dolphy-app/extension-api";
1
+ import { t as ExtensionEngine } from "./index-I_CXC6Lj.js";
2
+ import { a as MountContext$1, i as InjectionRegistration$1, l as ServerEntry$1, o as Mountable, r as ClientEntry, s as PanelRegistration$1, t as AppApi$1 } from "./define-entry-lsuxzKdD.js";
3
+ import { AnswerViewProps, AppLocale, AppTheme, ClientCommandRegistration, CommandOutcome, Disposable, ExportInput, ExportResult, ExtensionHookName, ExtensionLogger, ExtensionNotification, ExtensionNotifications, ExtensionSecrets, ExtensionSettings, ExtensionStats, ExtensionStorage, GradePolicyInput, GradeResult, GradeValue, HookRequest, HookResponse, ImportInput, ImportResult, JsonSchema, JsonValue, LearningEventName, LearningEventPayloads, LibraryReader, MarkdownBlockProps, RpcContract, ServerRegistration, SettingDefinition, SettingValue, ThemeRegistration } from "@dolphy-app/extension-api";
4
+ import { Component } from "vue";
3
5
  //#region packages/extension-sdk/src/testing.d.ts
4
6
  export declare const createMemoryLibrary: (files: Readonly<Record<string, string>>) => LibraryReader;
5
7
  /**
@@ -31,105 +33,15 @@ export interface MemorySettings extends ExtensionSettings {
31
33
  * Unlike the host, a handler failure is not swallowed but rejects the promise.
32
34
  */
33
35
  set(id: string, value: SettingValue): Promise<void>;
36
+ /** Adds definitions, as `server.registerSettings` does; an id registered twice throws. The returned `Disposable` removes them. */
37
+ register(definitions: readonly SettingDefinition[]): Disposable;
34
38
  }
35
- /** In-memory settings from manifest definitions; `initial` provides user values in place of `default`. */
36
- export declare const createMemorySettings: (definitions: readonly SettingContribution[], initial?: Readonly<Record<string, SettingValue>>) => MemorySettings;
37
- export interface MemoryEvents extends ExtensionEvents {
38
- /**
39
- * Sends the event to the subscribed handler and awaits it. With no subscription,
40
- * the event is skipped, as in the host. Unlike the host, a handler failure
41
- * is not swallowed but rejects the promise, and the 2 s handler timeout is not applied.
42
- */
43
- emit<N extends LearningEventName>(name: N, payload: LearningEventPayloads[N]): Promise<void>;
44
- }
45
- export interface MemoryEventsOptions {
46
- /** Events from `contributes.events`: subscribing to another throws, as in the host. Unset — any are allowed. */
47
- declared?: readonly LearningEventName[];
48
- /** false — subscribing throws `PermissionError`, as for an extension without `learning.events`. Defaults to true. */
49
- permitted?: boolean;
50
- }
51
- /** In-memory learning event subscriptions: one handler per event, as in the host. */
52
- export declare const createMemoryEvents: (options?: MemoryEventsOptions) => MemoryEvents;
53
- export interface MemoryCommands extends ExtensionCommands {
54
- /**
55
- * Runs a registered command the way the host does: the same
56
- * argument and result bounds, the same result normalization. An unregistered
57
- * command and an invalid result reject the promise. The 10 s handler timeout is not applied.
58
- */
59
- run(id: string, args?: JsonValue): Promise<CommandOutcome>;
60
- /** Registered commands in registration order. */
61
- ids(): string[];
62
- }
63
- export interface MemoryCommandsOptions {
64
- /** Commands from `contributes.commands`: registering another throws, as in the host. Unset — any are allowed. */
65
- declaredCommands?: readonly string[];
66
- /** Panels from `contributes.panels`: `openPanel` on another is invalid, as in the host. Unset — any. */
67
- declaredPanels?: readonly string[];
68
- }
69
- /** In-memory commands: the same registration rules and result parsing as the host. */
70
- export declare const createMemoryCommands: (options?: MemoryCommandsOptions) => MemoryCommands;
71
- export interface MemorySchedule extends ExtensionSchedule {
72
- /**
73
- * Fires a schedule the way the host does and awaits the handler: resolves
74
- * `true` once the handler returned. With no subscription, or while the
75
- * handler of the previous firing is still running, the firing is skipped and
76
- * resolves `false`. Unlike the host, a handler failure is not swallowed but
77
- * rejects the promise, and the 10 s handler timeout is not applied.
78
- */
79
- fire(id: string): Promise<boolean>;
80
- /** Subscribed schedules in subscription order. */
81
- ids(): string[];
82
- }
83
- export interface MemoryScheduleOptions {
84
- /** Schedules from `contributes.schedules`: subscribing to another throws, as in the host. Unset — any are allowed. */
85
- declared?: readonly string[];
86
- }
87
- /** In-memory schedule subscriptions: one handler per schedule and no overlapping firings, as in the host. */
88
- export declare const createMemorySchedule: (options?: MemoryScheduleOptions) => MemorySchedule;
89
- export interface MemoryImporters extends ExtensionImporters {
90
- /**
91
- * Runs a registered importer the way the host does: the input must have the
92
- * form the importer declares (`text` unless `input: 'bytes'`) and at most
93
- * `EXTENSION_TRANSFER_LIMITS.inputBytes`; the result goes through the host's
94
- * rules (`normalizeImportResult`: paths, sizes, number of files). An
95
- * unregistered importer and an invalid result reject the promise. The 30 s
96
- * handler timeout is not applied.
97
- */
98
- run(id: string, input: ImportInput): Promise<ImportResult>;
99
- /** Registered importers in registration order. */
100
- ids(): string[];
101
- }
102
- export interface MemoryImportersOptions {
103
- /** Importers from `contributes.importers`: registering another throws and `input` is checked, as in the host. Unset — any are allowed. */
104
- declaredImporters?: readonly {
105
- id: string;
106
- input?: ImporterInputKind;
107
- }[];
108
- }
109
- /** In-memory importers: the same registration rules and result checks as the host. */
110
- export declare const createMemoryImporters: (options?: MemoryImportersOptions) => MemoryImporters;
111
- export interface MemoryExporters extends ExtensionExporters {
112
- /**
113
- * Runs a registered exporter the way the host does: the input must match the
114
- * exporter's declared `scope` and a course snapshot is at most
115
- * `EXTENSION_TRANSFER_LIMITS.totalBytes`; the result goes through the host's
116
- * rules (`normalizeExportResult`: file name, size, `text` xor `bytes`). An
117
- * unregistered exporter and an invalid result reject the promise. The 30 s
118
- * handler timeout is not applied.
119
- */
120
- run(id: string, input: ExportInput): Promise<ExportResult>;
121
- /** Registered exporters in registration order. */
122
- ids(): string[];
123
- }
124
- export interface MemoryExportersOptions {
125
- /** Exporters from `contributes.exporters`: registering another throws and `scope` is checked, as in the host. Unset — any are allowed. */
126
- declaredExporters?: readonly {
127
- id: string;
128
- scope: ExportInput['scope'];
129
- }[];
130
- }
131
- /** In-memory exporters: the same registration rules and result checks as the host. */
132
- export declare const createMemoryExporters: (options?: MemoryExportersOptions) => MemoryExporters;
39
+ /**
40
+ * In-memory settings. `definitions` are registered at once, more come through
41
+ * `register`; `initial` provides user values in place of `default`, applied
42
+ * when the setting with that id is registered.
43
+ */
44
+ export declare const createMemorySettings: (definitions?: readonly SettingDefinition[], initial?: Readonly<Record<string, SettingValue>>) => MemorySettings;
133
45
  export interface MemoryStatsAttempt {
134
46
  /** When the attempt happened: epoch milliseconds, a `Date`, or an ISO-8601 string. */
135
47
  at: number | Date | string;
@@ -145,8 +57,6 @@ export interface MemoryStatsOptions {
145
57
  timeZone?: string;
146
58
  /** The current time, for the `current` streak. Defaults to `Date.now`. */
147
59
  now?: () => number;
148
- /** false — every call rejects with `PermissionError('learning.stats')`, as for an extension without the permission. Defaults to true. */
149
- permitted?: boolean;
150
60
  }
151
61
  export interface MemoryStats extends ExtensionStats {
152
62
  /** Adds an attempt to the history. */
@@ -159,8 +69,6 @@ export interface MemoryStats extends ExtensionStats {
159
69
  */
160
70
  export declare const createMemoryStats: (options?: MemoryStatsOptions) => MemoryStats;
161
71
  export interface MemoryNotificationsOptions {
162
- /** false — every call rejects with `PermissionError('notifications')`, as for an extension without the permission. Defaults to true. */
163
- permitted?: boolean;
164
72
  /** false — the operating system does not support notifications: `show` resolves `false`. Defaults to true. */
165
73
  supported?: boolean;
166
74
  /** false — the user switched notifications off for the extension: `show` resolves `false`. Defaults to true. */
@@ -184,23 +92,23 @@ export interface MemoryNotifications extends ExtensionNotifications {
184
92
  * would keep.
185
93
  */
186
94
  export declare const createMemoryNotifications: (options?: MemoryNotificationsOptions) => MemoryNotifications;
187
- /** What a test replaces in the extension context; by default everything is in memory and silent. */
188
- export interface LoadOptions {
95
+ export declare const createSchemaValidator: (schema: JsonSchema) => (value: unknown) => string[];
96
+ /** What a test replaces in the context of the server part; by default everything is in memory and silent. */
97
+ export interface TestServerOptions {
98
+ /** Default `test`. When set, every registered id must be equal to it or start with `<extensionId>.`, as the host checks. */
99
+ extensionId?: string;
189
100
  library?: LibraryReader;
190
101
  logger?: ExtensionLogger;
191
102
  storage?: ExtensionStorage;
192
- secrets?: ExtensionSecrets;
193
- settings?: ExtensionSettings;
194
- events?: ExtensionEvents;
195
- commands?: ExtensionCommands;
196
- importers?: ExtensionImporters;
197
- exporters?: ExtensionExporters;
198
- stats?: ExtensionStats;
199
- notifications?: ExtensionNotifications;
200
- schedule?: ExtensionSchedule;
103
+ secrets?: MemorySecrets;
104
+ stats?: MemoryStats;
105
+ notifications?: MemoryNotifications;
106
+ /** User values of settings in place of `default`, by setting id; every id must be registered by the entry. */
107
+ settingValues?: Readonly<Record<string, SettingValue>>;
108
+ /** The engine `ctx.engine` gives to the entry; by default every use of it throws, as the test server has no engine. */
109
+ engine?: ExtensionEngine;
201
110
  }
202
- export declare const createSchemaValidator: (schema: JsonSchema) => (value: unknown) => string[];
203
- export interface LoadedExerciseType {
111
+ export interface TestExerciseType {
204
112
  project(spec: unknown, options?: {
205
113
  exerciseId?: string;
206
114
  }): Promise<unknown>;
@@ -219,141 +127,176 @@ export interface LoadedExerciseType {
219
127
  } | {
220
128
  found: false;
221
129
  }>;
222
- /** Deactivates the extension module. */
223
- dispose(): Promise<void>;
224
130
  }
225
- export declare const loadExerciseType: (module: ExtensionModule, type: string, options?: LoadOptions) => Promise<LoadedExerciseType>;
226
- export interface LoadedGradePolicy {
131
+ export interface TestGradePolicy {
227
132
  evaluate(input: GradePolicyInput): Promise<GradeValue | null>;
228
- /** Deactivates the extension module. */
229
- dispose(): Promise<void>;
230
133
  }
231
- export declare const loadGradePolicy: (module: ExtensionModule, id: string, options?: LoadOptions) => Promise<LoadedGradePolicy>;
232
- export interface LoadedEvents {
233
- /** Events are delivered as in the host: to the subscribed handler, one at a time. See `MemoryEvents.emit`. */
234
- emit: MemoryEvents['emit'];
235
- storage: ExtensionStorage;
236
- secrets: ExtensionSecrets;
237
- settings: MemorySettings;
238
- /** Deactivates the extension module. */
239
- dispose(): Promise<void>;
134
+ export interface TestImporter {
135
+ /**
136
+ * Runs the importer the way the host does: the input must have the form the
137
+ * importer declares and at most `EXTENSION_TRANSFER_LIMITS.inputBytes`; the
138
+ * result goes through `normalizeImportResult`. An invalid result rejects the
139
+ * promise. The handler timeout is not applied.
140
+ */
141
+ run(input: ImportInput): Promise<ImportResult>;
240
142
  }
241
- export interface LoadEventsOptions extends Omit<LoadOptions, 'storage' | 'secrets' | 'settings' | 'events'>, MemoryEventsOptions {
242
- storage?: ExtensionStorage;
243
- secrets?: ExtensionSecrets;
244
- /** Definitions from the manifest's `contributes.settings`; values are read and changed through `settings`. */
245
- settings?: readonly SettingContribution[];
246
- /** User values in place of `default`. */
247
- settingValues?: Readonly<Record<string, SettingValue>>;
143
+ export interface TestExporter {
144
+ /**
145
+ * Runs the exporter the way the host does: the input must match the
146
+ * exporter's `scope` and a course snapshot is at most
147
+ * `EXTENSION_TRANSFER_LIMITS.totalBytes`; the result goes through
148
+ * `normalizeExportResult`. An invalid result rejects the promise. The handler
149
+ * timeout is not applied.
150
+ */
151
+ run(input: ExportInput): Promise<ExportResult>;
152
+ }
153
+ /** The server part of an extension, started on in-memory fakes. */
154
+ export interface TestServer {
155
+ readonly extensionId: string;
156
+ /** What the entry registered, as the host's registrar hands it to the engine (checked for types and unique ids only: the host checks the rest). */
157
+ readonly registration: ServerRegistration;
158
+ readonly library: LibraryReader;
159
+ readonly storage: ExtensionStorage;
160
+ readonly secrets: MemorySecrets;
161
+ readonly settings: MemorySettings;
162
+ readonly stats: MemoryStats;
163
+ readonly notifications: MemoryNotifications;
164
+ /** The engine of the context: `options.engine`. */
165
+ readonly engine: ExtensionEngine;
166
+ readonly commands: {
167
+ /**
168
+ * Runs a registered command the way the host does: the same argument and
169
+ * result bounds, the same result normalization. An unregistered command
170
+ * and an invalid result reject the promise. The handler timeout is not applied.
171
+ */
172
+ run(id: string, args?: JsonValue): Promise<CommandOutcome>;
173
+ };
174
+ readonly events: {
175
+ /**
176
+ * Sends the event to the subscribed handler and awaits it. With no
177
+ * subscription the event is skipped, as in the host. Unlike the host, a
178
+ * handler failure is not swallowed but rejects the promise, and the
179
+ * handler timeout is not applied.
180
+ */
181
+ emit<N extends LearningEventName>(name: N, payload: LearningEventPayloads[N]): Promise<void>;
182
+ };
183
+ /**
184
+ * Calls the handler registered with `server.before` the way the host does:
185
+ * the request must pass `EXTENSION_HOOKS[name].request` and the response
186
+ * `EXTENSION_HOOKS[name].response`. An unregistered hook, a schema
187
+ * violation and an error of the handler reject the promise. The handler
188
+ * timeout is not applied, and no other extension's handlers run.
189
+ */
190
+ hook<N extends ExtensionHookName>(name: N, request: HookRequest<N>): Promise<HookResponse<N>>;
191
+ readonly schedule: {
192
+ /**
193
+ * Fires a registered schedule the way the host does and awaits the
194
+ * handler: resolves `true` once the handler returned, `false` while the
195
+ * handler of the previous firing is still running. An unregistered
196
+ * schedule rejects the promise. Unlike the host, a handler failure is not
197
+ * swallowed but rejects the promise.
198
+ */
199
+ fire(id: string): Promise<boolean>;
200
+ };
201
+ exerciseType(id: string): TestExerciseType;
202
+ gradePolicy(id: string): TestGradePolicy;
203
+ importer(id: string): TestImporter;
204
+ exporter(id: string): TestExporter;
205
+ /**
206
+ * Calls the handler registered with `server.handle` under `contract.name`
207
+ * the way the host does: the input must serialize to at most
208
+ * `EXTENSION_RPC_LIMITS.inputChars` characters and pass the input schema
209
+ * the handler registered; the result must pass the output schema. An
210
+ * unregistered contract, a schema violation and an error of the handler
211
+ * reject the promise. The handler timeout is not applied.
212
+ */
213
+ rpc<Input, Output>(contract: RpcContract<Input, Output>, input: Input): Promise<Output>;
214
+ /** Runs the cleanup the entry returned and removes the registrations. */
215
+ dispose(): Promise<void>;
248
216
  }
249
217
  /**
250
- * Activates the module with in-memory storage, settings, and events, and lets the test
251
- * send events and change settings.
218
+ * Starts `entry` (the `server` export of an extension) with in-memory
219
+ * storage, secrets, settings, statistics, notifications and library, and
220
+ * returns a harness to call what it registered. Registration is all or
221
+ * nothing, as in the host: when `entry` throws, so does `createTestServer`.
252
222
  */
253
- export declare const loadEvents: (module: ExtensionModule, options?: LoadEventsOptions) => Promise<LoadedEvents>;
254
- export interface LoadedCommands {
255
- run: MemoryCommands['run'];
256
- ids: MemoryCommands['ids'];
257
- /** Deactivates the extension module. */
223
+ export declare const createTestServer: (entry: ServerEntry$1, options?: TestServerOptions) => Promise<TestServer>;
224
+ /** An answer view as registered: a Vue component or a `Mountable`. */
225
+ export type AnswerViewComponent = Component | Mountable<AnswerViewProps>;
226
+ /** A markdown renderer as registered: a Vue component or a `Mountable`. */
227
+ export type MarkdownRendererComponent = Component | Mountable<MarkdownBlockProps>;
228
+ /** The client part of an extension, started on a recording context. */
229
+ export interface TestClient {
230
+ readonly extensionId: string;
231
+ readonly panels: readonly PanelRegistration$1[];
232
+ /** Injections as registered, with `position` defaulted to `append`. */
233
+ readonly injections: readonly Required<InjectionRegistration$1>[];
234
+ /** Answer views by exercise type id, as registered (a Vue component or a `Mountable`). */
235
+ readonly answerViews: ReadonlyMap<string, AnswerViewComponent>;
236
+ /** Markdown renderers by block language, as registered (a Vue component or a `Mountable`). */
237
+ readonly markdownRenderers: ReadonlyMap<string, MarkdownRendererComponent>;
238
+ readonly themes: readonly ThemeRegistration[];
239
+ readonly commands: readonly ClientCommandRegistration[];
240
+ /** Runs the cleanup the entry returned and removes the registrations. */
258
241
  dispose(): Promise<void>;
259
242
  }
260
- export interface LoadCommandsOptions extends Omit<LoadOptions, 'commands'>, MemoryCommandsOptions {}
261
- /** Activates the module with in-memory commands and lets the test invoke them like the host. */
262
- export declare const loadCommands: (module: ExtensionModule, options?: LoadCommandsOptions) => Promise<LoadedCommands>;
263
- export interface LoadedImporters {
264
- run: MemoryImporters['run'];
265
- ids: MemoryImporters['ids'];
266
- /** Deactivates the extension module. */
267
- dispose(): Promise<void>;
268
- }
269
- export interface LoadImportersOptions extends Omit<LoadOptions, 'importers'>, MemoryImportersOptions {}
270
- /** Activates the module with in-memory importers and lets the test run them like the host. */
271
- export declare const loadImporters: (module: ExtensionModule, options?: LoadImportersOptions) => Promise<LoadedImporters>;
272
- export interface LoadedExporters {
273
- run: MemoryExporters['run'];
274
- ids: MemoryExporters['ids'];
275
- /** Deactivates the extension module. */
276
- dispose(): Promise<void>;
277
- }
278
- export interface LoadExportersOptions extends Omit<LoadOptions, 'exporters'>, MemoryExportersOptions {}
279
- /** Activates the module with in-memory exporters and lets the test run them like the host; `stats` feeds `ctx.stats` of a progress exporter. */
280
- export declare const loadExporters: (module: ExtensionModule, options?: LoadExportersOptions) => Promise<LoadedExporters>;
281
- export interface LoadedSchedules {
282
- fire: MemorySchedule['fire'];
283
- ids: MemorySchedule['ids'];
284
- /** Deactivates the extension module. */
285
- dispose(): Promise<void>;
286
- }
287
- export interface LoadSchedulesOptions extends Omit<LoadOptions, 'schedule'>, MemoryScheduleOptions {}
288
- /** Activates the module with in-memory schedules and lets the test fire them like the host. */
289
- export declare const loadSchedules: (module: ExtensionModule, options?: LoadSchedulesOptions) => Promise<LoadedSchedules>;
290
- export interface LoadViewOptions extends Partial<AnswerElementProps> {
291
- /** `aria-label` of the host element, as the app sets it. */
292
- label?: string;
293
- /** Where to mount; defaults to a new `div` in `document.body`. */
294
- container?: HTMLElement;
295
- }
296
- export interface LoadedView {
297
- /** The kind's custom element, as the app creates it. */
298
- readonly element: HTMLElement;
299
- /** The element's shadow root: the view renders its UI here. */
300
- readonly root: ShadowRoot;
301
- /** `dolphy-answer-change` events in order. */
302
- readonly changes: readonly AnswerChangeDetail[];
303
- /** How many times the view asked to submit the answer (`dolphy-answer-submit`). */
304
- readonly submissions: number;
305
- /** Sets element properties and waits for the view to apply the update. */
306
- update(props: Partial<AnswerElementProps>): Promise<void>;
307
- query<E extends Element = Element>(selector: string): E | null;
308
- queryAll<E extends Element = Element>(selector: string): E[];
309
- /** Removes the element from the document; the view receives `destroy()`. */
310
- dispose(): void;
243
+ export interface TestClientOptions {
244
+ /** Default `test`. When set, every registered id must be equal to it or start with `<extensionId>.`, as the window checks. */
245
+ extensionId?: string;
246
+ /** The window API `client.app` gives to the entry; by default every use of it throws, as the test client has no window. */
247
+ app?: AppApi$1;
248
+ /** The engine `client.engine` gives to the entry; by default every use of it throws. */
249
+ engine?: ExtensionEngine;
311
250
  }
312
251
  /**
313
- * Mounts a view from `views[id]` in the test DOM environment with the same element
314
- * the app creates (test tags are issued; the manifest `element` is not needed).
252
+ * Starts `entry` (the `client` export of an extension) on a context that
253
+ * records what it adds, so a test can mount the components and read the
254
+ * themes and commands. An id added twice and an injection with a bad target
255
+ * or position fail like in the window.
315
256
  */
316
- export declare const loadView: (views: Readonly<Record<string, AnswerView>>, id: string, options?: LoadViewOptions) => Promise<LoadedView>;
317
- export interface LoadPanelOptions {
318
- /** Properties the panel was opened with (`openPanel(id, props)`). */
319
- props?: JsonValue;
320
- /** Reply to `ctx.call`; by default the call is rejected. */
321
- call?: (commandId: string, args: JsonValue | undefined) => JsonValue | undefined | Promise<JsonValue | undefined>;
322
- /** The surroundings the frame starts with (`ctx.context`); defaults to all courses (`courseId: null`). */
323
- context?: PanelContextInfo;
324
- /** Where to mount; defaults to a new `div` in `document.body`. */
325
- container?: HTMLElement;
326
- }
327
- export interface LoadWidgetOptions {
328
- /** Reply to `ctx.call`; by default the call is rejected. */
329
- call?: LoadPanelOptions['call'];
330
- /** The surroundings the frame starts with (`ctx.context`); defaults to all courses (`courseId: null`). */
331
- context?: PanelContextInfo;
332
- /** Where to mount; defaults to a new `div` in `document.body`. */
333
- container?: HTMLElement;
334
- }
335
- export interface LoadedFrame {
336
- /** Container the module received in `mount`. */
337
- readonly container: HTMLElement;
338
- /** `ctx.call` invocations in order. */
339
- readonly calls: readonly {
340
- commandId: string;
341
- args: JsonValue | undefined;
342
- }[];
343
- /** Whether `ctx.signal` was aborted (after `dispose()`). */
344
- readonly aborted: boolean;
345
- /** The app focused another course: updates `ctx.context` and notifies `ctx.onContextChange` subscribers. */
346
- setContext(context: PanelContextInfo): void;
347
- /** Closes the frame: aborts `ctx.signal` and removes the container. */
348
- dispose(): void;
257
+ export declare const createTestClient: (entry: ClientEntry, options?: TestClientOptions) => Promise<TestClient>;
258
+ /** What `mountForTest` gives `ctx`; everything is optional except `props`. */
259
+ export interface MountForTestOptions<Props, Handle = undefined> {
260
+ /** The first `ctx.props`. */
261
+ props: Props;
262
+ /** The element to draw into; by default a new `<div>` of the global `document`. Required without a DOM. */
263
+ el?: HTMLElement;
264
+ /** `ctx.handle`: a panel or injection handle; `undefined` by default. */
265
+ handle?: Handle;
266
+ /** `ctx.app`; by default every use of it throws, as the test has no window. */
267
+ app?: AppApi$1;
268
+ /** `ctx.engine`, the engine of `ctx.callRpc`; by default every use of it throws. */
269
+ engine?: ExtensionEngine;
270
+ /** Default `{ id: 'light', dark: false }`. */
271
+ theme?: AppTheme;
272
+ /** Default `en`. */
273
+ locale?: AppLocale;
274
+ /** Default `test`. */
275
+ extensionId?: string;
276
+ }
277
+ /** A `Mountable` mounted by `mountForTest`. */
278
+ export interface MountedForTest<Props, Handle = undefined> {
279
+ readonly el: HTMLElement;
280
+ /** The context the `Mountable` got. */
281
+ readonly ctx: MountContext$1<Props, Handle>;
282
+ /** Replaces `ctx.props` and calls the `onProps` listeners. */
283
+ setProps(next: Props): void;
284
+ /** Replaces `ctx.theme` and calls the `onTheme` listeners. */
285
+ setTheme(next: AppTheme): void;
286
+ /** Replaces `ctx.locale` and calls the `onLocale` listeners. */
287
+ setLocale(next: AppLocale): void;
288
+ /** Every `ctx.emit` call, in order: `[event, payload]`. */
289
+ readonly emitted: readonly (readonly [string, unknown])[];
290
+ /** Every `ctx.reportError` call, in order. */
291
+ readonly errors: readonly unknown[];
292
+ /** Aborts `ctx.signal` and runs the cleanup `mount` returned, once. */
293
+ unmount(): Promise<void>;
349
294
  }
350
- export interface LoadedPanel extends LoadedFrame {
351
- /** Sends new properties to the panel (`ctx.onProps`). */
352
- setProps(props: JsonValue | undefined): void;
353
- }
354
- export type LoadedWidget = LoadedFrame;
355
- /** Mounts a panel from `panels[id]` in the test DOM environment with the same context the frame provides. */
356
- export declare const loadPanel: (panels: Readonly<Record<string, PanelModule<HTMLElement>>>, id: string, options?: LoadPanelOptions) => Promise<LoadedPanel>;
357
- /** Mounts a widget from `widgets[id]` in the test DOM environment with the same context the frame provides. */
358
- export declare const loadWidget: (widgets: Readonly<Record<string, WidgetModule<HTMLElement>>>, id: string, options?: LoadWidgetOptions) => Promise<LoadedWidget>;
295
+ /**
296
+ * Mounts a `Mountable` into an element on a recording context, so a test can
297
+ * change the props, the theme and the language, read what the component
298
+ * emitted and reported, and unmount it. Rejects with what `mount` throws. Needs
299
+ * a DOM (`document`) or `options.el`.
300
+ */
301
+ export declare const mountForTest: <Props, Handle = undefined>(mountable: Mountable<Props, Handle>, options: MountForTestOptions<Props, Handle>) => Promise<MountedForTest<Props, Handle>>;
359
302
  //#endregion