Socket
Socket
Sign inDemoInstall

@backstage/frontend-test-utils

Package Overview
Dependencies
Maintainers
0
Versions
316
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@backstage/frontend-test-utils - npm Package Compare versions

Comparing version 0.0.0-nightly-20240801022222 to 0.0.0-nightly-20240802021846

dist/frontend-app-api/src/tree/instantiateAppNodeTree.esm.js

10

CHANGELOG.md
# @backstage/frontend-test-utils
## 0.0.0-nightly-20240801022222
## 0.0.0-nightly-20240802021846
### Patch Changes
- 8209449: Added new APIs for testing extensions
- 3be9aeb: Added support for v2 extensions, which declare their inputs and outputs without using a data map.
- 6349099: Added config input type to the extensions
- Updated dependencies
- @backstage/frontend-plugin-api@0.0.0-nightly-20240801022222
- @backstage/frontend-app-api@0.0.0-nightly-20240801022222
- @backstage/test-utils@0.0.0-nightly-20240801022222
- @backstage/frontend-plugin-api@0.0.0-nightly-20240802021846
- @backstage/frontend-app-api@0.0.0-nightly-20240802021846
- @backstage/config@1.2.0
- @backstage/test-utils@0.0.0-nightly-20240802021846
- @backstage/types@1.1.1

@@ -14,0 +16,0 @@

132

dist/app/createExtensionTester.esm.js

@@ -6,5 +6,9 @@ import React from 'react';

import { createExtension, createExtensionInput, createNavItemExtension, coreExtensionData, useRouteRef, createExtensionOverrides, createRouterExtension } from '@backstage/frontend-plugin-api';
import { MockConfigApi } from '@backstage/test-utils';
import { ConfigReader } from '@backstage/config';
import { resolveExtensionDefinition } from '../frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js';
import { toInternalExtensionDefinition } from '../frontend-plugin-api/src/wiring/createExtension.esm.js';
import { resolveAppTree } from '../frontend-app-api/src/tree/resolveAppTree.esm.js';
import { resolveAppNodeSpecs } from '../frontend-app-api/src/tree/resolveAppNodeSpecs.esm.js';
import { instantiateAppNodeTree } from '../frontend-app-api/src/tree/instantiateAppNodeTree.esm.js';
import { readAppExtensionsConfig } from '../frontend-app-api/src/tree/readAppExtensionsConfig.esm.js';

@@ -42,2 +46,23 @@ const NavItem = (props) => {

});
class ExtensionQuery {
#node;
constructor(node) {
this.#node = node;
}
get node() {
return this.#node;
}
get instance() {
const instance = this.#node.instance;
if (!instance) {
throw new Error(
`Unable to access the instance of extension with ID '${this.#node.spec.id}'`
);
}
return instance;
}
data(ref) {
return this.instance.getData(ref);
}
}
class ExtensionTester {

@@ -84,4 +109,10 @@ /** @internal */

}
#tree;
#extensions = new Array();
add(extension, options) {
if (this.#tree) {
throw new Error(
"Cannot add more extensions accessing the extension tree"
);
}
const { name, namespace } = extension;

@@ -93,5 +124,6 @@ const definition = {

};
const { id } = resolveExtensionDefinition(definition);
const resolvedExtension = resolveExtensionDefinition(definition);
this.#extensions.push({
id,
id: resolvedExtension.id,
extension: resolvedExtension,
definition,

@@ -102,5 +134,24 @@ config: options?.config

}
data(ref) {
const tree = this.#resolveTree();
return new ExtensionQuery(tree.root).data(ref);
}
query(id) {
const tree = this.#resolveTree();
const actualId = typeof id === "string" ? id : resolveExtensionDefinition(id).id;
const node = tree.nodes.get(actualId);
if (!node) {
throw new Error(
`Extension with ID '${actualId}' not found, please make sure it's added to the tester.`
);
} else if (!node.instance) {
throw new Error(
`Extension with ID '${actualId}' has not been instantiated, because it is not part of the test subject's extension tree.`
);
}
return new ExtensionQuery(node);
}
render(options) {
const { config = {} } = options ?? {};
const [subject, ...rest] = this.#extensions;
const [subject] = this.#extensions;
if (!subject) {

@@ -111,22 +162,2 @@ throw new Error(

}
const extensionsConfig = [
...rest.map((extension) => ({
[extension.id]: {
config: extension.config
}
})),
{
[subject.id]: {
config: subject.config,
disabled: false
}
}
];
const finalConfig = {
...config,
app: {
...typeof config.app === "object" ? config.app : void 0,
extensions: extensionsConfig
}
};
const app = createSpecializedApp({

@@ -145,6 +176,55 @@ features: [

],
config: new MockConfigApi(finalConfig)
config: this.#getConfig(config)
});
return render(app.createRoot());
}
#resolveTree() {
if (this.#tree) {
return this.#tree;
}
const [subject] = this.#extensions;
if (!subject) {
throw new Error(
"No subject found. At least one extension should be added to the tester."
);
}
const tree = resolveAppTree(
subject.id,
resolveAppNodeSpecs({
features: [],
builtinExtensions: this.#extensions.map((_) => _.extension),
parameters: readAppExtensionsConfig(this.#getConfig())
})
);
instantiateAppNodeTree(tree.root);
this.#tree = tree;
return tree;
}
#getConfig(additionalConfig) {
const [subject, ...rest] = this.#extensions;
const extensionsConfig = [
...rest.map((extension) => ({
[extension.id]: {
config: extension.config
}
})),
{
[subject.id]: {
config: subject.config,
disabled: false
}
}
];
return ConfigReader.fromConfigs([
{ context: "render-config", data: additionalConfig ?? {} },
{
context: "test",
data: {
app: {
extensions: extensionsConfig
}
}
}
]);
}
}

