@mosaicast/plugin-sdk 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +323 -4
- package/dist/index.d.ts +825 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +341 -1
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +168 -10
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +381 -14
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/testing.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
|
-
import type { BlobClient, BlobInfo, ConsentApi, LogLevel, PluginApiClient, PluginContext, PluginRoute, SchemaClient, SchemaQuery, ThemeTokens } from './index.js';
|
|
9
|
+
import type { BlobClient, BlobInfo, ConsentApi, DisplaySnapshot, DocClient, FeedsClient, LogLevel, PluginApiClient, PluginContext, PluginRoute, ProblemDetail, SchemaClient, SchemaQuery, TagsClient, ThemeTokens } from './index.js';
|
|
10
10
|
/** One recorded {@link PluginContext.log} call. */
|
|
11
11
|
export interface LogRecord {
|
|
12
12
|
/** The severity it was logged at. */
|
|
@@ -45,6 +45,33 @@ export interface RecordedCall {
|
|
|
45
45
|
/** The request body, if any. */
|
|
46
46
|
body?: unknown;
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* A canned failure: what the host would have answered instead of a body.
|
|
50
|
+
*
|
|
51
|
+
* Put one in {@link MockApiClient.responses} and the call rejects with a {@link PluginApiError} carrying
|
|
52
|
+
* that status — which is how a component's 404 branch and its 500 branch become separately testable.
|
|
53
|
+
*
|
|
54
|
+
* ```ts
|
|
55
|
+
* const ctx = makeMockCtx({ apiResponses: { 'get data/site/main/stats': apiError(403, {
|
|
56
|
+
* detail: 'this key is written by the plugin backend',
|
|
57
|
+
* }) } });
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @param status the HTTP status to fail with
|
|
61
|
+
* @param problem the RFC 7807 body, if the test cares about it
|
|
62
|
+
* @returns a marker the mock client turns into a rejection
|
|
63
|
+
* @since 0.9.0
|
|
64
|
+
*/
|
|
65
|
+
export declare function apiError(status: number, problem?: ProblemDetail): CannedApiError;
|
|
66
|
+
/** The marker {@link apiError} produces. Recognised by {@link MockApiClient}; not a real error. */
|
|
67
|
+
export interface CannedApiError {
|
|
68
|
+
/** Discriminator, so an ordinary response object is never mistaken for a failure. */
|
|
69
|
+
__mosaicastApiError: true;
|
|
70
|
+
/** The status to reject with. */
|
|
71
|
+
status: number;
|
|
72
|
+
/** The problem body to attach. */
|
|
73
|
+
problem?: ProblemDetail;
|
|
74
|
+
}
|
|
48
75
|
/** A {@link PluginApiClient} that records calls and returns canned responses. */
|
|
49
76
|
export interface MockApiClient extends PluginApiClient {
|
|
50
77
|
/** Every call made through this client, in order. */
|
|
@@ -52,9 +79,43 @@ export interface MockApiClient extends PluginApiClient {
|
|
|
52
79
|
/**
|
|
53
80
|
* Canned responses keyed by `"<method> <path>"` (e.g. `"get /board"`) or bare `path`; the more
|
|
54
81
|
* specific key wins. Missing keys resolve to `undefined`.
|
|
82
|
+
*
|
|
83
|
+
* A value built by {@link apiError} **rejects** with a {@link PluginApiError} instead of resolving.
|
|
55
84
|
*/
|
|
56
85
|
responses: Record<string, unknown>;
|
|
86
|
+
/**
|
|
87
|
+
* Resolves once every call made so far has settled.
|
|
88
|
+
*
|
|
89
|
+
* A component typically does `ctx.api.get(...).then(setState)`, sometimes with another `.then` behind
|
|
90
|
+
* it, so the mock's already-resolved promise still needs one microtask hop per `.then` before the DOM
|
|
91
|
+
* reflects it. A single `await Promise.resolve()` covers one hop and not two — which is why the
|
|
92
|
+
* symptom is **an assertion that fails only sometimes**, depending on how many hops the component
|
|
93
|
+
* happens to have. This waits for the calls themselves rather than for a guessed number of hops.
|
|
94
|
+
*
|
|
95
|
+
* Prefer {@link flushMockApi}, which also drains the hops the component adds after the call settles.
|
|
96
|
+
*
|
|
97
|
+
* @since 0.9.0
|
|
98
|
+
*/
|
|
99
|
+
settled(): Promise<void>;
|
|
57
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Waits until every call recorded by a mock client has settled *and* the `.then` chains behind them have
|
|
103
|
+
* run.
|
|
104
|
+
*
|
|
105
|
+
* The two-part wait is the point: `await client.settled()` knows when the *requests* finished, and the
|
|
106
|
+
* microtask drain after it lets the component's own `.then(setState)` hops reach the DOM. Use it instead
|
|
107
|
+
* of counting `await Promise.resolve()` calls by hand.
|
|
108
|
+
*
|
|
109
|
+
* ```ts
|
|
110
|
+
* mount(ctx);
|
|
111
|
+
* await flushMockApi(ctx.api);
|
|
112
|
+
* expect(root.querySelector('.title')).toHaveTextContent('The Kraken');
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @param client the mock client — `ctx.api` from {@link makeMockCtx}
|
|
116
|
+
* @since 0.9.0
|
|
117
|
+
*/
|
|
118
|
+
export declare function flushMockApi(client: MockApiClient): Promise<void>;
|
|
58
119
|
/** A {@link ConsentApi} whose grants a test can drive. */
|
|
59
120
|
export interface MockConsent extends ConsentApi {
|
|
60
121
|
/** Grants a category and notifies subscribers. Granting an already-granted category does nothing. */
|
|
@@ -139,6 +200,100 @@ export interface MockSchemaClient extends SchemaClient {
|
|
|
139
200
|
* ```
|
|
140
201
|
*/
|
|
141
202
|
export declare function makeMockSchema(rows?: Record<string, Record<string, unknown>[]>): MockSchemaClient;
|
|
203
|
+
/** A {@link FeedsClient} answering from registered snapshots. @since 0.9.0 */
|
|
204
|
+
export interface MockFeedsClient extends FeedsClient {
|
|
205
|
+
/**
|
|
206
|
+
* Registers the snapshot `display`/`displayMany` return for a slug.
|
|
207
|
+
*
|
|
208
|
+
* Mirrors the Java kit's `FakeFeedAccess.withDisplay(...)`, so both halves of a plugin describe the
|
|
209
|
+
* host's answer the same way.
|
|
210
|
+
*
|
|
211
|
+
* @param slug the episode's public slug
|
|
212
|
+
* @param snapshot what the host would hand over
|
|
213
|
+
* @returns this client, for chaining
|
|
214
|
+
*/
|
|
215
|
+
withDisplay(slug: string, snapshot: DisplaySnapshot): MockFeedsClient;
|
|
216
|
+
/** Every slug asked for, in order — batched calls contribute each slug separately. */
|
|
217
|
+
readonly requested: string[];
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* A {@link FeedsClient} double: snapshots you register, and **nothing for the ones you don't**.
|
|
221
|
+
*
|
|
222
|
+
* An unregistered slug resolves `null` (or is absent from a batch) rather than throwing, because that is
|
|
223
|
+
* what the host does for an episode this visitor may not see — a `WITHDRAWN` or tier-gated one is absent,
|
|
224
|
+
* not redacted. So the empty case a component must handle is the double's default, and a component that
|
|
225
|
+
* assumes every slug comes back fails here rather than in front of a visitor.
|
|
226
|
+
*
|
|
227
|
+
* ```ts
|
|
228
|
+
* const feeds = makeMockFeeds().withDisplay('kraken', { title: 'The Kraken', description: '' });
|
|
229
|
+
* const ctx = makeMockCtx({ feeds, episodes: ['kraken', 'gated'] });
|
|
230
|
+
*
|
|
231
|
+
* await mount(ctx);
|
|
232
|
+
* expect(root.textContent).toContain('The Kraken'); // and renders nothing for `gated`
|
|
233
|
+
* ```
|
|
234
|
+
*
|
|
235
|
+
* @param snapshots snapshots to start with, keyed by slug
|
|
236
|
+
* @returns a feeds double with `withDisplay` and a recorded `requested` list
|
|
237
|
+
* @since 0.9.0
|
|
238
|
+
*/
|
|
239
|
+
export declare function makeMockFeeds(snapshots?: Record<string, DisplaySnapshot>): MockFeedsClient;
|
|
240
|
+
/** A {@link TagsClient} backed by an in-memory vocabulary. @since 0.9.0 */
|
|
241
|
+
export interface MockTagsClient extends TagsClient {
|
|
242
|
+
/** Seeds a tag the **feed** put on an episode — a row the plugin may read but must not remove. */
|
|
243
|
+
withFeedTag(episodeSlug: string, tag: string): MockTagsClient;
|
|
244
|
+
/** The canonical keys currently on each episode, for asserting without going through the client. */
|
|
245
|
+
readonly episodeTags: Record<string, string[]>;
|
|
246
|
+
/** The canonical keys currently on each of this plugin's subjects. */
|
|
247
|
+
readonly subjectTags: Record<string, string[]>;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* A {@link TagsClient} double that **refuses what the host refuses**.
|
|
251
|
+
*
|
|
252
|
+
* Two refusals matter, and both are invisible to a component tested against a permissive double:
|
|
253
|
+
*
|
|
254
|
+
* - **Episode writes throw** unless you pass `writesEpisodes: true`, standing in for the manifest
|
|
255
|
+
* declaration. Off by default, so the branch where the host says no gets exercised.
|
|
256
|
+
* - **`untagEpisode` removes only this plugin's own assignment.** Seed the feed's side with
|
|
257
|
+
* {@link MockTagsClient.withFeedTag} and the tag survives your removal, exactly as the host's `source`
|
|
258
|
+
* column makes it survive.
|
|
259
|
+
*
|
|
260
|
+
* Canonicalisation is applied as the host applies it, so a test that writes `'Maritime '` and reads
|
|
261
|
+
* `'maritime'` passes here for the same reason it passes against core.
|
|
262
|
+
*
|
|
263
|
+
* @param opts `writesEpisodes` grants the episode-write capability; `subjects` and `episodes` seed
|
|
264
|
+
* assignments this plugin owns
|
|
265
|
+
* @returns a tags double
|
|
266
|
+
* @since 0.9.0
|
|
267
|
+
*/
|
|
268
|
+
export declare function makeMockTags(opts?: {
|
|
269
|
+
writesEpisodes?: boolean;
|
|
270
|
+
subjects?: Record<string, string[]>;
|
|
271
|
+
episodes?: Record<string, string[]>;
|
|
272
|
+
}): MockTagsClient;
|
|
273
|
+
/** A {@link DocClient} storing in memory, keyed by resolved partition path. @since 0.9.0 */
|
|
274
|
+
export interface MockDocClient extends DocClient {
|
|
275
|
+
/** What is currently stored, keyed `"<partition>/<key>"` — e.g. `"data/user/me/marks"`. */
|
|
276
|
+
readonly stored: Record<string, unknown>;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* A {@link DocClient} double: an in-memory store that **validates keys the way the client does**.
|
|
280
|
+
*
|
|
281
|
+
* A key with a `/` in it, or one over 200 characters, throws here rather than silently working — which
|
|
282
|
+
* matters, because against a permissive double the failure would first appear as a 400 in production.
|
|
283
|
+
*
|
|
284
|
+
* ```ts
|
|
285
|
+
* const docs = makeMockDocs({ 'data/user/me/marks': { b3: true } });
|
|
286
|
+
* const ctx = makeMockCtx({ docs });
|
|
287
|
+
*
|
|
288
|
+
* await mount(ctx);
|
|
289
|
+
* expect(docs.stored['data/user/me/marks']).toEqual({ b3: true, b4: true });
|
|
290
|
+
* ```
|
|
291
|
+
*
|
|
292
|
+
* @param initial documents to start with, keyed `"<partition>/<key>"`
|
|
293
|
+
* @returns a doc client double with an inspectable `stored` map
|
|
294
|
+
* @since 0.9.0
|
|
295
|
+
*/
|
|
296
|
+
export declare function makeMockDocs(initial?: Record<string, unknown>): MockDocClient;
|
|
142
297
|
/** Default theme tokens (neutral light values) used when a test does not override them. */
|
|
143
298
|
export declare const DEFAULT_THEME: ThemeTokens;
|
|
144
299
|
/** One recorded {@link BlobClient.upload} call. @since 0.8.0 */
|
|
@@ -234,15 +389,18 @@ export interface MockCtxOverrides extends Partial<Omit<PluginContext, 'api' | 'r
|
|
|
234
389
|
*
|
|
235
390
|
* Defaults: `site` scope, no episodes, anonymous user, **all consent denied** (a {@link makeMockConsent}
|
|
236
391
|
* double — pass your own to drive grants), empty filter, a player
|
|
237
|
-
* parked at 0s, empty route, `en` locale, unknown progress, and
|
|
238
|
-
* change any field; the returned `api` is a
|
|
239
|
-
* collects every `ctx.log(...)`.
|
|
240
|
-
*
|
|
241
|
-
* `
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
392
|
+
* parked at 0s, empty route with an empty query and hash, `en` locale, unknown progress, and
|
|
393
|
+
* {@link DEFAULT_THEME}. Pass overrides to change any field; the returned `api` is a
|
|
394
|
+
* {@link MockApiClient} recording every call, and `logs` collects every `ctx.log(...)`.
|
|
395
|
+
*
|
|
396
|
+
* `docs` and `feeds` are real doubles ({@link makeMockDocs}, {@link makeMockFeeds}), because every plugin
|
|
397
|
+
* has both — the empty ones give a component nothing to render, which is the case worth defaulting to.
|
|
398
|
+
*
|
|
399
|
+
* `episodeLabels` is deliberately **absent** by default, and `schema`, `blobs` and `tags` are **`null`**.
|
|
400
|
+
* All four are optional on the real context — the host supplies labels partially, and gives a plugin no
|
|
401
|
+
* schema, no blob store and no tag surface unless its manifest declares them — so a component that needs
|
|
402
|
+
* any of them has to survive its absence. The mock makes you face that unless you pass one in
|
|
403
|
+
* ({@link makeMockSchema}, {@link makeMockBlobs}, {@link makeMockTags}).
|
|
246
404
|
*
|
|
247
405
|
* **`route` is the one override that merges** rather than replacing: `route: { path: 'kraken' }` pins the
|
|
248
406
|
* subpath and keeps the recording `navigate`. Everything else is all-or-nothing, because everything else
|
package/dist/testing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,EAGR,UAAU,
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
|