@backstage/test-utils 1.6.1-next.2 → 1.7.1-next.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/CHANGELOG.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # @backstage/test-utils
2
2
 
3
+ ## 1.7.1-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/theme@0.6.1-next.0
9
+ - @backstage/config@1.2.0
10
+ - @backstage/core-app-api@1.15.1
11
+ - @backstage/core-plugin-api@1.10.0
12
+ - @backstage/types@1.1.1
13
+ - @backstage/plugin-permission-common@0.8.1
14
+ - @backstage/plugin-permission-react@0.4.27
15
+
16
+ ## 1.7.0
17
+
18
+ ### Minor Changes
19
+
20
+ - 9cc7dd6: Added a `mockApis` export, which will replace the `MockX` API implementation classes and their related types. This is analogous with the backend's `mockServices`.
21
+
22
+ **DEPRECATED** several old helpers:
23
+
24
+ - Deprecated `MockAnalyticsApi`, please use `mockApis.analytics` instead.
25
+ - Deprecated `MockConfigApi`, please use `mockApis.config` instead.
26
+ - Deprecated `MockPermissionApi`, please use `mockApis.permission` instead.
27
+ - Deprecated `MockStorageApi`, please use `mockApis.storage` instead.
28
+ - Deprecated `MockTranslationApi`, please use `mockApis.translation` instead.
29
+
30
+ ### Patch Changes
31
+
32
+ - e969dc7: Move `@types/react` to a peer dependency.
33
+ - Updated dependencies
34
+ - @backstage/core-plugin-api@1.10.0
35
+ - @backstage/plugin-permission-react@0.4.27
36
+ - @backstage/core-app-api@1.15.1
37
+ - @backstage/theme@0.6.0
38
+ - @backstage/config@1.2.0
39
+ - @backstage/types@1.1.1
40
+ - @backstage/plugin-permission-common@0.8.1
41
+
3
42
  ## 1.6.1-next.2
4
43
 
5
44
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/test-utils__alpha",
3
- "version": "1.6.1-next.2",
3
+ "version": "1.7.1-next.0",
4
4
  "main": "../dist/alpha.esm.js",
5
5
  "module": "../dist/alpha.esm.js",
6
6
  "types": "../dist/alpha.d.ts"
package/dist/alpha.d.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  import { TranslationApi, TranslationRef, TranslationSnapshot } from '@backstage/core-plugin-api/alpha';
2
2
  import { Observable } from '@backstage/types';
3
3
 