@@ -155,3 +235,3 @@ function createExtensionTester(subject, options) {

export { ExtensionTester, createExtensionTester };
export { ExtensionQuery, ExtensionTester, createExtensionTester };
//# sourceMappingURL=createExtensionTester.esm.js.map
import { toInternalExtensionDefinition } from './createExtension.esm.js';
function toInternalExtension(overrides) {
const internal = overrides;
if (internal.$$type !== "@backstage/Extension") {
throw new Error(
`Invalid extension instance, bad type '${internal.$$type}'`
);
}
const version = internal.version;
if (version !== "v1" && version !== "v2") {
throw new Error(`Invalid extension instance, bad version '${version}'`);
}
return internal;
}
function resolveExtensionDefinition(definition, context) {

@@ -25,3 +38,3 @@ const internalDefinition = toInternalExtensionDefinition(definition);

export { resolveExtensionDefinition };
export { resolveExtensionDefinition, toInternalExtension };
//# sourceMappingURL=resolveExtensionDefinition.esm.js.map
/// <reference types="react" />
export { ErrorWithContext, MockConfigApi, MockErrorApi, MockErrorApiOptions, MockFetchApi, MockFetchApiOptions, MockPermissionApi, MockStorageApi, MockStorageBucket, TestApiProvider, TestApiProviderProps, TestApiRegistry, registerMswTestHooks, withLogCollector } from '@backstage/test-utils';
import { AnalyticsApi, AnalyticsEvent, ExtensionDefinition, RouteRef } from '@backstage/frontend-plugin-api';
import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
import { AnalyticsApi, AnalyticsEvent, AppNode, ExtensionDataRef, ExtensionDefinition, RouteRef } from '@backstage/frontend-plugin-api';
import * as _testing_library_react from '@testing-library/react';

@@ -31,2 +32,10 @@ import { RenderResult } from '@testing-library/react';

/** @public */
declare class ExtensionQuery {
#private;
constructor(node: AppNode);
get node(): AppNode;
get instance(): _backstage_frontend_plugin_api.AppNodeInstance;
data<T>(ref: ExtensionDataRef<T>): T | undefined;
}
/** @public */
declare class ExtensionTester {

@@ -37,2 +46,4 @@ #private;

}): ExtensionTester;
data<T>(ref: ExtensionDataRef<T>): T | undefined;
query(id: string | ExtensionDefinition<any, any>): ExtensionQuery;
render(options?: {

@@ -78,2 +89,2 @@ config?: JsonObject;

export { ExtensionTester, MockAnalyticsApi, type TestAppOptions, createExtensionTester, renderInTestApp, setupRequestMockHandlers };
export { ExtensionQuery, ExtensionTester, MockAnalyticsApi, type TestAppOptions, createExtensionTester, renderInTestApp, setupRequestMockHandlers };
{
"name": "@backstage/frontend-test-utils",
"version": "0.0.0-nightly-20240801022222",
"version": "0.0.0-nightly-20240802021846",
"backstage": {

@@ -34,9 +34,10 @@ "role": "web-library"

"dependencies": {
"@backstage/frontend-app-api": "^0.0.0-nightly-20240801022222",
"@backstage/frontend-plugin-api": "^0.0.0-nightly-20240801022222",
"@backstage/test-utils": "^0.0.0-nightly-20240801022222",
"@backstage/config": "^1.2.0",
"@backstage/frontend-app-api": "^0.0.0-nightly-20240802021846",
"@backstage/frontend-plugin-api": "^0.0.0-nightly-20240802021846",
"@backstage/test-utils": "^0.0.0-nightly-20240802021846",
"@backstage/types": "^1.1.1"
},
"devDependencies": {
"@backstage/cli": "^0.0.0-nightly-20240801022222",
"@backstage/cli": "^0.0.0-nightly-20240802021846",
"@testing-library/jest-dom": "^6.0.0",

@@ -43,0 +44,0 @@ "@types/react": "*"

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc