Socket
Socket
Sign inDemoInstall

@backstage/frontend-test-utils

Package Overview
Dependencies
Maintainers
0
Versions
318
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.1.12-next.1 to 0.1.12-next.2

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

13

CHANGELOG.md
# @backstage/frontend-test-utils
## 0.1.12-next.2
### Patch Changes
- 8209449: Added new APIs for testing extensions
- 72754db: Updated usage of `useRouteRef`, which can now always return `undefined`.
- Updated dependencies
- @backstage/frontend-plugin-api@0.7.0-next.2
- @backstage/frontend-app-api@0.7.5-next.2
- @backstage/test-utils@1.5.10-next.2
- @backstage/config@1.2.0
- @backstage/types@1.1.1
## 0.1.12-next.1

@@ -4,0 +17,0 @@

139

dist/app/createExtensionTester.esm.js

@@ -6,10 +6,17 @@ 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';
const NavItem = (props) => {
const { routeRef, title, icon: Icon } = props;
const to = useRouteRef(routeRef)();
return /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link, { to }, /* @__PURE__ */ React.createElement(Icon, null), " ", title));
const link = useRouteRef(routeRef);
if (!link) {
return null;
}
return /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link, { to: link() }, /* @__PURE__ */ React.createElement(Icon, null), " ", title));
};

@@ -42,2 +49,23 @@ const TestAppNavExtension = createExtension({

});
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 +112,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 +127,6 @@ const definition = {

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

@@ -102,5 +137,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 +165,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 +179,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 +238,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.1.12-next.1",
"version": "0.1.12-next.2",
"backstage": {

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

"dependencies": {
"@backstage/frontend-app-api": "^0.7.5-next.1",
"@backstage/frontend-plugin-api": "^0.6.8-next.1",
"@backstage/test-utils": "^1.5.10-next.1",
"@backstage/config": "^1.2.0",
"@backstage/frontend-app-api": "^0.7.5-next.2",
"@backstage/frontend-plugin-api": "^0.7.0-next.2",
"@backstage/test-utils": "^1.5.10-next.2",
"@backstage/types": "^1.1.1"
},
"devDependencies": {
"@backstage/cli": "^0.27.0-next.1",
"@backstage/cli": "^0.27.0-next.3",
"@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

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