4
- /** @alpha */
4
+ /**
5
+ * @alpha
6
+ * @deprecated Use `mockApis` from `@backstage/test-utils` instead
7
+ */
5
8
  declare class MockTranslationApi implements TranslationApi {
6
9
  #private;
7
10
  static create(): MockTranslationApi;
package/dist/index.d.ts CHANGED
@@ -1,9 +1,12 @@
1
- import { AnalyticsApi, AnalyticsEvent, ConfigApi, ErrorApiError, ErrorApiErrorContext, ErrorApi, DiscoveryApi, IdentityApi, FetchApi, StorageApi, StorageValueSnapshot, RouteRef, ExternalRouteRef, AppComponents, IconComponent, ApiHolder, ApiRef } from '@backstage/core-plugin-api';
1
+ /// <reference types="jest" />
2
+ import { AnalyticsApi, AnalyticsEvent, ConfigApi, ErrorApiError, ErrorApiErrorContext, ErrorApi, DiscoveryApi, IdentityApi, FetchApi, StorageApi, StorageValueSnapshot, ApiFactory, RouteRef, ExternalRouteRef, AppComponents, IconComponent, ApiHolder, ApiRef } from '@backstage/core-plugin-api';
3
+ import * as _backstage_config from '@backstage/config';
2
4
  import { Config } from '@backstage/config';
3
5
  import { JsonObject, JsonValue, Observable } from '@backstage/types';
4
6
  import crossFetch from 'cross-fetch';
5
7
  import { PermissionApi } from '@backstage/plugin-permission-react';
6
8
  import { EvaluatePermissionRequest, AuthorizeResult, EvaluatePermissionResponse } from '@backstage/plugin-permission-common';
9
+ import { TranslationApi } from '@backstage/core-plugin-api/alpha';
7
10
  import React, { ReactElement, ReactNode, ComponentType, PropsWithChildren } from 'react';
8
11
  import { AppIcons } from '@backstage/core-app-api';
9
12
  import { RenderOptions, RenderResult, MatcherFunction } from '@testing-library/react';
@@ -23,6 +26,7 @@ declare function setupRequestMockHandlers(worker: {
23
26
  * Use getEvents in tests to verify captured events.
24
27
  *
25
28
  * @public
29
+ * @deprecated Use {@link @backstage/test-utils#mockApis.(analytics:namespace)} instead
26
30
  */
27
31
  declare class MockAnalyticsApi implements AnalyticsApi {
28
32
  private events;
@@ -35,6 +39,7 @@ declare class MockAnalyticsApi implements AnalyticsApi {
35
39
  * that can be used to mock configuration using a plain object.
36
40
  *
37
41
  * @public
42
+ * @deprecated Use {@link mockApis.(config:namespace)} instead
38
43
  * @example
39
44
  * ```tsx
40
45
  * const mockConfig = new MockConfigApi({
@@ -198,6 +203,7 @@ declare class MockFetchApi implements FetchApi {
198
203
  * {@link @backstage/plugin-permission-react#PermissionApi}. Supply a
199
204
  * requestHandler function to override the mock result returned for a given
200
205
  * request.
206
+ * @deprecated Use {@link @backstage/test-utils#mockApis.(permission:namespace)} instead
201
207
  * @public
202
208
  */
203
209
  declare class MockPermissionApi implements PermissionApi {
@@ -208,6 +214,7 @@ declare class MockPermissionApi implements PermissionApi {
208
214
 
209
215
  /**
210
216
  * Type for map holding data in {@link MockStorageApi}
217
+ * @deprecated Use {@link @backstage/test-utils#mockApis.(storage:namespace)} instead
211
218
  * @public
212
219
  */
213
220
  type MockStorageBucket = {
@@ -215,6 +222,7 @@ type MockStorageBucket = {
215
222
  };
216
223
  /**
217
224
  * Mock implementation of the {@link core-plugin-api#StorageApi} to be used in tests
225
+ * @deprecated Use {@link @backstage/test-utils#mockApis.(storage:namespace)} instead
218
226
  * @public
219
227
  */
220
228
  declare class MockStorageApi implements StorageApi {
@@ -234,6 +242,232 @@ declare class MockStorageApi implements StorageApi {
234
242
  private readonly observable;
235
243
  }
236
244
 
245
+ /**
246
+ * Represents a mocked version of an API, where you automatically have access to
247
+ * the mocked versions of all of its methods along with a factory that returns
248
+ * that same mock.
249
+ *
250
+ * @public
251
+ */
252
+ type ApiMock<TApi> = {
253
+ factory: ApiFactory<TApi, TApi, {}>;
254
+ } & {
255
+ [Key in keyof TApi]: TApi[Key] extends (...args: infer Args) => infer Return ? TApi[Key] & jest.MockInstance<Return, Args> : TApi[Key];
256
+ };
257
+
258
+ /**
259
+ * Mock implementations of the core utility APIs, to be used in tests.
260
+ *
261
+ * @public
262
+ * @remarks
263
+ *
264
+ * There are some variations among the APIs depending on what needs tests
265
+ * might have, but overall there are three main usage patterns:
266
+ *
267
+ * 1: Creating an actual fake API instance, often with a simplified version
268
+ * of functionality, by calling the mock API itself as a function.
269
+ *
270
+ * ```ts
271
+ * // The function often accepts parameters that control its behavior
272
+ * const foo = mockApis.foo();
273
+ * ```
274
+ *
275
+ * 2: Creating a mock API, where all methods are replaced with jest mocks, by
276
+ * calling the API's `mock` function.
277
+ *
278
+ * ```ts
279
+ * // You can optionally supply a subset of its methods to implement
280
+ * const foo = mockApis.foo.mock({
281
+ * someMethod: () => 'mocked result',
282
+ * });
283
+ * // After exercising your test, you can make assertions on the mock:
284
+ * expect(foo.someMethod).toHaveBeenCalledTimes(2);
285
+ * expect(foo.otherMethod).toHaveBeenCalledWith(testData);
286
+ * ```
287
+ *
288
+ * 3: Creating an API factory that behaves similarly to the mock as per above.
289
+ *
290
+ * ```ts
291
+ * const factory = mockApis.foo.factory({
292
+ * someMethod: () => 'mocked result',
293
+ * });
294
+ * ```
295
+ */
296
+ declare namespace mockApis {
297
+ /**
298
+ * Mock implementation of {@link @backstage/core-plugin-api#AnalyticsApi}.
299
+ *
300
+ * @public
301
+ */
302
+ function analytics(): AnalyticsApi;
303
+ /**
304
+ * Mock implementations of {@link @backstage/core-plugin-api#AnalyticsApi}.
305
+ *
306
+ * @public
307
+ */
308
+ namespace analytics {
309
+ const factory: () => ApiFactory<AnalyticsApi, AnalyticsApi, {}>;
310
+ const mock: (partialImpl?: Partial<AnalyticsApi> | undefined) => ApiMock<AnalyticsApi>;
311
+ }
312
+ /**
313
+ * Fake implementation of {@link @backstage/core-plugin-api#ConfigApi}
314
+ * with optional data supplied.
315
+ *
316
+ * @public
317
+ * @example
318
+ *
319
+ * ```tsx
320
+ * const config = mockApis.config({
321
+ * data: { app: { baseUrl: 'https://example.com' } },
322
+ * });
323
+ *
324
+ * await renderInTestApp(
325
+ * <TestApiProvider apis={[[configApiRef, config]]}>
326
+ * <MyTestedComponent />
327
+ * </TestApiProvider>,
328
+ * );
329
+ * ```
330
+ */
331
+ function config(options?: {
332
+ data?: JsonObject;
333
+ }): ConfigApi;
334
+ /**
335
+ * Mock helpers for {@link @backstage/core-plugin-api#ConfigApi}.
336
+ *
337
+ * @see {@link @backstage/core-plugin-api#mockApis.config}
338
+ * @public
339
+ */
340
+ namespace config {
341
+ /**
342
+ * Creates a factory for a fake implementation of
343
+ * {@link @backstage/core-plugin-api#ConfigApi} with optional
344
+ * configuration data supplied.
345
+ *
346
+ * @public
347
+ */
348
+ const factory: (options?: {
349
+ data?: JsonObject | undefined;
350
+ } | undefined) => ApiFactory<_backstage_config.Config, _backstage_config.Config, {}>;
351
+ /**
352
+ * Creates a mock implementation of
353
+ * {@link @backstage/core-plugin-api#ConfigApi}. All methods are
354
+ * replaced with jest mock functions, and you can optionally pass in a
355
+ * subset of methods with an explicit implementation.
356
+ *
357
+ * @public
358
+ */
359
+ const mock: (partialImpl?: Partial<_backstage_config.Config> | undefined) => ApiMock<_backstage_config.Config>;
360
+ }
361
+ /**
362
+ * Fake implementation of {@link @backstage/core-plugin-api#DiscoveryApi}. By
363
+ * default returns URLs on the form `http://example.com/api/<pluginIs>`.
364
+ *
365
+ * @public
366
+ */
367
+ function discovery(options?: {
368
+ baseUrl?: string;
369
+ }): DiscoveryApi;
370
+ /**
371
+ * Mock implementations of {@link @backstage/core-plugin-api#DiscoveryApi}.
372
+ *
373
+ * @public
374
+ */
375
+ namespace discovery {
376
+ const factory: (options?: {
377
+ baseUrl?: string | undefined;
378
+ } | undefined) => ApiFactory<DiscoveryApi, DiscoveryApi, {}>;
379
+ const mock: (partialImpl?: Partial<DiscoveryApi> | undefined) => ApiMock<DiscoveryApi>;
380
+ }
381
+ /**
382
+ * Fake implementation of {@link @backstage/core-plugin-api#IdentityApi}. By
383
+ * default returns no token or profile info, and the user `user:default/test`.
384
+ *
385
+ * @public
386
+ */
387
+ function identity(options?: {
388
+ userEntityRef?: string;
389
+ ownershipEntityRefs?: string[];
390
+ token?: string;
391
+ email?: string;
392
+ displayName?: string;
393
+ picture?: string;
394
+ }): IdentityApi;
395
+ /**
396
+ * Mock implementations of {@link @backstage/core-plugin-api#IdentityApi}.
397
+ *
398
+ * @public
399
+ */
400
+ namespace identity {
401
+ const factory: (options?: {
402
+ userEntityRef?: string | undefined;
403
+ ownershipEntityRefs?: string[] | undefined;
404
+ token?: string | undefined;
405
+ email?: string | undefined;
406
+ displayName?: string | undefined;
407
+ picture?: string | undefined;
408
+ } | undefined) => ApiFactory<IdentityApi, IdentityApi, {}>;
409
+ const mock: (partialImpl?: Partial<IdentityApi> | undefined) => ApiMock<IdentityApi>;
410
+ }
411
+ /**
412
+ * Fake implementation of
413
+ * {@link @backstage/plugin-permission-react#PermissionApi}. By default allows
414
+ * all actions.
415
+ *
416
+ * @public
417
+ */
418
+ function permission(options?: {
419
+ authorize?: AuthorizeResult.ALLOW | AuthorizeResult.DENY | ((request: EvaluatePermissionRequest) => AuthorizeResult.ALLOW | AuthorizeResult.DENY);
420
+ }): PermissionApi;
421
+ /**
422
+ * Mock implementation of
423
+ * {@link @backstage/plugin-permission-react#PermissionApi}.
424
+ *
425
+ * @public
426
+ */
427
+ namespace permission {
428
+ const factory: (options?: {
429
+ authorize?: AuthorizeResult.DENY | AuthorizeResult.ALLOW | ((request: EvaluatePermissionRequest) => AuthorizeResult.DENY | AuthorizeResult.ALLOW) | undefined;
430
+ } | undefined) => ApiFactory<PermissionApi, PermissionApi, {}>;
431
+ const mock: (partialImpl?: Partial<PermissionApi> | undefined) => ApiMock<PermissionApi>;
432
+ }
433
+ /**
434
+ * Fake implementation of {@link @backstage/core-plugin-api#StorageApi}.
435
+ * Stores data temporarily in memory.
436
+ *
437
+ * @public
438
+ */
439
+ function storage(options?: {
440
+ data?: JsonObject;
441
+ }): StorageApi;
442
+ /**
443
+ * Mock implementations of {@link @backstage/core-plugin-api#StorageApi}.
444
+ *
445
+ * @public
446
+ */
447
+ namespace storage {
448
+ const factory: (options?: {
449
+ data?: JsonObject | undefined;
450
+ } | undefined) => ApiFactory<StorageApi, StorageApi, {}>;
451
+ const mock: (partialImpl?: Partial<StorageApi> | undefined) => ApiMock<StorageApi>;
452
+ }
453
+ /**
454
+ * Fake implementation of {@link @backstage/core-plugin-api/alpha#TranslationApi}.
455
+ * By default returns the default translation.
456
+ *
457
+ * @public
458
+ */
459
+ function translation(): TranslationApi;
460
+ /**
461
+ * Mock implementations of {@link @backstage/core-plugin-api/alpha#TranslationApi}.
462
+ *
463
+ * @public
464
+ */
465
+ namespace translation {
466
+ const factory: () => ApiFactory<TranslationApi, TranslationApi, {}>;
467
+ const mock: (partialImpl?: Partial<TranslationApi> | undefined) => ApiMock<TranslationApi>;
468
+ }
469
+ }
470
+
237
471
  /**
238
472
  * This is a mocking method suggested in the Jest docs, as it is not implemented in JSDOM yet.
239
473
  * It can be used to mock values for the Material UI `useMediaQuery` hook if it is used in a tested component.
@@ -502,4 +736,4 @@ declare class TestApiRegistry implements ApiHolder {
502
736
  */
503
737
  declare const TestApiProvider: <T extends any[]>(props: TestApiProviderProps<T>) => React.JSX.Element;
504
738
 
505
- export { type AsyncLogCollector, type CollectedLogs, type ErrorWithContext, type LegacyRootOption, type LogCollector, type LogFuncs, MockAnalyticsApi, MockConfigApi, MockErrorApi, type MockErrorApiOptions, MockFetchApi, type MockFetchApiOptions, MockPermissionApi, MockStorageApi, type MockStorageBucket, type SyncLogCollector, TestApiProvider, type TestApiProviderProps, TestApiRegistry, type TestAppOptions, createTestAppWrapper, mockBreakpoint, registerMswTestHooks, renderInTestApp, renderWithEffects, setupRequestMockHandlers, textContentMatcher, withLogCollector, wrapInTestApp };
739
+ export { type ApiMock, type AsyncLogCollector, type CollectedLogs, type ErrorWithContext, type LegacyRootOption, type LogCollector, type LogFuncs, MockAnalyticsApi, MockConfigApi, MockErrorApi, type MockErrorApiOptions, MockFetchApi, type MockFetchApiOptions, MockPermissionApi, MockStorageApi, type MockStorageBucket, type SyncLogCollector, TestApiProvider, type TestApiProviderProps, TestApiRegistry, type TestAppOptions, createTestAppWrapper, mockApis, mockBreakpoint, registerMswTestHooks, renderInTestApp, renderWithEffects, setupRequestMockHandlers, textContentMatcher, withLogCollector, wrapInTestApp };
package/dist/index.esm.js CHANGED
@@ -5,6 +5,7 @@ export { MockErrorApi } from './testUtils/apis/ErrorApi/MockErrorApi.esm.js';
5
5
  export { MockFetchApi } from './testUtils/apis/FetchApi/MockFetchApi.esm.js';
6
6
  export { MockPermissionApi } from './testUtils/apis/PermissionApi/MockPermissionApi.esm.js';
7
7
  export { MockStorageApi } from './testUtils/apis/StorageApi/MockStorageApi.esm.js';
8
+ export { mockApis } from './testUtils/apis/mockApis.esm.js';
8
9
  export { default as mockBreakpoint } from './testUtils/mockBreakpoint.esm.js';
9
10
  export { createTestAppWrapper, renderInTestApp, textContentMatcher, wrapInTestApp } from './testUtils/appWrappers.esm.js';
10
11
  export { registerMswTestHooks } from './testUtils/msw/registerMswTestHooks.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MockAnalyticsApi.esm.js","sources":["../../../../src/testUtils/apis/AnalyticsApi/MockAnalyticsApi.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AnalyticsApi, AnalyticsEvent } from '@backstage/core-plugin-api';\n\n/**\n * Mock implementation of {@link core-plugin-api#AnalyticsApi} with helpers to ensure that events are sent correctly.\n * Use getEvents in tests to verify captured events.\n *\n * @public\n */\nexport class MockAnalyticsApi implements AnalyticsApi {\n private events: AnalyticsEvent[] = [];\n\n captureEvent(event: AnalyticsEvent) {\n const { action, subject, value, attributes, context } = event;\n\n this.events.push({\n action,\n subject,\n context,\n ...(value !== undefined ? { value } : {}),\n ...(attributes !== undefined ? { attributes } : {}),\n });\n }\n\n getEvents(): AnalyticsEvent[] {\n return this.events;\n }\n}\n"],"names":[],"mappings":"AAwBO,MAAM,gBAAyC,CAAA;AAAA,EAC5C,SAA2B,EAAC,CAAA;AAAA,EAEpC,aAAa,KAAuB,EAAA;AAClC,IAAA,MAAM,EAAE,MAAQ,EAAA,OAAA,EAAS,KAAO,EAAA,UAAA,EAAY,SAAY,GAAA,KAAA,CAAA;AAExD,IAAA,IAAA,CAAK,OAAO,IAAK,CAAA;AAAA,MACf,MAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,GAAI,KAAU,KAAA,KAAA,CAAA,GAAY,EAAE,KAAA,KAAU,EAAC;AAAA,MACvC,GAAI,UAAe,KAAA,KAAA,CAAA,GAAY,EAAE,UAAA,KAAe,EAAC;AAAA,KAClD,CAAA,CAAA;AAAA,GACH;AAAA,EAEA,SAA8B,GAAA;AAC5B,IAAA,OAAO,IAAK,CAAA,MAAA,CAAA;AAAA,GACd;AACF;;;;"}
1
+ {"version":3,"file":"MockAnalyticsApi.esm.js","sources":["../../../../src/testUtils/apis/AnalyticsApi/MockAnalyticsApi.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AnalyticsApi, AnalyticsEvent } from '@backstage/core-plugin-api';\n\n/**\n * Mock implementation of {@link core-plugin-api#AnalyticsApi} with helpers to ensure that events are sent correctly.\n * Use getEvents in tests to verify captured events.\n *\n * @public\n * @deprecated Use {@link @backstage/test-utils#mockApis.(analytics:namespace)} instead\n */\nexport class MockAnalyticsApi implements AnalyticsApi {\n private events: AnalyticsEvent[] = [];\n\n captureEvent(event: AnalyticsEvent) {\n const { action, subject, value, attributes, context } = event;\n\n this.events.push({\n action,\n subject,\n context,\n ...(value !== undefined ? { value } : {}),\n ...(attributes !== undefined ? { attributes } : {}),\n });\n }\n\n getEvents(): AnalyticsEvent[] {\n return this.events;\n }\n}\n"],"names":[],"mappings":"AAyBO,MAAM,gBAAyC,CAAA;AAAA,EAC5C,SAA2B,EAAC,CAAA;AAAA,EAEpC,aAAa,KAAuB,EAAA;AAClC,IAAA,MAAM,EAAE,MAAQ,EAAA,OAAA,EAAS,KAAO,EAAA,UAAA,EAAY,SAAY,GAAA,KAAA,CAAA;AAExD,IAAA,IAAA,CAAK,OAAO,IAAK,CAAA;AAAA,MACf,MAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,GAAI,KAAU,KAAA,KAAA,CAAA,GAAY,EAAE,KAAA,KAAU,EAAC;AAAA,MACvC,GAAI,UAAe,KAAA,KAAA,CAAA,GAAY,EAAE,UAAA,KAAe,EAAC;AAAA,KAClD,CAAA,CAAA;AAAA,GACH;AAAA,EAEA,SAA8B,GAAA;AAC5B,IAAA,OAAO,IAAK,CAAA,MAAA,CAAA;AAAA,GACd;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MockConfigApi.esm.js","sources":["../../../../src/testUtils/apis/ConfigApi/MockConfigApi.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config, ConfigReader } from '@backstage/config';\nimport { JsonObject, JsonValue } from '@backstage/types';\nimport { ConfigApi } from '@backstage/core-plugin-api';\n\n/**\n * MockConfigApi is a thin wrapper around {@link @backstage/config#ConfigReader}\n * that can be used to mock configuration using a plain object.\n *\n * @public\n * @example\n * ```tsx\n * const mockConfig = new MockConfigApi({\n * app: { baseUrl: 'https://example.com' },\n * });\n *\n * const rendered = await renderInTestApp(\n * <TestApiProvider apis={[[configApiRef, mockConfig]]}>\n * <MyTestedComponent />\n * </TestApiProvider>,\n * );\n * ```\n */\nexport class MockConfigApi implements ConfigApi {\n private readonly config: ConfigReader;\n\n // NOTE: not extending in order to avoid inheriting the static `.fromConfigs`\n constructor(data: JsonObject) {\n this.config = new ConfigReader(data);\n }\n\n /** {@inheritdoc @backstage/config#Config.has} */\n has(key: string): boolean {\n return this.config.has(key);\n }\n /** {@inheritdoc @backstage/config#Config.keys} */\n keys(): string[] {\n return this.config.keys();\n }\n /** {@inheritdoc @backstage/config#Config.get} */\n get<T = JsonValue>(key?: string): T {\n return this.config.get(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptional} */\n getOptional<T = JsonValue>(key?: string): T | undefined {\n return this.config.getOptional(key);\n }\n /** {@inheritdoc @backstage/config#Config.getConfig} */\n getConfig(key: string): Config {\n return this.config.getConfig(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalConfig} */\n getOptionalConfig(key: string): Config | undefined {\n return this.config.getOptionalConfig(key);\n }\n /** {@inheritdoc @backstage/config#Config.getConfigArray} */\n getConfigArray(key: string): Config[] {\n return this.config.getConfigArray(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalConfigArray} */\n getOptionalConfigArray(key: string): Config[] | undefined {\n return this.config.getOptionalConfigArray(key);\n }\n /** {@inheritdoc @backstage/config#Config.getNumber} */\n getNumber(key: string): number {\n return this.config.getNumber(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalNumber} */\n getOptionalNumber(key: string): number | undefined {\n return this.config.getOptionalNumber(key);\n }\n /** {@inheritdoc @backstage/config#Config.getBoolean} */\n getBoolean(key: string): boolean {\n return this.config.getBoolean(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalBoolean} */\n getOptionalBoolean(key: string): boolean | undefined {\n return this.config.getOptionalBoolean(key);\n }\n /** {@inheritdoc @backstage/config#Config.getString} */\n getString(key: string): string {\n return this.config.getString(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalString} */\n getOptionalString(key: string): string | undefined {\n return this.config.getOptionalString(key);\n }\n /** {@inheritdoc @backstage/config#Config.getStringArray} */\n getStringArray(key: string): string[] {\n return this.config.getStringArray(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalStringArray} */\n getOptionalStringArray(key: string): string[] | undefined {\n return this.config.getOptionalStringArray(key);\n }\n}\n"],"names":[],"mappings":";;AAsCO,MAAM,aAAmC,CAAA;AAAA,EAC7B,MAAA,CAAA;AAAA;AAAA,EAGjB,YAAY,IAAkB,EAAA;AAC5B,IAAK,IAAA,CAAA,MAAA,GAAS,IAAI,YAAA,CAAa,IAAI,CAAA,CAAA;AAAA,GACrC;AAAA;AAAA,EAGA,IAAI,GAAsB,EAAA;AACxB,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAA,CAAI,GAAG,CAAA,CAAA;AAAA,GAC5B;AAAA;AAAA,EAEA,IAAiB,GAAA;AACf,IAAO,OAAA,IAAA,CAAK,OAAO,IAAK,EAAA,CAAA;AAAA,GAC1B;AAAA;AAAA,EAEA,IAAmB,GAAiB,EAAA;AAClC,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAA,CAAI,GAAG,CAAA,CAAA;AAAA,GAC5B;AAAA;AAAA,EAEA,YAA2B,GAA6B,EAAA;AACtD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,WAAA,CAAY,GAAG,CAAA,CAAA;AAAA,GACpC;AAAA;AAAA,EAEA,UAAU,GAAqB,EAAA;AAC7B,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,SAAA,CAAU,GAAG,CAAA,CAAA;AAAA,GAClC;AAAA;AAAA,EAEA,kBAAkB,GAAiC,EAAA;AACjD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,iBAAA,CAAkB,GAAG,CAAA,CAAA;AAAA,GAC1C;AAAA;AAAA,EAEA,eAAe,GAAuB,EAAA;AACpC,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,cAAA,CAAe,GAAG,CAAA,CAAA;AAAA,GACvC;AAAA;AAAA,EAEA,uBAAuB,GAAmC,EAAA;AACxD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,sBAAA,CAAuB,GAAG,CAAA,CAAA;AAAA,GAC/C;AAAA;AAAA,EAEA,UAAU,GAAqB,EAAA;AAC7B,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,SAAA,CAAU,GAAG,CAAA,CAAA;AAAA,GAClC;AAAA;AAAA,EAEA,kBAAkB,GAAiC,EAAA;AACjD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,iBAAA,CAAkB,GAAG,CAAA,CAAA;AAAA,GAC1C;AAAA;AAAA,EAEA,WAAW,GAAsB,EAAA;AAC/B,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,UAAA,CAAW,GAAG,CAAA,CAAA;AAAA,GACnC;AAAA;AAAA,EAEA,mBAAmB,GAAkC,EAAA;AACnD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,kBAAA,CAAmB,GAAG,CAAA,CAAA;AAAA,GAC3C;AAAA;AAAA,EAEA,UAAU,GAAqB,EAAA;AAC7B,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,SAAA,CAAU,GAAG,CAAA,CAAA;AAAA,GAClC;AAAA;AAAA,EAEA,kBAAkB,GAAiC,EAAA;AACjD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,iBAAA,CAAkB,GAAG,CAAA,CAAA;AAAA,GAC1C;AAAA;AAAA,EAEA,eAAe,GAAuB,EAAA;AACpC,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,cAAA,CAAe,GAAG,CAAA,CAAA;AAAA,GACvC;AAAA;AAAA,EAEA,uBAAuB,GAAmC,EAAA;AACxD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,sBAAA,CAAuB,GAAG,CAAA,CAAA;AAAA,GAC/C;AACF;;;;"}
1
+ {"version":3,"file":"MockConfigApi.esm.js","sources":["../../../../src/testUtils/apis/ConfigApi/MockConfigApi.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config, ConfigReader } from '@backstage/config';\nimport { JsonObject, JsonValue } from '@backstage/types';\nimport { ConfigApi } from '@backstage/core-plugin-api';\n\n/**\n * MockConfigApi is a thin wrapper around {@link @backstage/config#ConfigReader}\n * that can be used to mock configuration using a plain object.\n *\n * @public\n * @deprecated Use {@link mockApis.(config:namespace)} instead\n * @example\n * ```tsx\n * const mockConfig = new MockConfigApi({\n * app: { baseUrl: 'https://example.com' },\n * });\n *\n * const rendered = await renderInTestApp(\n * <TestApiProvider apis={[[configApiRef, mockConfig]]}>\n * <MyTestedComponent />\n * </TestApiProvider>,\n * );\n * ```\n */\nexport class MockConfigApi implements ConfigApi {\n private readonly config: ConfigReader;\n\n // NOTE: not extending in order to avoid inheriting the static `.fromConfigs`\n constructor(data: JsonObject) {\n this.config = new ConfigReader(data);\n }\n\n /** {@inheritdoc @backstage/config#Config.has} */\n has(key: string): boolean {\n return this.config.has(key);\n }\n /** {@inheritdoc @backstage/config#Config.keys} */\n keys(): string[] {\n return this.config.keys();\n }\n /** {@inheritdoc @backstage/config#Config.get} */\n get<T = JsonValue>(key?: string): T {\n return this.config.get(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptional} */\n getOptional<T = JsonValue>(key?: string): T | undefined {\n return this.config.getOptional(key);\n }\n /** {@inheritdoc @backstage/config#Config.getConfig} */\n getConfig(key: string): Config {\n return this.config.getConfig(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalConfig} */\n getOptionalConfig(key: string): Config | undefined {\n return this.config.getOptionalConfig(key);\n }\n /** {@inheritdoc @backstage/config#Config.getConfigArray} */\n getConfigArray(key: string): Config[] {\n return this.config.getConfigArray(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalConfigArray} */\n getOptionalConfigArray(key: string): Config[] | undefined {\n return this.config.getOptionalConfigArray(key);\n }\n /** {@inheritdoc @backstage/config#Config.getNumber} */\n getNumber(key: string): number {\n return this.config.getNumber(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalNumber} */\n getOptionalNumber(key: string): number | undefined {\n return this.config.getOptionalNumber(key);\n }\n /** {@inheritdoc @backstage/config#Config.getBoolean} */\n getBoolean(key: string): boolean {\n return this.config.getBoolean(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalBoolean} */\n getOptionalBoolean(key: string): boolean | undefined {\n return this.config.getOptionalBoolean(key);\n }\n /** {@inheritdoc @backstage/config#Config.getString} */\n getString(key: string): string {\n return this.config.getString(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalString} */\n getOptionalString(key: string): string | undefined {\n return this.config.getOptionalString(key);\n }\n /** {@inheritdoc @backstage/config#Config.getStringArray} */\n getStringArray(key: string): string[] {\n return this.config.getStringArray(key);\n }\n /** {@inheritdoc @backstage/config#Config.getOptionalStringArray} */\n getOptionalStringArray(key: string): string[] | undefined {\n return this.config.getOptionalStringArray(key);\n }\n}\n"],"names":[],"mappings":";;AAuCO,MAAM,aAAmC,CAAA;AAAA,EAC7B,MAAA,CAAA;AAAA;AAAA,EAGjB,YAAY,IAAkB,EAAA;AAC5B,IAAK,IAAA,CAAA,MAAA,GAAS,IAAI,YAAA,CAAa,IAAI,CAAA,CAAA;AAAA,GACrC;AAAA;AAAA,EAGA,IAAI,GAAsB,EAAA;AACxB,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAA,CAAI,GAAG,CAAA,CAAA;AAAA,GAC5B;AAAA;AAAA,EAEA,IAAiB,GAAA;AACf,IAAO,OAAA,IAAA,CAAK,OAAO,IAAK,EAAA,CAAA;AAAA,GAC1B;AAAA;AAAA,EAEA,IAAmB,GAAiB,EAAA;AAClC,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAA,CAAI,GAAG,CAAA,CAAA;AAAA,GAC5B;AAAA;AAAA,EAEA,YAA2B,GAA6B,EAAA;AACtD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,WAAA,CAAY,GAAG,CAAA,CAAA;AAAA,GACpC;AAAA;AAAA,EAEA,UAAU,GAAqB,EAAA;AAC7B,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,SAAA,CAAU,GAAG,CAAA,CAAA;AAAA,GAClC;AAAA;AAAA,EAEA,kBAAkB,GAAiC,EAAA;AACjD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,iBAAA,CAAkB,GAAG,CAAA,CAAA;AAAA,GAC1C;AAAA;AAAA,EAEA,eAAe,GAAuB,EAAA;AACpC,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,cAAA,CAAe,GAAG,CAAA,CAAA;AAAA,GACvC;AAAA;AAAA,EAEA,uBAAuB,GAAmC,EAAA;AACxD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,sBAAA,CAAuB,GAAG,CAAA,CAAA;AAAA,GAC/C;AAAA;AAAA,EAEA,UAAU,GAAqB,EAAA;AAC7B,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,SAAA,CAAU,GAAG,CAAA,CAAA;AAAA,GAClC;AAAA;AAAA,EAEA,kBAAkB,GAAiC,EAAA;AACjD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,iBAAA,CAAkB,GAAG,CAAA,CAAA;AAAA,GAC1C;AAAA;AAAA,EAEA,WAAW,GAAsB,EAAA;AAC/B,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,UAAA,CAAW,GAAG,CAAA,CAAA;AAAA,GACnC;AAAA;AAAA,EAEA,mBAAmB,GAAkC,EAAA;AACnD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,kBAAA,CAAmB,GAAG,CAAA,CAAA;AAAA,GAC3C;AAAA;AAAA,EAEA,UAAU,GAAqB,EAAA;AAC7B,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,SAAA,CAAU,GAAG,CAAA,CAAA;AAAA,GAClC;AAAA;AAAA,EAEA,kBAAkB,GAAiC,EAAA;AACjD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,iBAAA,CAAkB,GAAG,CAAA,CAAA;AAAA,GAC1C;AAAA;AAAA,EAEA,eAAe,GAAuB,EAAA;AACpC,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,cAAA,CAAe,GAAG,CAAA,CAAA;AAAA,GACvC;AAAA;AAAA,EAEA,uBAAuB,GAAmC,EAAA;AACxD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,sBAAA,CAAuB,GAAG,CAAA,CAAA;AAAA,GAC/C;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MockPermissionApi.esm.js","sources":["../../../../src/testUtils/apis/PermissionApi/MockPermissionApi.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PermissionApi } from '@backstage/plugin-permission-react';\nimport {\n EvaluatePermissionResponse,\n EvaluatePermissionRequest,\n AuthorizeResult,\n} from '@backstage/plugin-permission-common';\n\n/**\n * Mock implementation of\n * {@link @backstage/plugin-permission-react#PermissionApi}. Supply a\n * requestHandler function to override the mock result returned for a given\n * request.\n * @public\n */\nexport class MockPermissionApi implements PermissionApi {\n constructor(\n private readonly requestHandler: (\n request: EvaluatePermissionRequest,\n ) => AuthorizeResult.ALLOW | AuthorizeResult.DENY = () =>\n AuthorizeResult.ALLOW,\n ) {}\n\n async authorize(\n request: EvaluatePermissionRequest,\n ): Promise<EvaluatePermissionResponse> {\n return { result: this.requestHandler(request) };\n }\n}\n"],"names":[],"mappings":";;AA8BO,MAAM,iBAA2C,CAAA;AAAA,EACtD,WACmB,CAAA,cAAA,GAEmC,MAClD,eAAA,CAAgB,KAClB,EAAA;AAJiB,IAAA,IAAA,CAAA,cAAA,GAAA,cAAA,CAAA;AAAA,GAIhB;AAAA,EAEH,MAAM,UACJ,OACqC,EAAA;AACrC,IAAA,OAAO,EAAE,MAAA,EAAQ,IAAK,CAAA,cAAA,CAAe,OAAO,CAAE,EAAA,CAAA;AAAA,GAChD;AACF;;;;"}
1
+ {"version":3,"file":"MockPermissionApi.esm.js","sources":["../../../../src/testUtils/apis/PermissionApi/MockPermissionApi.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PermissionApi } from '@backstage/plugin-permission-react';\nimport {\n EvaluatePermissionResponse,\n EvaluatePermissionRequest,\n AuthorizeResult,\n} from '@backstage/plugin-permission-common';\n\n/**\n * Mock implementation of\n * {@link @backstage/plugin-permission-react#PermissionApi}. Supply a\n * requestHandler function to override the mock result returned for a given\n * request.\n * @deprecated Use {@link @backstage/test-utils#mockApis.(permission:namespace)} instead\n * @public\n */\nexport class MockPermissionApi implements PermissionApi {\n constructor(\n private readonly requestHandler: (\n request: EvaluatePermissionRequest,\n ) => AuthorizeResult.ALLOW | AuthorizeResult.DENY = () =>\n AuthorizeResult.ALLOW,\n ) {}\n\n async authorize(\n request: EvaluatePermissionRequest,\n ): Promise<EvaluatePermissionResponse> {\n return { result: this.requestHandler(request) };\n }\n}\n"],"names":[],"mappings":";;AA+BO,MAAM,iBAA2C,CAAA;AAAA,EACtD,WACmB,CAAA,cAAA,GAEmC,MAClD,eAAA,CAAgB,KAClB,EAAA;AAJiB,IAAA,IAAA,CAAA,cAAA,GAAA,cAAA,CAAA;AAAA,GAIhB;AAAA,EAEH,MAAM,UACJ,OACqC,EAAA;AACrC,IAAA,OAAO,EAAE,MAAA,EAAQ,IAAK,CAAA,cAAA,CAAe,OAAO,CAAE,EAAA,CAAA;AAAA,GAChD;AACF;;;;"}
@@ -10,7 +10,19 @@ class MockStorageApi {
10
10
  this.data = { ...data };
11
11
  }
12
12
  static create(data) {
13
- return new MockStorageApi("", /* @__PURE__ */ new Map(), data);
13
+ const keyValues = {};
14
+ function put(value, namespace) {
15
+ for (const [key, val] of Object.entries(value)) {
16
+ if (typeof val === "object" && val !== null) {
17
+ put(val, `${namespace}/${key}`);
18
+ } else {
19
+ const namespacedKey = `${namespace}/${key.replace(/^\//, "")}`;
20
+ keyValues[namespacedKey] = val;
21
+ }
22
+ }
23
+ }
24
+ put(data ?? {}, "");
25
+ return new MockStorageApi("", /* @__PURE__ */ new Map(), keyValues);
14
26
  }
15
27
  forBucket(name) {
16
28
  if (!this.bucketStorageApis.has(name)) {
@@ -1 +1 @@
1
- {"version":3,"file":"MockStorageApi.esm.js","sources":["../../../../src/testUtils/apis/StorageApi/MockStorageApi.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { StorageApi, StorageValueSnapshot } from '@backstage/core-plugin-api';\nimport { JsonValue, Observable } from '@backstage/types';\nimport ObservableImpl from 'zen-observable';\n\n/**\n * Type for map holding data in {@link MockStorageApi}\n * @public\n */\nexport type MockStorageBucket = { [key: string]: any };\n\n/**\n * Mock implementation of the {@link core-plugin-api#StorageApi} to be used in tests\n * @public\n */\nexport class MockStorageApi implements StorageApi {\n private readonly namespace: string;\n private readonly data: MockStorageBucket;\n private readonly bucketStorageApis: Map<string, MockStorageApi>;\n\n private constructor(\n namespace: string,\n bucketStorageApis: Map<string, MockStorageApi>,\n data?: MockStorageBucket,\n ) {\n this.namespace = namespace;\n this.bucketStorageApis = bucketStorageApis;\n this.data = { ...data };\n }\n\n static create(data?: MockStorageBucket) {\n return new MockStorageApi('', new Map(), data);\n }\n\n forBucket(name: string): StorageApi {\n if (!this.bucketStorageApis.has(name)) {\n this.bucketStorageApis.set(\n name,\n new MockStorageApi(\n `${this.namespace}/${name}`,\n this.bucketStorageApis,\n this.data,\n ),\n );\n }\n return this.bucketStorageApis.get(name)!;\n }\n\n snapshot<T extends JsonValue>(key: string): StorageValueSnapshot<T> {\n if (this.data.hasOwnProperty(this.getKeyName(key))) {\n const data = this.data[this.getKeyName(key)];\n return {\n key,\n presence: 'present',\n value: data,\n };\n }\n return {\n key,\n presence: 'absent',\n value: undefined,\n };\n }\n\n async set<T>(key: string, data: T): Promise<void> {\n const serialized = JSON.parse(JSON.stringify(data), (_key, value) => {\n if (typeof value === 'object' && value !== null) {\n Object.freeze(value);\n }\n return value;\n });\n this.data[this.getKeyName(key)] = serialized;\n this.notifyChanges({\n key,\n presence: 'present',\n value: serialized,\n });\n }\n\n async remove(key: string): Promise<void> {\n delete this.data[this.getKeyName(key)];\n this.notifyChanges({\n key,\n presence: 'absent',\n value: undefined,\n });\n }\n\n observe$<T extends JsonValue>(\n key: string,\n ): Observable<StorageValueSnapshot<T>> {\n return this.observable.filter(({ key: messageKey }) => messageKey === key);\n }\n\n private getKeyName(key: string) {\n return `${this.namespace}/${encodeURIComponent(key)}`;\n }\n\n private notifyChanges<T extends JsonValue>(message: StorageValueSnapshot<T>) {\n for (const subscription of this.subscribers) {\n subscription.next(message);\n }\n }\n\n private subscribers = new Set<\n ZenObservable.SubscriptionObserver<StorageValueSnapshot<JsonValue>>\n >();\n\n private readonly observable = new ObservableImpl<\n StorageValueSnapshot<JsonValue>\n >(subscriber => {\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\n };\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MockStorageApi.esm.js","sources":["../../../../src/testUtils/apis/StorageApi/MockStorageApi.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { StorageApi, StorageValueSnapshot } from '@backstage/core-plugin-api';\nimport { JsonValue, Observable } from '@backstage/types';\nimport ObservableImpl from 'zen-observable';\n\n/**\n * Type for map holding data in {@link MockStorageApi}\n * @deprecated Use {@link @backstage/test-utils#mockApis.(storage:namespace)} instead\n * @public\n */\nexport type MockStorageBucket = { [key: string]: any };\n\n/**\n * Mock implementation of the {@link core-plugin-api#StorageApi} to be used in tests\n * @deprecated Use {@link @backstage/test-utils#mockApis.(storage:namespace)} instead\n * @public\n */\nexport class MockStorageApi implements StorageApi {\n private readonly namespace: string;\n private readonly data: MockStorageBucket;\n private readonly bucketStorageApis: Map<string, MockStorageApi>;\n\n private constructor(\n namespace: string,\n bucketStorageApis: Map<string, MockStorageApi>,\n data?: MockStorageBucket,\n ) {\n this.namespace = namespace;\n this.bucketStorageApis = bucketStorageApis;\n this.data = { ...data };\n }\n\n static create(data?: MockStorageBucket) {\n // Translate a nested data object structure into a flat object with keys\n // like `/a/b` with their corresponding leaf values\n const keyValues: { [key: string]: any } = {};\n function put(value: { [key: string]: any }, namespace: string) {\n for (const [key, val] of Object.entries(value)) {\n if (typeof val === 'object' && val !== null) {\n put(val, `${namespace}/${key}`);\n } else {\n const namespacedKey = `${namespace}/${key.replace(/^\\//, '')}`;\n keyValues[namespacedKey] = val;\n }\n }\n }\n put(data ?? {}, '');\n return new MockStorageApi('', new Map(), keyValues);\n }\n\n forBucket(name: string): StorageApi {\n if (!this.bucketStorageApis.has(name)) {\n this.bucketStorageApis.set(\n name,\n new MockStorageApi(\n `${this.namespace}/${name}`,\n this.bucketStorageApis,\n this.data,\n ),\n );\n }\n return this.bucketStorageApis.get(name)!;\n }\n\n snapshot<T extends JsonValue>(key: string): StorageValueSnapshot<T> {\n if (this.data.hasOwnProperty(this.getKeyName(key))) {\n const data = this.data[this.getKeyName(key)];\n return {\n key,\n presence: 'present',\n value: data,\n };\n }\n return {\n key,\n presence: 'absent',\n value: undefined,\n };\n }\n\n async set<T>(key: string, data: T): Promise<void> {\n const serialized = JSON.parse(JSON.stringify(data), (_key, value) => {\n if (typeof value === 'object' && value !== null) {\n Object.freeze(value);\n }\n return value;\n });\n this.data[this.getKeyName(key)] = serialized;\n this.notifyChanges({\n key,\n presence: 'present',\n value: serialized,\n });\n }\n\n async remove(key: string): Promise<void> {\n delete this.data[this.getKeyName(key)];\n this.notifyChanges({\n key,\n presence: 'absent',\n value: undefined,\n });\n }\n\n observe$<T extends JsonValue>(\n key: string,\n ): Observable<StorageValueSnapshot<T>> {\n return this.observable.filter(({ key: messageKey }) => messageKey === key);\n }\n\n private getKeyName(key: string) {\n return `${this.namespace}/${encodeURIComponent(key)}`;\n }\n\n private notifyChanges<T extends JsonValue>(message: StorageValueSnapshot<T>) {\n for (const subscription of this.subscribers) {\n subscription.next(message);\n }\n }\n\n private subscribers = new Set<\n ZenObservable.SubscriptionObserver<StorageValueSnapshot<JsonValue>>\n >();\n\n private readonly observable = new ObservableImpl<\n StorageValueSnapshot<JsonValue>\n >(subscriber => {\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\n };\n });\n}\n"],"names":[],"mappings":";;AAgCO,MAAM,cAAqC,CAAA;AAAA,EAC/B,SAAA,CAAA;AAAA,EACA,IAAA,CAAA;AAAA,EACA,iBAAA,CAAA;AAAA,EAET,WAAA,CACN,SACA,EAAA,iBAAA,EACA,IACA,EAAA;AACA,IAAA,IAAA,CAAK,SAAY,GAAA,SAAA,CAAA;AACjB,IAAA,IAAA,CAAK,iBAAoB,GAAA,iBAAA,CAAA;AACzB,IAAK,IAAA,CAAA,IAAA,GAAO,EAAE,GAAG,IAAK,EAAA,CAAA;AAAA,GACxB;AAAA,EAEA,OAAO,OAAO,IAA0B,EAAA;AAGtC,IAAA,MAAM,YAAoC,EAAC,CAAA;AAC3C,IAAS,SAAA,GAAA,CAAI,OAA+B,SAAmB,EAAA;AAC7D,MAAA,KAAA,MAAW,CAAC,GAAK,EAAA,GAAG,KAAK,MAAO,CAAA,OAAA,CAAQ,KAAK,CAAG,EAAA;AAC9C,QAAA,IAAI,OAAO,GAAA,KAAQ,QAAY,IAAA,GAAA,KAAQ,IAAM,EAAA;AAC3C,UAAA,GAAA,CAAI,GAAK,EAAA,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,GAAG,CAAE,CAAA,CAAA,CAAA;AAAA,SACzB,MAAA;AACL,UAAM,MAAA,aAAA,GAAgB,GAAG,SAAS,CAAA,CAAA,EAAI,IAAI,OAAQ,CAAA,KAAA,EAAO,EAAE,CAAC,CAAA,CAAA,CAAA;AAC5D,UAAA,SAAA,CAAU,aAAa,CAAI,GAAA,GAAA,CAAA;AAAA,SAC7B;AAAA,OACF;AAAA,KACF;AACA,IAAI,GAAA,CAAA,IAAA,IAAQ,EAAC,EAAG,EAAE,CAAA,CAAA;AAClB,IAAA,OAAO,IAAI,cAAe,CAAA,EAAA,kBAAQ,IAAA,GAAA,IAAO,SAAS,CAAA,CAAA;AAAA,GACpD;AAAA,EAEA,UAAU,IAA0B,EAAA;AAClC,IAAA,IAAI,CAAC,IAAA,CAAK,iBAAkB,CAAA,GAAA,CAAI,IAAI,CAAG,EAAA;AACrC,MAAA,IAAA,CAAK,iBAAkB,CAAA,GAAA;AAAA,QACrB,IAAA;AAAA,QACA,IAAI,cAAA;AAAA,UACF,CAAG,EAAA,IAAA,CAAK,SAAS,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAAA,UACzB,IAAK,CAAA,iBAAA;AAAA,UACL,IAAK,CAAA,IAAA;AAAA,SACP;AAAA,OACF,CAAA;AAAA,KACF;AACA,IAAO,OAAA,IAAA,CAAK,iBAAkB,CAAA,GAAA,CAAI,IAAI,CAAA,CAAA;AAAA,GACxC;AAAA,EAEA,SAA8B,GAAsC,EAAA;AAClE,IAAA,IAAI,KAAK,IAAK,CAAA,cAAA,CAAe,KAAK,UAAW,CAAA,GAAG,CAAC,CAAG,EAAA;AAClD,MAAA,MAAM,OAAO,IAAK,CAAA,IAAA,CAAK,IAAK,CAAA,UAAA,CAAW,GAAG,CAAC,CAAA,CAAA;AAC3C,MAAO,OAAA;AAAA,QACL,GAAA;AAAA,QACA,QAAU,EAAA,SAAA;AAAA,QACV,KAAO,EAAA,IAAA;AAAA,OACT,CAAA;AAAA,KACF;AACA,IAAO,OAAA;AAAA,MACL,GAAA;AAAA,MACA,QAAU,EAAA,QAAA;AAAA,MACV,KAAO,EAAA,KAAA,CAAA;AAAA,KACT,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,GAAO,CAAA,GAAA,EAAa,IAAwB,EAAA;AAChD,IAAM,MAAA,UAAA,GAAa,KAAK,KAAM,CAAA,IAAA,CAAK,UAAU,IAAI,CAAA,EAAG,CAAC,IAAA,EAAM,KAAU,KAAA;AACnE,MAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,KAAA,KAAU,IAAM,EAAA;AAC/C,QAAA,MAAA,CAAO,OAAO,KAAK,CAAA,CAAA;AAAA,OACrB;AACA,MAAO,OAAA,KAAA,CAAA;AAAA,KACR,CAAA,CAAA;AACD,IAAA,IAAA,CAAK,IAAK,CAAA,IAAA,CAAK,UAAW,CAAA,GAAG,CAAC,CAAI,GAAA,UAAA,CAAA;AAClC,IAAA,IAAA,CAAK,aAAc,CAAA;AAAA,MACjB,GAAA;AAAA,MACA,QAAU,EAAA,SAAA;AAAA,MACV,KAAO,EAAA,UAAA;AAAA,KACR,CAAA,CAAA;AAAA,GACH;AAAA,EAEA,MAAM,OAAO,GAA4B,EAAA;AACvC,IAAA,OAAO,IAAK,CAAA,IAAA,CAAK,IAAK,CAAA,UAAA,CAAW,GAAG,CAAC,CAAA,CAAA;AACrC,IAAA,IAAA,CAAK,aAAc,CAAA;AAAA,MACjB,GAAA;AAAA,MACA,QAAU,EAAA,QAAA;AAAA,MACV,KAAO,EAAA,KAAA,CAAA;AAAA,KACR,CAAA,CAAA;AAAA,GACH;AAAA,EAEA,SACE,GACqC,EAAA;AACrC,IAAO,OAAA,IAAA,CAAK,WAAW,MAAO,CAAA,CAAC,EAAE,GAAK,EAAA,UAAA,EAAiB,KAAA,UAAA,KAAe,GAAG,CAAA,CAAA;AAAA,GAC3E;AAAA,EAEQ,WAAW,GAAa,EAAA;AAC9B,IAAA,OAAO,GAAG,IAAK,CAAA,SAAS,CAAI,CAAA,EAAA,kBAAA,CAAmB,GAAG,CAAC,CAAA,CAAA,CAAA;AAAA,GACrD;AAAA,EAEQ,cAAmC,OAAkC,EAAA;AAC3E,IAAW,KAAA,MAAA,YAAA,IAAgB,KAAK,WAAa,EAAA;AAC3C,MAAA,YAAA,CAAa,KAAK,OAAO,CAAA,CAAA;AAAA,KAC3B;AAAA,GACF;AAAA,EAEQ,WAAA,uBAAkB,GAExB,EAAA,CAAA;AAAA,EAEe,UAAA,GAAa,IAAI,cAAA,CAEhC,CAAc,UAAA,KAAA;AACd,IAAK,IAAA,CAAA,WAAA,CAAY,IAAI,UAAU,CAAA,CAAA;AAC/B,IAAA,OAAO,MAAM;AACX,MAAK,IAAA,CAAA,WAAA,CAAY,OAAO,UAAU,CAAA,CAAA;AAAA,KACpC,CAAA;AAAA,GACD,CAAA,CAAA;AACH;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MockTranslationApi.esm.js","sources":["../../../../src/testUtils/apis/TranslationApi/MockTranslationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n TranslationApi,\n TranslationFunction,\n TranslationRef,\n TranslationSnapshot,\n} from '@backstage/core-plugin-api/alpha';\nimport { createInstance as createI18n, type i18n as I18n } from 'i18next';\nimport ObservableImpl from 'zen-observable';\n\nimport { Observable } from '@backstage/types';\n// Internal import to avoid code duplication, this will lead to duplication in build output\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalTranslationRef } from '../../../../../core-plugin-api/src/translation/TranslationRef';\n\nconst DEFAULT_LANGUAGE = 'en';\n\n/** @alpha */\nexport class MockTranslationApi implements TranslationApi {\n static create() {\n const i18n = createI18n({\n fallbackLng: DEFAULT_LANGUAGE,\n supportedLngs: [DEFAULT_LANGUAGE],\n interpolation: {\n escapeValue: false,\n },\n ns: [],\n defaultNS: false,\n fallbackNS: false,\n\n // Disable resource loading on init, meaning i18n will be ready to use immediately\n initImmediate: false,\n });\n\n i18n.init();\n if (!i18n.isInitialized) {\n throw new Error('i18next was unexpectedly not initialized');\n }\n\n return new MockTranslationApi(i18n);\n }\n\n #i18n: I18n;\n #registeredRefs = new Set<string>();\n\n private constructor(i18n: I18n) {\n this.#i18n = i18n;\n }\n\n getTranslation<TMessages extends { [key in string]: string }>(\n translationRef: TranslationRef<string, TMessages>,\n ): TranslationSnapshot<TMessages> {\n const internalRef = toInternalTranslationRef(translationRef);\n\n if (!this.#registeredRefs.has(internalRef.id)) {\n this.#registeredRefs.add(internalRef.id);\n this.#i18n.addResourceBundle(\n DEFAULT_LANGUAGE,\n internalRef.id,\n internalRef.getDefaultMessages(),\n false, // do not merge\n true, // overwrite existing\n );\n }\n\n const t = this.#i18n.getFixedT(\n null,\n internalRef.id,\n ) as TranslationFunction<TMessages>;\n\n return {\n ready: true,\n t,\n };\n }\n\n translation$<TMessages extends { [key in string]: string }>(): Observable<\n TranslationSnapshot<TMessages>\n > {\n // No need to implement, getTranslation will always return a ready snapshot\n return new ObservableImpl<TranslationSnapshot<TMessages>>(_subscriber => {\n return () => {};\n });\n }\n}\n"],"names":["createI18n"],"mappings":";;;;AA8BA,MAAM,gBAAmB,GAAA,IAAA,CAAA;AAGlB,MAAM,kBAA6C,CAAA;AAAA,EACxD,OAAO,MAAS,GAAA;AACd,IAAA,MAAM,OAAOA,cAAW,CAAA;AAAA,MACtB,WAAa,EAAA,gBAAA;AAAA,MACb,aAAA,EAAe,CAAC,gBAAgB,CAAA;AAAA,MAChC,aAAe,EAAA;AAAA,QACb,WAAa,EAAA,KAAA;AAAA,OACf;AAAA,MACA,IAAI,EAAC;AAAA,MACL,SAAW,EAAA,KAAA;AAAA,MACX,UAAY,EAAA,KAAA;AAAA;AAAA,MAGZ,aAAe,EAAA,KAAA;AAAA,KAChB,CAAA,CAAA;AAED,IAAA,IAAA,CAAK,IAAK,EAAA,CAAA;AACV,IAAI,IAAA,CAAC,KAAK,aAAe,EAAA;AACvB,MAAM,MAAA,IAAI,MAAM,0CAA0C,CAAA,CAAA;AAAA,KAC5D;AAEA,IAAO,OAAA,IAAI,mBAAmB,IAAI,CAAA,CAAA;AAAA,GACpC;AAAA,EAEA,KAAA,CAAA;AAAA,EACA,eAAA,uBAAsB,GAAY,EAAA,CAAA;AAAA,EAE1B,YAAY,IAAY,EAAA;AAC9B,IAAA,IAAA,CAAK,KAAQ,GAAA,IAAA,CAAA;AAAA,GACf;AAAA,EAEA,eACE,cACgC,EAAA;AAChC,IAAM,MAAA,WAAA,GAAc,yBAAyB,cAAc,CAAA,CAAA;AAE3D,IAAA,IAAI,CAAC,IAAK,CAAA,eAAA,CAAgB,GAAI,CAAA,WAAA,CAAY,EAAE,CAAG,EAAA;AAC7C,MAAK,IAAA,CAAA,eAAA,CAAgB,GAAI,CAAA,WAAA,CAAY,EAAE,CAAA,CAAA;AACvC,MAAA,IAAA,CAAK,KAAM,CAAA,iBAAA;AAAA,QACT,gBAAA;AAAA,QACA,WAAY,CAAA,EAAA;AAAA,QACZ,YAAY,kBAAmB,EAAA;AAAA,QAC/B,KAAA;AAAA;AAAA,QACA,IAAA;AAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAM,MAAA,CAAA,GAAI,KAAK,KAAM,CAAA,SAAA;AAAA,MACnB,IAAA;AAAA,MACA,WAAY,CAAA,EAAA;AAAA,KACd,CAAA;AAEA,IAAO,OAAA;AAAA,MACL,KAAO,EAAA,IAAA;AAAA,MACP,CAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,YAEE,GAAA;AAEA,IAAO,OAAA,IAAI,eAA+C,CAAe,WAAA,KAAA;AACvE,MAAA,OAAO,MAAM;AAAA,OAAC,CAAA;AAAA,KACf,CAAA,CAAA;AAAA,GACH;AACF;;;;"}
1
+ {"version":3,"file":"MockTranslationApi.esm.js","sources":["../../../../src/testUtils/apis/TranslationApi/MockTranslationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n TranslationApi,\n TranslationFunction,\n TranslationRef,\n TranslationSnapshot,\n} from '@backstage/core-plugin-api/alpha';\nimport { createInstance as createI18n, type i18n as I18n } from 'i18next';\nimport ObservableImpl from 'zen-observable';\n\nimport { Observable } from '@backstage/types';\n// Internal import to avoid code duplication, this will lead to duplication in build output\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalTranslationRef } from '../../../../../core-plugin-api/src/translation/TranslationRef';\n\nconst DEFAULT_LANGUAGE = 'en';\n\n/**\n * @alpha\n * @deprecated Use `mockApis` from `@backstage/test-utils` instead\n */\nexport class MockTranslationApi implements TranslationApi {\n static create() {\n const i18n = createI18n({\n fallbackLng: DEFAULT_LANGUAGE,\n supportedLngs: [DEFAULT_LANGUAGE],\n interpolation: {\n escapeValue: false,\n },\n ns: [],\n defaultNS: false,\n fallbackNS: false,\n\n // Disable resource loading on init, meaning i18n will be ready to use immediately\n initImmediate: false,\n });\n\n i18n.init();\n if (!i18n.isInitialized) {\n throw new Error('i18next was unexpectedly not initialized');\n }\n\n return new MockTranslationApi(i18n);\n }\n\n #i18n: I18n;\n #registeredRefs = new Set<string>();\n\n private constructor(i18n: I18n) {\n this.#i18n = i18n;\n }\n\n getTranslation<TMessages extends { [key in string]: string }>(\n translationRef: TranslationRef<string, TMessages>,\n ): TranslationSnapshot<TMessages> {\n const internalRef = toInternalTranslationRef(translationRef);\n\n if (!this.#registeredRefs.has(internalRef.id)) {\n this.#registeredRefs.add(internalRef.id);\n this.#i18n.addResourceBundle(\n DEFAULT_LANGUAGE,\n internalRef.id,\n internalRef.getDefaultMessages(),\n false, // do not merge\n true, // overwrite existing\n );\n }\n\n const t = this.#i18n.getFixedT(\n null,\n internalRef.id,\n ) as TranslationFunction<TMessages>;\n\n return {\n ready: true,\n t,\n };\n }\n\n translation$<TMessages extends { [key in string]: string }>(): Observable<\n TranslationSnapshot<TMessages>\n > {\n // No need to implement, getTranslation will always return a ready snapshot\n return new ObservableImpl<TranslationSnapshot<TMessages>>(_subscriber => {\n return () => {};\n });\n }\n}\n"],"names":["createI18n"],"mappings":";;;;AA8BA,MAAM,gBAAmB,GAAA,IAAA,CAAA;AAMlB,MAAM,kBAA6C,CAAA;AAAA,EACxD,OAAO,MAAS,GAAA;AACd,IAAA,MAAM,OAAOA,cAAW,CAAA;AAAA,MACtB,WAAa,EAAA,gBAAA;AAAA,MACb,aAAA,EAAe,CAAC,gBAAgB,CAAA;AAAA,MAChC,aAAe,EAAA;AAAA,QACb,WAAa,EAAA,KAAA;AAAA,OACf;AAAA,MACA,IAAI,EAAC;AAAA,MACL,SAAW,EAAA,KAAA;AAAA,MACX,UAAY,EAAA,KAAA;AAAA;AAAA,MAGZ,aAAe,EAAA,KAAA;AAAA,KAChB,CAAA,CAAA;AAED,IAAA,IAAA,CAAK,IAAK,EAAA,CAAA;AACV,IAAI,IAAA,CAAC,KAAK,aAAe,EAAA;AACvB,MAAM,MAAA,IAAI,MAAM,0CAA0C,CAAA,CAAA;AAAA,KAC5D;AAEA,IAAO,OAAA,IAAI,mBAAmB,IAAI,CAAA,CAAA;AAAA,GACpC;AAAA,EAEA,KAAA,CAAA;AAAA,EACA,eAAA,uBAAsB,GAAY,EAAA,CAAA;AAAA,EAE1B,YAAY,IAAY,EAAA;AAC9B,IAAA,IAAA,CAAK,KAAQ,GAAA,IAAA,CAAA;AAAA,GACf;AAAA,EAEA,eACE,cACgC,EAAA;AAChC,IAAM,MAAA,WAAA,GAAc,yBAAyB,cAAc,CAAA,CAAA;AAE3D,IAAA,IAAI,CAAC,IAAK,CAAA,eAAA,CAAgB,GAAI,CAAA,WAAA,CAAY,EAAE,CAAG,EAAA;AAC7C,MAAK,IAAA,CAAA,eAAA,CAAgB,GAAI,CAAA,WAAA,CAAY,EAAE,CAAA,CAAA;AACvC,MAAA,IAAA,CAAK,KAAM,CAAA,iBAAA;AAAA,QACT,gBAAA;AAAA,QACA,WAAY,CAAA,EAAA;AAAA,QACZ,YAAY,kBAAmB,EAAA;AAAA,QAC/B,KAAA;AAAA;AAAA,QACA,IAAA;AAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAM,MAAA,CAAA,GAAI,KAAK,KAAM,CAAA,SAAA;AAAA,MACnB,IAAA;AAAA,MACA,WAAY,CAAA,EAAA;AAAA,KACd,CAAA;AAEA,IAAO,OAAA;AAAA,MACL,KAAO,EAAA,IAAA;AAAA,MACP,CAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,YAEE,GAAA;AAEA,IAAO,OAAA,IAAI,eAA+C,CAAe,WAAA,KAAA;AACvE,MAAA,OAAO,MAAM;AAAA,OAAC,CAAA;AAAA,KACf,CAAA,CAAA;AAAA,GACH;AACF;;;;"}
@@ -0,0 +1,174 @@
1
+ import { ConfigReader } from '@backstage/config';
2
+ import { createApiFactory, analyticsApiRef, configApiRef, discoveryApiRef, identityApiRef, storageApiRef } from '@backstage/core-plugin-api';
3
+ import { translationApiRef } from '@backstage/core-plugin-api/alpha';
4
+ import { AuthorizeResult } from '@backstage/plugin-permission-common';
5
+ import { permissionApiRef } from '@backstage/plugin-permission-react';
6
+ import { MockPermissionApi } from './PermissionApi/MockPermissionApi.esm.js';
7
+ import { MockStorageApi } from './StorageApi/MockStorageApi.esm.js';
8
+ import { MockTranslationApi } from './TranslationApi/MockTranslationApi.esm.js';
9
+
10
+ function simpleFactory(ref, factory) {
11
+ return (...args) => createApiFactory({
12
+ api: ref,
13
+ deps: {},
14
+ factory: () => factory(...args)
15
+ });
16
+ }
17
+ function simpleMock(ref, mockFactory) {
18
+ return (partialImpl) => {
19
+ const mock = mockFactory();
20
+ if (partialImpl) {
21
+ for (const [key, impl] of Object.entries(partialImpl)) {
22
+ if (typeof impl === "function") {
23
+ mock[key].mockImplementation(impl);
24
+ } else {
25
+ mock[key] = impl;
26
+ }
27
+ }
28
+ }
29
+ return Object.assign(mock, {
30
+ factory: createApiFactory({
31
+ api: ref,
32
+ deps: {},
33
+ factory: () => mock
34
+ })
35
+ });
36
+ };
37
+ }
38
+ var mockApis;
39
+ ((mockApis2) => {
40
+ const analyticsMockSkeleton = () => ({
41
+ captureEvent: jest.fn()
42
+ });
43
+ function analytics() {
44
+ return analyticsMockSkeleton();
45
+ }
46
+ mockApis2.analytics = analytics;
47
+ ((analytics2) => {
48
+ analytics2.factory = simpleFactory(analyticsApiRef, analytics2);
49
+ analytics2.mock = simpleMock(analyticsApiRef, analyticsMockSkeleton);
50
+ })(analytics = mockApis2.analytics || (mockApis2.analytics = {}));
51
+ function config(options) {
52
+ return new ConfigReader(options?.data, "mock-config");
53
+ }
54
+ mockApis2.config = config;
55
+ ((config2) => {
56
+ config2.factory = simpleFactory(configApiRef, config2);
57
+ config2.mock = simpleMock(configApiRef, () => ({
58
+ has: jest.fn(),
59
+ keys: jest.fn(),
60
+ get: jest.fn(),
61
+ getOptional: jest.fn(),
62
+ getConfig: jest.fn(),
63
+ getOptionalConfig: jest.fn(),
64
+ getConfigArray: jest.fn(),
65
+ getOptionalConfigArray: jest.fn(),
66
+ getNumber: jest.fn(),
67
+ getOptionalNumber: jest.fn(),
68
+ getBoolean: jest.fn(),
69
+ getOptionalBoolean: jest.fn(),
70
+ getString: jest.fn(),
71
+ getOptionalString: jest.fn(),
72
+ getStringArray: jest.fn(),
73
+ getOptionalStringArray: jest.fn()
74
+ }));
75
+ })(config = mockApis2.config || (mockApis2.config = {}));
76
+ function discovery(options) {
77
+ const baseUrl = options?.baseUrl ?? "http://example.com";
78
+ return {
79
+ async getBaseUrl(pluginId) {
80
+ return `${baseUrl}/api/${pluginId}`;
81
+ }
82
+ };
83
+ }
84
+ mockApis2.discovery = discovery;
85
+ ((discovery2) => {
86
+ discovery2.factory = simpleFactory(discoveryApiRef, discovery2);
87
+ discovery2.mock = simpleMock(discoveryApiRef, () => ({
88
+ getBaseUrl: jest.fn()
89
+ }));
90
+ })(discovery = mockApis2.discovery || (mockApis2.discovery = {}));
91
+ function identity(options) {
92
+ const {
93
+ userEntityRef = "user:default/test",
94
+ ownershipEntityRefs = ["user:default/test"],
95
+ token,
96
+ email,
97
+ displayName,
98
+ picture
99
+ } = options ?? {};
100
+ return {
101
+ async getBackstageIdentity() {
102
+ return { type: "user", ownershipEntityRefs, userEntityRef };
103
+ },
104
+ async getCredentials() {
105
+ return { token };
106
+ },
107
+ async getProfileInfo() {
108
+ return { email, displayName, picture };
109
+ },
110
+ async signOut() {
111
+ }
112
+ };
113
+ }
114
+ mockApis2.identity = identity;
115
+ ((identity2) => {
116
+ identity2.factory = simpleFactory(identityApiRef, identity2);
117
+ identity2.mock = simpleMock(
118
+ identityApiRef,
119
+ () => ({
120
+ getBackstageIdentity: jest.fn(),
121
+ getCredentials: jest.fn(),
122
+ getProfileInfo: jest.fn(),
123
+ signOut: jest.fn()
124
+ })
125
+ );
126
+ })(identity = mockApis2.identity || (mockApis2.identity = {}));
127
+ function permission(options) {
128
+ const authorizeInput = options?.authorize;
129
+ let authorize;
130
+ if (authorizeInput === void 0) {
131
+ authorize = () => AuthorizeResult.ALLOW;
132
+ } else if (typeof authorizeInput === "function") {
133
+ authorize = authorizeInput;
134
+ } else {
135
+ authorize = () => authorizeInput;
136
+ }
137
+ return new MockPermissionApi(authorize);
138
+ }
139
+ mockApis2.permission = permission;
140
+ ((permission2) => {
141
+ permission2.factory = simpleFactory(permissionApiRef, permission2);
142
+ permission2.mock = simpleMock(permissionApiRef, () => ({
143
+ authorize: jest.fn()
144
+ }));
145
+ })(permission = mockApis2.permission || (mockApis2.permission = {}));
146
+ function storage(options) {
147
+ return MockStorageApi.create(options?.data);
148
+ }
149
+ mockApis2.storage = storage;
150
+ ((storage2) => {
151
+ storage2.factory = simpleFactory(storageApiRef, storage2);
152
+ storage2.mock = simpleMock(storageApiRef, () => ({
153
+ forBucket: jest.fn(),
154
+ set: jest.fn(),
155
+ remove: jest.fn(),
156
+ observe$: jest.fn(),
157
+ snapshot: jest.fn()
158
+ }));
159
+ })(storage = mockApis2.storage || (mockApis2.storage = {}));
160
+ function translation() {
161
+ return MockTranslationApi.create();
162
+ }
163
+ mockApis2.translation = translation;
164
+ ((translation2) => {
165
+ translation2.factory = simpleFactory(translationApiRef, translation2);
166
+ translation2.mock = simpleMock(translationApiRef, () => ({
167
+ getTranslation: jest.fn(),
168
+ translation$: jest.fn()
169
+ }));
170
+ })(translation = mockApis2.translation || (mockApis2.translation = {}));
171
+ })(mockApis || (mockApis = {}));
172
+
173
+ export { mockApis };
174
+ //# sourceMappingURL=mockApis.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mockApis.esm.js","sources":["../../../src/testUtils/apis/mockApis.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ConfigReader } from '@backstage/config';\nimport {\n AnalyticsApi,\n ApiFactory,\n ApiRef,\n ConfigApi,\n DiscoveryApi,\n IdentityApi,\n StorageApi,\n analyticsApiRef,\n configApiRef,\n createApiFactory,\n discoveryApiRef,\n identityApiRef,\n storageApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n TranslationApi,\n translationApiRef,\n} from '@backstage/core-plugin-api/alpha';\nimport {\n AuthorizeResult,\n EvaluatePermissionRequest,\n} from '@backstage/plugin-permission-common';\nimport {\n PermissionApi,\n permissionApiRef,\n} from '@backstage/plugin-permission-react';\nimport { JsonObject } from '@backstage/types';\nimport { ApiMock } from './ApiMock';\nimport { MockPermissionApi } from './PermissionApi';\nimport { MockStorageApi } from './StorageApi';\nimport { MockTranslationApi } from './TranslationApi';\n\n/** @internal */\nfunction simpleFactory<TApi, TArgs extends unknown[]>(\n ref: ApiRef<TApi>,\n factory: (...args: TArgs) => TApi,\n): (...args: TArgs) => ApiFactory<TApi, TApi, {}> {\n return (...args) =>\n createApiFactory({\n api: ref,\n deps: {},\n factory: () => factory(...args),\n });\n}\n\n/** @internal */\nfunction simpleMock<TApi>(\n ref: ApiRef<TApi>,\n mockFactory: () => jest.Mocked<TApi>,\n): (partialImpl?: Partial<TApi>) => ApiMock<TApi> {\n return partialImpl => {\n const mock = mockFactory();\n if (partialImpl) {\n for (const [key, impl] of Object.entries(partialImpl)) {\n if (typeof impl === 'function') {\n (mock as any)[key].mockImplementation(impl);\n } else {\n (mock as any)[key] = impl;\n }\n }\n }\n return Object.assign(mock, {\n factory: createApiFactory({\n api: ref,\n deps: {},\n factory: () => mock,\n }),\n }) as ApiMock<TApi>;\n };\n}\n\n/**\n * Mock implementations of the core utility APIs, to be used in tests.\n *\n * @public\n * @remarks\n *\n * There are some variations among the APIs depending on what needs tests\n * might have, but overall there are three main usage patterns:\n *\n * 1: Creating an actual fake API instance, often with a simplified version\n * of functionality, by calling the mock API itself as a function.\n *\n * ```ts\n * // The function often accepts parameters that control its behavior\n * const foo = mockApis.foo();\n * ```\n *\n * 2: Creating a mock API, where all methods are replaced with jest mocks, by\n * calling the API's `mock` function.\n *\n * ```ts\n * // You can optionally supply a subset of its methods to implement\n * const foo = mockApis.foo.mock({\n * someMethod: () => 'mocked result',\n * });\n * // After exercising your test, you can make assertions on the mock:\n * expect(foo.someMethod).toHaveBeenCalledTimes(2);\n * expect(foo.otherMethod).toHaveBeenCalledWith(testData);\n * ```\n *\n * 3: Creating an API factory that behaves similarly to the mock as per above.\n *\n * ```ts\n * const factory = mockApis.foo.factory({\n * someMethod: () => 'mocked result',\n * });\n * ```\n */\nexport namespace mockApis {\n const analyticsMockSkeleton = (): jest.Mocked<AnalyticsApi> => ({\n captureEvent: jest.fn(),\n });\n /**\n * Mock implementation of {@link @backstage/core-plugin-api#AnalyticsApi}.\n *\n * @public\n */\n export function analytics(): AnalyticsApi {\n return analyticsMockSkeleton();\n }\n /**\n * Mock implementations of {@link @backstage/core-plugin-api#AnalyticsApi}.\n *\n * @public\n */\n export namespace analytics {\n export const factory = simpleFactory(analyticsApiRef, analytics);\n export const mock = simpleMock(analyticsApiRef, analyticsMockSkeleton);\n }\n\n /**\n * Fake implementation of {@link @backstage/core-plugin-api#ConfigApi}\n * with optional data supplied.\n *\n * @public\n * @example\n *\n * ```tsx\n * const config = mockApis.config({\n * data: { app: { baseUrl: 'https://example.com' } },\n * });\n *\n * await renderInTestApp(\n * <TestApiProvider apis={[[configApiRef, config]]}>\n * <MyTestedComponent />\n * </TestApiProvider>,\n * );\n * ```\n */\n export function config(options?: { data?: JsonObject }): ConfigApi {\n return new ConfigReader(options?.data, 'mock-config');\n }\n /**\n * Mock helpers for {@link @backstage/core-plugin-api#ConfigApi}.\n *\n * @see {@link @backstage/core-plugin-api#mockApis.config}\n * @public\n */\n export namespace config {\n /**\n * Creates a factory for a fake implementation of\n * {@link @backstage/core-plugin-api#ConfigApi} with optional\n * configuration data supplied.\n *\n * @public\n */\n export const factory = simpleFactory(configApiRef, config);\n /**\n * Creates a mock implementation of\n * {@link @backstage/core-plugin-api#ConfigApi}. All methods are\n * replaced with jest mock functions, and you can optionally pass in a\n * subset of methods with an explicit implementation.\n *\n * @public\n */\n export const mock = simpleMock(configApiRef, () => ({\n has: jest.fn(),\n keys: jest.fn(),\n get: jest.fn(),\n getOptional: jest.fn(),\n getConfig: jest.fn(),\n getOptionalConfig: jest.fn(),\n getConfigArray: jest.fn(),\n getOptionalConfigArray: jest.fn(),\n getNumber: jest.fn(),\n getOptionalNumber: jest.fn(),\n getBoolean: jest.fn(),\n getOptionalBoolean: jest.fn(),\n getString: jest.fn(),\n getOptionalString: jest.fn(),\n getStringArray: jest.fn(),\n getOptionalStringArray: jest.fn(),\n }));\n }\n\n /**\n * Fake implementation of {@link @backstage/core-plugin-api#DiscoveryApi}. By\n * default returns URLs on the form `http://example.com/api/<pluginIs>`.\n *\n * @public\n */\n export function discovery(options?: { baseUrl?: string }): DiscoveryApi {\n const baseUrl = options?.baseUrl ?? 'http://example.com';\n return {\n async getBaseUrl(pluginId: string) {\n return `${baseUrl}/api/${pluginId}`;\n },\n };\n }\n /**\n * Mock implementations of {@link @backstage/core-plugin-api#DiscoveryApi}.\n *\n * @public\n */\n export namespace discovery {\n export const factory = simpleFactory(discoveryApiRef, discovery);\n export const mock = simpleMock(discoveryApiRef, () => ({\n getBaseUrl: jest.fn(),\n }));\n }\n\n /**\n * Fake implementation of {@link @backstage/core-plugin-api#IdentityApi}. By\n * default returns no token or profile info, and the user `user:default/test`.\n *\n * @public\n */\n export function identity(options?: {\n userEntityRef?: string;\n ownershipEntityRefs?: string[];\n token?: string;\n email?: string;\n displayName?: string;\n picture?: string;\n }): IdentityApi {\n const {\n userEntityRef = 'user:default/test',\n ownershipEntityRefs = ['user:default/test'],\n token,\n email,\n displayName,\n picture,\n } = options ?? {};\n return {\n async getBackstageIdentity() {\n return { type: 'user', ownershipEntityRefs, userEntityRef };\n },\n async getCredentials() {\n return { token };\n },\n async getProfileInfo() {\n return { email, displayName, picture };\n },\n async signOut() {},\n };\n }\n /**\n * Mock implementations of {@link @backstage/core-plugin-api#IdentityApi}.\n *\n * @public\n */\n export namespace identity {\n export const factory = simpleFactory(identityApiRef, identity);\n export const mock = simpleMock(\n identityApiRef,\n (): jest.Mocked<IdentityApi> => ({\n getBackstageIdentity: jest.fn(),\n getCredentials: jest.fn(),\n getProfileInfo: jest.fn(),\n signOut: jest.fn(),\n }),\n );\n }\n\n /**\n * Fake implementation of\n * {@link @backstage/plugin-permission-react#PermissionApi}. By default allows\n * all actions.\n *\n * @public\n */\n export function permission(options?: {\n authorize?:\n | AuthorizeResult.ALLOW\n | AuthorizeResult.DENY\n | ((\n request: EvaluatePermissionRequest,\n ) => AuthorizeResult.ALLOW | AuthorizeResult.DENY);\n }): PermissionApi {\n const authorizeInput = options?.authorize;\n let authorize: (\n request: EvaluatePermissionRequest,\n ) => AuthorizeResult.ALLOW | AuthorizeResult.DENY;\n if (authorizeInput === undefined) {\n authorize = () => AuthorizeResult.ALLOW;\n } else if (typeof authorizeInput === 'function') {\n authorize = authorizeInput;\n } else {\n authorize = () => authorizeInput;\n }\n return new MockPermissionApi(authorize);\n }\n /**\n * Mock implementation of\n * {@link @backstage/plugin-permission-react#PermissionApi}.\n *\n * @public\n */\n export namespace permission {\n export const factory = simpleFactory(permissionApiRef, permission);\n export const mock = simpleMock(permissionApiRef, () => ({\n authorize: jest.fn(),\n }));\n }\n\n /**\n * Fake implementation of {@link @backstage/core-plugin-api#StorageApi}.\n * Stores data temporarily in memory.\n *\n * @public\n */\n export function storage(options?: { data?: JsonObject }): StorageApi {\n return MockStorageApi.create(options?.data);\n }\n /**\n * Mock implementations of {@link @backstage/core-plugin-api#StorageApi}.\n *\n * @public\n */\n export namespace storage {\n export const factory = simpleFactory(storageApiRef, storage);\n export const mock = simpleMock(storageApiRef, () => ({\n forBucket: jest.fn(),\n set: jest.fn(),\n remove: jest.fn(),\n observe$: jest.fn(),\n snapshot: jest.fn(),\n }));\n }\n\n /**\n * Fake implementation of {@link @backstage/core-plugin-api/alpha#TranslationApi}.\n * By default returns the default translation.\n *\n * @public\n */\n export function translation(): TranslationApi {\n return MockTranslationApi.create();\n }\n /**\n * Mock implementations of {@link @backstage/core-plugin-api/alpha#TranslationApi}.\n *\n * @public\n */\n export namespace translation {\n export const factory = simpleFactory(translationApiRef, translation);\n export const mock = simpleMock(translationApiRef, () => ({\n getTranslation: jest.fn(),\n translation$: jest.fn(),\n }));\n }\n}\n"],"names":["mockApis","analytics","config","discovery","identity","permission","storage","translation"],"mappings":"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"}
@@ -5,6 +5,7 @@ import { MockErrorApi } from './apis/ErrorApi/MockErrorApi.esm.js';
5
5
  import { MockFetchApi } from './apis/FetchApi/MockFetchApi.esm.js';
6
6
  import '@backstage/plugin-permission-common';
7
7
  import { MockStorageApi } from './apis/StorageApi/MockStorageApi.esm.js';
8
+ import './apis/mockApis.esm.js';
8
9
  import { MockTranslationApi } from './apis/TranslationApi/MockTranslationApi.esm.js';
9
10
 
10
11
  const mockApis = [
@@ -1 +1 @@
1
- {"version":3,"file":"mockApis.esm.js","sources":["../../src/testUtils/mockApis.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createApiFactory,\n errorApiRef,\n fetchApiRef,\n storageApiRef,\n} from '@backstage/core-plugin-api';\nimport { translationApiRef } from '@backstage/core-plugin-api/alpha';\nimport { MockErrorApi, MockFetchApi, MockStorageApi } from './apis';\nimport { MockTranslationApi } from './apis/TranslationApi';\n\nexport const mockApis = [\n createApiFactory(errorApiRef, new MockErrorApi()),\n createApiFactory(fetchApiRef, new MockFetchApi()),\n createApiFactory(storageApiRef, MockStorageApi.create()),\n createApiFactory(translationApiRef, MockTranslationApi.create()),\n];\n"],"names":[],"mappings":";;;;;;;;;AA0BO,MAAM,QAAW,GAAA;AAAA,EACtB,gBAAiB,CAAA,WAAA,EAAa,IAAI,YAAA,EAAc,CAAA;AAAA,EAChD,gBAAiB,CAAA,WAAA,EAAa,IAAI,YAAA,EAAc,CAAA;AAAA,EAChD,gBAAiB,CAAA,aAAA,EAAe,cAAe,CAAA,MAAA,EAAQ,CAAA;AAAA,EACvD,gBAAiB,CAAA,iBAAA,EAAmB,kBAAmB,CAAA,MAAA,EAAQ,CAAA;AACjE;;;;"}
1
+ {"version":3,"file":"mockApis.esm.js","sources":["../../src/testUtils/mockApis.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createApiFactory,\n errorApiRef,\n fetchApiRef,\n storageApiRef,\n} from '@backstage/core-plugin-api';\nimport { translationApiRef } from '@backstage/core-plugin-api/alpha';\nimport { MockErrorApi, MockFetchApi, MockStorageApi } from './apis';\nimport { MockTranslationApi } from './apis/TranslationApi';\n\nexport const mockApis = [\n createApiFactory(errorApiRef, new MockErrorApi()),\n createApiFactory(fetchApiRef, new MockFetchApi()),\n createApiFactory(storageApiRef, MockStorageApi.create()),\n createApiFactory(translationApiRef, MockTranslationApi.create()),\n];\n"],"names":[],"mappings":";;;;;;;;;;AA0BO,MAAM,QAAW,GAAA;AAAA,EACtB,gBAAiB,CAAA,WAAA,EAAa,IAAI,YAAA,EAAc,CAAA;AAAA,EAChD,gBAAiB,CAAA,WAAA,EAAa,IAAI,YAAA,EAAc,CAAA;AAAA,EAChD,gBAAiB,CAAA,aAAA,EAAe,cAAe,CAAA,MAAA,EAAQ,CAAA;AAAA,EACvD,gBAAiB,CAAA,iBAAA,EAAmB,kBAAmB,CAAA,MAAA,EAAQ,CAAA;AACjE;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/test-utils",
3
- "version": "1.6.1-next.2",
3
+ "version": "1.7.1-next.0",
4
4
  "description": "Utilities to test Backstage plugins and apps.",
5
5
  "backstage": {
6
6
  "role": "web-library"
@@ -49,11 +49,11 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@backstage/config": "1.2.0",
52
- "@backstage/core-app-api": "1.15.1-next.1",
53
- "@backstage/core-plugin-api": "1.10.0-next.1",
52
+ "@backstage/core-app-api": "1.15.1",
53
+ "@backstage/core-plugin-api": "1.10.0",
54
54
  "@backstage/plugin-permission-common": "0.8.1",
55
- "@backstage/plugin-permission-react": "0.4.27-next.1",
56
- "@backstage/theme": "0.6.0-next.1",
55
+ "@backstage/plugin-permission-react": "0.4.27",
56
+ "@backstage/theme": "0.6.1-next.0",
57
57
  "@backstage/types": "1.1.1",
58
58
  "@material-ui/core": "^4.12.2",
59
59
  "@material-ui/icons": "^4.9.1",
@@ -62,8 +62,9 @@
62
62
  "zen-observable": "^0.10.0"
63
63
  },
64
64
  "devDependencies": {
65
- "@backstage/cli": "0.28.0-next.2",
65
+ "@backstage/cli": "0.29.0-next.1",
66
66
  "@testing-library/jest-dom": "^6.0.0",
67
+ "@types/jest": "*",
67
68
  "@types/react": "^18.0.0",
68
69
  "msw": "^1.0.0",
69
70
  "react": "^18.0.2",
@@ -72,12 +73,16 @@
72
73
  },
73
74
  "peerDependencies": {
74
75
  "@testing-library/react": "^16.0.0",
76
+ "@types/jest": "*",
75
77
  "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
76
78
  "react": "^16.13.1 || ^17.0.0 || ^18.0.0",
77
79
  "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0",
78
80
  "react-router-dom": "6.0.0-beta.0 || ^6.3.0"
79
81
  },
80
82
  "peerDependenciesMeta": {
83
+ "@types/jest": {
84
+ "optional": true
85
+ },
81
86
  "@types/react": {
82
87
  "optional": true
83
88
  }