Merge branch 'master' into plugin-azure-functions

Signed-off-by: Wesley Pattison <wesley.pattison@friss.com>
This commit is contained in:
Wesley Pattison
2022-09-26 12:07:14 +02:00
336 changed files with 9035 additions and 7795 deletions
+7 -7
View File
@@ -32,11 +32,11 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/core-app-api": "^1.1.0",
"@backstage/core-components": "^0.11.1",
"@backstage/core-plugin-api": "^1.0.6",
"@backstage/plugin-permission-react": "^0.4.5",
"@backstage/theme": "^0.2.16",
"@backstage/core-app-api": "workspace:^",
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/plugin-permission-react": "workspace:^",
"@backstage/theme": "workspace:^",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1"
},
@@ -47,8 +47,8 @@
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/test-utils": "^1.2.0",
"@backstage/cli": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@types/node": "^16.11.26",
+58 -58
View File
@@ -7,63 +7,63 @@
},
"bundled": true,
"dependencies": {
"@backstage/app-defaults": "^1.0.6",
"@backstage/catalog-model": "^1.1.1",
"@backstage/cli": "^0.19.0",
"@backstage/config": "^1.0.2",
"@backstage/core-app-api": "^1.1.0",
"@backstage/core-components": "^0.11.1",
"@backstage/core-plugin-api": "^1.0.6",
"@backstage/integration-react": "^1.1.4",
"@backstage/plugin-airbrake": "^0.3.9",
"@backstage/plugin-apache-airflow": "^0.2.2",
"@backstage/plugin-api-docs": "^0.8.9",
"@backstage/plugin-azure-devops": "^0.2.0",
"@backstage/plugin-azure-functions": "^0.0.0",
"@backstage/plugin-badges": "^0.2.33",
"@backstage/plugin-catalog-common": "^1.0.6",
"@backstage/plugin-catalog-graph": "^0.2.21",
"@backstage/plugin-catalog-import": "^0.8.12",
"@backstage/plugin-catalog-react": "^1.1.4",
"@backstage/plugin-circleci": "^0.3.9",
"@backstage/plugin-cloudbuild": "^0.3.9",
"@backstage/plugin-code-coverage": "^0.2.2",
"@backstage/plugin-cost-insights": "^0.11.31",
"@backstage/plugin-dynatrace": "^0.2.0",
"@backstage/plugin-explore": "^0.3.40",
"@backstage/plugin-gcalendar": "^0.3.5",
"@backstage/plugin-gcp-projects": "^0.3.28",
"@backstage/plugin-github-actions": "^0.5.9",
"@backstage/plugin-gocd": "^0.1.15",
"@backstage/plugin-graphiql": "^0.2.41",
"@backstage/plugin-home": "^0.4.25",
"@backstage/plugin-jenkins": "^0.7.8",
"@backstage/plugin-kafka": "^0.3.9",
"@backstage/plugin-kubernetes": "^0.7.2",
"@backstage/plugin-lighthouse": "^0.3.9",
"@backstage/plugin-newrelic": "^0.3.27",
"@backstage/plugin-newrelic-dashboard": "^0.2.2",
"@backstage/plugin-org": "^0.5.9",
"@backstage/plugin-pagerduty": "0.5.2",
"@backstage/plugin-permission-react": "^0.4.5",
"@backstage/plugin-playlist": "^0.1.0",
"@backstage/plugin-rollbar": "^0.4.9",
"@backstage/plugin-scaffolder": "^1.6.0",
"@backstage/plugin-search": "^1.0.2",
"@backstage/plugin-search-common": "^1.0.1",
"@backstage/plugin-search-react": "^1.1.0",
"@backstage/plugin-sentry": "^0.4.2",
"@backstage/plugin-shortcuts": "^0.3.1",
"@backstage/plugin-stack-overflow": "^0.1.5",
"@backstage/plugin-tech-insights": "^0.3.0",
"@backstage/plugin-tech-radar": "^0.5.16",
"@backstage/plugin-techdocs": "^1.3.2",
"@backstage/plugin-techdocs-module-addons-contrib": "^1.0.4",
"@backstage/plugin-techdocs-react": "^1.0.4",
"@backstage/plugin-todo": "^0.2.11",
"@backstage/plugin-user-settings": "^0.4.8",
"@backstage/theme": "^0.2.16",
"@internal/plugin-catalog-customized": "0.0.2",
"@backstage/app-defaults": "workspace:^",
"@backstage/catalog-model": "workspace:^",
"@backstage/cli": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/integration-react": "workspace:^",
"@backstage/plugin-airbrake": "workspace:^",
"@backstage/plugin-apache-airflow": "workspace:^",
"@backstage/plugin-api-docs": "workspace:^",
"@backstage/plugin-azure-devops": "workspace:^",
"@backstage/plugin-azure-functions": "workspace:^",
"@backstage/plugin-badges": "workspace:^",
"@backstage/plugin-catalog-common": "workspace:^",
"@backstage/plugin-catalog-graph": "workspace:^",
"@backstage/plugin-catalog-import": "workspace:^",
"@backstage/plugin-catalog-react": "workspace:^",
"@backstage/plugin-circleci": "workspace:^",
"@backstage/plugin-cloudbuild": "workspace:^",
"@backstage/plugin-code-coverage": "workspace:^",
"@backstage/plugin-cost-insights": "workspace:^",
"@backstage/plugin-dynatrace": "workspace:^",
"@backstage/plugin-explore": "workspace:^",
"@backstage/plugin-gcalendar": "workspace:^",
"@backstage/plugin-gcp-projects": "workspace:^",
"@backstage/plugin-github-actions": "workspace:^",
"@backstage/plugin-gocd": "workspace:^",
"@backstage/plugin-graphiql": "workspace:^",
"@backstage/plugin-home": "workspace:^",
"@backstage/plugin-jenkins": "workspace:^",
"@backstage/plugin-kafka": "workspace:^",
"@backstage/plugin-kubernetes": "workspace:^",
"@backstage/plugin-lighthouse": "workspace:^",
"@backstage/plugin-newrelic": "workspace:^",
"@backstage/plugin-newrelic-dashboard": "workspace:^",
"@backstage/plugin-org": "workspace:^",
"@backstage/plugin-pagerduty": "workspace:^",
"@backstage/plugin-permission-react": "workspace:^",
"@backstage/plugin-playlist": "workspace:^",
"@backstage/plugin-rollbar": "workspace:^",
"@backstage/plugin-scaffolder": "workspace:^",
"@backstage/plugin-search": "workspace:^",
"@backstage/plugin-search-common": "workspace:^",
"@backstage/plugin-search-react": "workspace:^",
"@backstage/plugin-sentry": "workspace:^",
"@backstage/plugin-shortcuts": "workspace:^",
"@backstage/plugin-stack-overflow": "workspace:^",
"@backstage/plugin-tech-insights": "workspace:^",
"@backstage/plugin-tech-radar": "workspace:^",
"@backstage/plugin-techdocs": "workspace:^",
"@backstage/plugin-techdocs-module-addons-contrib": "workspace:^",
"@backstage/plugin-techdocs-react": "workspace:^",
"@backstage/plugin-todo": "workspace:^",
"@backstage/plugin-user-settings": "workspace:^",
"@backstage/theme": "workspace:^",
"@internal/plugin-catalog-customized": "workspace:^",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
@@ -82,7 +82,7 @@
"zen-observable": "^0.8.15"
},
"devDependencies": {
"@backstage/test-utils": "^1.2.0",
"@backstage/test-utils": "workspace:^",
"@rjsf/core": "^3.2.1",
"@testing-library/cypress": "^8.0.2",
"@testing-library/jest-dom": "^5.10.1",
+1 -1
View File
@@ -148,7 +148,7 @@ const AppRouter = app.getRouter();
const routes = (
<FlatRoutes>
<Navigate key="/" to="catalog" />
<Route path="/" element={<Navigate to="/catalog" />} />
{/* TODO(rubenl): Move this to / once its more mature and components exist */}
<Route path="/home" element={<HomepageCompositionRoot />}>
{homePage}
@@ -28,7 +28,6 @@ const TwoColumn: LayoutTemplate = ({ properties, description, title }) => {
return (
<>
<h1>{title}</h1>
<h2>In two column layout!!</h2>
<Grid container justifyContent="flex-end">
{left.map(prop => (
<Grid item xs={6} key={prop.content.key}>
+6 -6
View File
@@ -33,17 +33,17 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/backend-common": "^0.15.1",
"@backstage/backend-plugin-api": "^0.1.2",
"@backstage/backend-tasks": "^0.3.5",
"@backstage/errors": "^1.1.1",
"@backstage/plugin-permission-node": "^0.6.5",
"@backstage/backend-common": "workspace:^",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/backend-tasks": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/plugin-permission-node": "workspace:^",
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/cli": "^0.19.0"
"@backstage/cli": "workspace:^"
},
"files": [
"dist",
+8 -8
View File
@@ -34,12 +34,12 @@
"test:kubernetes": "backstage-cli package test -t KubernetesContainerRunner --no-watch"
},
"dependencies": {
"@backstage/cli-common": "^0.1.10",
"@backstage/config": "^1.0.2",
"@backstage/config-loader": "^1.1.4",
"@backstage/errors": "^1.1.1",
"@backstage/integration": "^1.3.1",
"@backstage/types": "^1.0.0",
"@backstage/cli-common": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/config-loader": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/types": "workspace:^",
"@google-cloud/storage": "^6.0.0",
"@keyv/redis": "^2.2.3",
"@kubernetes/client-node": "^0.17.0",
@@ -94,8 +94,8 @@
}
},
"devDependencies": {
"@backstage/backend-test-utils": "^0.1.28",
"@backstage/cli": "^0.19.0",
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@types/archiver": "^5.1.0",
"@types/base64-stream": "^1.0.2",
"@types/compression": "^1.7.0",
+3 -3
View File
@@ -32,11 +32,11 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/backend-app-api": "^0.2.1",
"@backstage/backend-plugin-api": "^0.1.2"
"@backstage/backend-app-api": "workspace:^",
"@backstage/backend-plugin-api": "workspace:^"
},
"devDependencies": {
"@backstage/cli": "^0.19.0"
"@backstage/cli": "workspace:^"
},
"files": [
"dist"
+4 -4
View File
@@ -25,12 +25,12 @@
"clean": "backstage-cli package clean"
},
"dependencies": {
"@backstage/backend-defaults": "^0.1.1",
"@backstage/plugin-catalog-backend": "^1.4.0",
"@backstage/plugin-scaffolder-backend": "^1.6.0"
"@backstage/backend-defaults": "workspace:^",
"@backstage/plugin-catalog-backend": "workspace:^",
"@backstage/plugin-scaffolder-backend": "workspace:^"
},
"devDependencies": {
"@backstage/cli": "^0.19.0"
"@backstage/cli": "workspace:^"
},
"files": [
"dist"
+5 -5
View File
@@ -33,17 +33,17 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/backend-common": "^0.15.1",
"@backstage/backend-tasks": "^0.3.5",
"@backstage/config": "^1.0.2",
"@backstage/plugin-permission-common": "^0.6.4",
"@backstage/backend-common": "workspace:^",
"@backstage/backend-tasks": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
"@types/express": "^4.17.6",
"express": "^4.17.1",
"winston": "^3.2.1",
"winston-transport": "^4.5.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0"
"@backstage/cli": "workspace:^"
},
"files": [
"dist",
+6 -6
View File
@@ -32,10 +32,10 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/backend-common": "^0.15.1",
"@backstage/config": "^1.0.2",
"@backstage/errors": "^1.1.1",
"@backstage/types": "^1.0.0",
"@backstage/backend-common": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/types": "workspace:^",
"@types/luxon": "^3.0.0",
"cron": "^2.0.0",
"knex": "^2.0.0",
@@ -47,8 +47,8 @@
"zod": "^3.9.5"
},
"devDependencies": {
"@backstage/backend-test-utils": "^0.1.28",
"@backstage/cli": "^0.19.0",
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@types/cron": "^2.0.0",
"wait-for-expect": "^3.0.2"
},
@@ -25,8 +25,6 @@ import {
PluginTaskSchedulerImpl,
} from './PluginTaskSchedulerImpl';
jest.useFakeTimers();
function defer() {
let resolve = () => {};
const promise = new Promise<void>(_resolve => {
@@ -40,6 +38,15 @@ describe('PluginTaskManagerImpl', () => {
ids: ['POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'],
});
beforeAll(async () => {
// Make sure all databases are running before mocking timers, in case of testcontainers
await Promise.all(
databases.eachSupportedId().map(([id]) => databases.init(id)),
);
jest.useFakeTimers();
}, 60_000);
async function init(databaseId: TestDatabaseId) {
const knex = await databases.init(databaseId);
await migrateBackendTasks(knex);
+6 -6
View File
@@ -34,11 +34,11 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/backend-app-api": "^0.2.1",
"@backstage/backend-common": "^0.15.1",
"@backstage/backend-plugin-api": "^0.1.2",
"@backstage/cli": "^0.19.0",
"@backstage/config": "^1.0.2",
"@backstage/backend-app-api": "workspace:^",
"@backstage/backend-common": "workspace:^",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/cli": "workspace:^",
"@backstage/config": "workspace:^",
"better-sqlite3": "^7.5.0",
"knex": "^2.0.0",
"msw": "^0.47.0",
@@ -48,7 +48,7 @@
"uuid": "^8.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0"
"@backstage/cli": "workspace:^"
},
"files": [
"dist",
@@ -28,6 +28,13 @@ import {
TestDatabaseProperties,
} from './types';
const LARGER_POOL_CONFIG = {
pool: {
min: 0,
max: 50,
},
};
/**
* Encapsulates the creation of ephemeral test database instances for use
* inside unit or integration tests.
@@ -164,6 +171,9 @@ export class TestDatabases {
new ConfigReader({
backend: {
database: {
knexConfig: properties.driver.includes('sqlite')
? {}
: LARGER_POOL_CONFIG,
client: properties.driver,
connection: connectionString,
},
@@ -203,6 +213,7 @@ export class TestDatabases {
new ConfigReader({
backend: {
database: {
knexConfig: LARGER_POOL_CONFIG,
client: 'pg',
connection: { host, port, user, password },
},
@@ -228,6 +239,7 @@ export class TestDatabases {
new ConfigReader({
backend: {
database: {
knexConfig: LARGER_POOL_CONFIG,
client: 'mysql2',
connection: { host, port, user, password },
},
+37 -37
View File
@@ -26,42 +26,42 @@
"build-image": "docker build ../.. -f Dockerfile --tag example-backend"
},
"dependencies": {
"@backstage/backend-common": "^0.15.1",
"@backstage/backend-tasks": "^0.3.5",
"@backstage/catalog-client": "^1.1.0",
"@backstage/catalog-model": "^1.1.1",
"@backstage/config": "^1.0.2",
"@backstage/integration": "^1.3.1",
"@backstage/plugin-app-backend": "^0.3.36",
"@backstage/plugin-auth-backend": "^0.16.0",
"@backstage/plugin-auth-node": "^0.2.5",
"@backstage/plugin-azure-devops-backend": "^0.3.15",
"@backstage/plugin-azure-functions-backend": "^0.0.0",
"@backstage/plugin-badges-backend": "^0.1.30",
"@backstage/plugin-catalog-backend": "^1.4.0",
"@backstage/plugin-code-coverage-backend": "^0.2.2",
"@backstage/plugin-graphql-backend": "^0.1.26",
"@backstage/plugin-jenkins-backend": "^0.1.26",
"@backstage/plugin-kafka-backend": "^0.2.29",
"@backstage/plugin-kubernetes-backend": "^0.7.2",
"@backstage/plugin-permission-backend": "^0.5.11",
"@backstage/plugin-permission-common": "^0.6.4",
"@backstage/plugin-permission-node": "^0.6.5",
"@backstage/plugin-playlist-backend": "^0.1.0",
"@backstage/plugin-proxy-backend": "^0.2.30",
"@backstage/plugin-rollbar-backend": "^0.1.33",
"@backstage/plugin-scaffolder-backend": "^1.6.0",
"@backstage/plugin-scaffolder-backend-module-rails": "^0.4.4",
"@backstage/plugin-search-backend": "^1.0.2",
"@backstage/plugin-search-backend-module-elasticsearch": "^1.0.2",
"@backstage/plugin-search-backend-module-pg": "^0.4.0",
"@backstage/plugin-search-backend-node": "^1.0.2",
"@backstage/plugin-search-common": "^1.0.1",
"@backstage/plugin-tech-insights-backend": "^0.5.2",
"@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.20",
"@backstage/plugin-tech-insights-node": "^0.3.4",
"@backstage/plugin-techdocs-backend": "^1.3.0",
"@backstage/plugin-todo-backend": "^0.1.33",
"@backstage/backend-common": "workspace:^",
"@backstage/backend-tasks": "workspace:^",
"@backstage/catalog-client": "workspace:^",
"@backstage/catalog-model": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/plugin-app-backend": "workspace:^",
"@backstage/plugin-auth-backend": "workspace:^",
"@backstage/plugin-auth-node": "workspace:^",
"@backstage/plugin-azure-devops-backend": "workspace:^",
"@backstage/plugin-azure-functions-backend": "workspace:^",
"@backstage/plugin-badges-backend": "workspace:^",
"@backstage/plugin-catalog-backend": "workspace:^",
"@backstage/plugin-code-coverage-backend": "workspace:^",
"@backstage/plugin-graphql-backend": "workspace:^",
"@backstage/plugin-jenkins-backend": "workspace:^",
"@backstage/plugin-kafka-backend": "workspace:^",
"@backstage/plugin-kubernetes-backend": "workspace:^",
"@backstage/plugin-permission-backend": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
"@backstage/plugin-permission-node": "workspace:^",
"@backstage/plugin-playlist-backend": "workspace:^",
"@backstage/plugin-proxy-backend": "workspace:^",
"@backstage/plugin-rollbar-backend": "workspace:^",
"@backstage/plugin-scaffolder-backend": "workspace:^",
"@backstage/plugin-scaffolder-backend-module-rails": "workspace:^",
"@backstage/plugin-search-backend": "workspace:^",
"@backstage/plugin-search-backend-module-elasticsearch": "workspace:^",
"@backstage/plugin-search-backend-module-pg": "workspace:^",
"@backstage/plugin-search-backend-node": "workspace:^",
"@backstage/plugin-search-common": "workspace:^",
"@backstage/plugin-tech-insights-backend": "workspace:^",
"@backstage/plugin-tech-insights-backend-module-jsonfc": "workspace:^",
"@backstage/plugin-tech-insights-node": "workspace:^",
"@backstage/plugin-techdocs-backend": "workspace:^",
"@backstage/plugin-todo-backend": "workspace:^",
"@gitbeaker/node": "^35.1.0",
"@octokit/rest": "^19.0.3",
"azure-devops-node-api": "^11.0.1",
@@ -78,7 +78,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"@types/dockerode": "^3.3.0",
"@types/express": "^4.17.6",
"@types/express-serve-static-core": "^4.17.5",
@@ -33,5 +33,6 @@ export default async function createPlugin(
catalogClient: catalogClient,
reader: env.reader,
identity: env.identity,
scheduler: env.scheduler,
});
}
+3 -3
View File
@@ -32,12 +32,12 @@
"clean": "backstage-cli package clean"
},
"dependencies": {
"@backstage/catalog-model": "^1.1.1",
"@backstage/errors": "^1.1.1",
"@backstage/catalog-model": "workspace:^",
"@backstage/errors": "workspace:^",
"cross-fetch": "^3.1.5"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"msw": "^0.47.0"
},
"files": [
+4 -4
View File
@@ -33,16 +33,16 @@
"clean": "backstage-cli package clean"
},
"dependencies": {
"@backstage/config": "^1.0.2",
"@backstage/errors": "^1.1.1",
"@backstage/types": "^1.0.0",
"@backstage/config": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/types": "workspace:^",
"ajv": "^8.10.0",
"json-schema": "^0.4.0",
"lodash": "^4.17.21",
"uuid": "^8.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"@types/json-schema": "^7.0.5",
"@types/lodash": "^4.14.151",
"yaml": "^2.0.0"
+4 -1
View File
@@ -22,9 +22,12 @@ import { KindValidator } from './types';
// exported kind validators have the `KindValidator` signature which is
// different. So let's postpone that change until a later time.
export function ajvCompiledJsonSchemaValidator(schema: unknown): KindValidator {
const validator = entityKindSchemaValidator(schema);
let validator: undefined | ((data: unknown) => any);
return {
async check(data) {
if (!validator) {
validator = entityKindSchemaValidator(schema);
}
return validator(data) === data;
},
};
+1 -1
View File
@@ -32,7 +32,7 @@
"start": "backstage-cli package start"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"@types/node": "^16.0.0"
},
"files": [
+18 -8
View File
@@ -276,7 +276,7 @@ Usage: backstage-cli [--config=<pathToConfigFile>] [TestPathPattern]
Options:
-h, --help
-v, --version
--version
--all
--automock
-b, --bail
@@ -289,7 +289,6 @@ Options:
--clearMocks
--collectCoverage
--collectCoverageFrom
--collectCoverageOnlyFrom
--color
--colors
-c, --config
@@ -312,6 +311,7 @@ Options:
--globalTeardown
--globals
--haste
--ignoreProjects
--init
--injectGlobals
--json
@@ -348,6 +348,7 @@ Options:
--selectProjects
--setupFiles
--setupFilesAfterEnv
--shard
--showConfig
--silent
--skipFilter
@@ -365,8 +366,6 @@ Options:
--testRunner
--testSequencer
--testTimeout
--testURL
--timers
--transform
--transformIgnorePatterns
--unmockedModulePathPatterns
@@ -391,6 +390,7 @@ Commands:
build [options]
lint [options]
clean
test [options]
help [command]
```
@@ -426,6 +426,17 @@ Options:
-h, --help
```
### `backstage-cli repo test`
```
Usage: backstage-cli repo test [options]
Options:
--since <ref>
--jest-help
-h, --help
```
### `backstage-cli test`
```
@@ -433,7 +444,7 @@ Usage: backstage-cli [--config=<pathToConfigFile>] [TestPathPattern]
Options:
-h, --help
-v, --version
--version
--all
--automock
-b, --bail
@@ -446,7 +457,6 @@ Options:
--clearMocks
--collectCoverage
--collectCoverageFrom
--collectCoverageOnlyFrom
--color
--colors
-c, --config
@@ -469,6 +479,7 @@ Options:
--globalTeardown
--globals
--haste
--ignoreProjects
--init
--injectGlobals
--json
@@ -505,6 +516,7 @@ Options:
--selectProjects
--setupFiles
--setupFilesAfterEnv
--shard
--showConfig
--silent
--skipFilter
@@ -522,8 +534,6 @@ Options:
--testRunner
--testSequencer
--testTimeout
--testURL
--timers
--transform
--transformIgnorePatterns
--unmockedModulePathPatterns
+6 -7
View File
@@ -27,7 +27,6 @@ const envOptions = {
const transformIgnorePattern = [
'@material-ui',
'@rjsf',
'ajv',
'core-js',
'jest-.*',
@@ -189,13 +188,13 @@ async function getProjectConfig(targetPath, displayName) {
],
'\\.(bmp|gif|jpg|jpeg|png|frag|xml|svg|eot|woff|woff2|ttf)$':
require.resolve('./jestFileTransform.js'),
'\\.(yaml)$': require.resolve('jest-transform-yaml'),
'\\.(yaml)$': require.resolve('./jestYamlTransform'),
},
// A bit more opinionated
testMatch: ['**/*.test.{js,jsx,ts,tsx,mjs,cjs}'],
moduleLoader: envOptions.nextTests
runtime: envOptions.nextTests
? require.resolve('./jestCachingModuleLoader')
: undefined,
@@ -210,16 +209,16 @@ async function getProjectConfig(targetPath, displayName) {
const config = Object.assign(options, ...pkgJsonConfigs);
// The config name is a cache key that lets us share the jest cache across projects.
// If no explicit name was configured, generated one based on the configuration.
if (!config.name) {
// The config id is a cache key that lets us share the jest cache across projects.
// If no explicit id was configured, generated one based on the configuration.
if (!config.id) {
const configHash = crypto
.createHash('md5')
.update(version)
.update(Buffer.alloc(1))
.update(JSON.stringify(config.transform))
.digest('hex');
config.name = `backstage_cli_${configHash}`;
config.id = `backstage_cli_${configHash}`;
}
return config;
+5 -3
View File
@@ -21,7 +21,8 @@ module.exports = {
const assetFilename = JSON.stringify(path.basename(filename));
if (filename.match(/\.icon\.svg$/)) {
return `const React = require('react');
return {
code: `const React = require('react');
const SvgIcon = require('@material-ui/core/SvgIcon').default;
module.exports = {
__esModule: true,
@@ -34,9 +35,10 @@ module.exports = {
children: ${assetFilename}
})
})
};`;
};`,
};
}
return `module.exports = ${assetFilename};`;
return { code: `module.exports = ${assetFilename};` };
},
};
+2 -2
View File
@@ -64,10 +64,10 @@ function createTransformer(config) {
}
// We only return the `map` result if source maps are enabled, as they
// have a negative impact on the coverage accuracy.
return code;
return { code };
}
return source;
return { code: source };
};
// TODO: contribute something like this to @sucrase/jest-plugin
+1 -1
View File
@@ -21,7 +21,7 @@ function createTransformer(config) {
const swcTransformer = createSwcTransformer(config);
const process = (source, filePath, jestOptions) => {
if (filePath.endsWith('.js') && !ESM_REGEX.test(source)) {
return source;
return { code: source };
}
return swcTransformer.process(source, filePath, jestOptions);
+40
View File
@@ -0,0 +1,40 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const yaml = require('yaml');
const crypto = require('crypto');
function createTransformer(config) {
const process = source => {
const json = JSON.stringify(yaml.parse(source), null, 2);
return { code: `module.exports = ${json}`, map: null };
};
const getCacheKey = sourceText => {
return crypto
.createHash('md5')
.update(sourceText)
.update(Buffer.alloc(1))
.update(JSON.stringify(config))
.update(Buffer.alloc(1))
.update('1') // increment whenever the transform logic in this file changes
.digest('hex');
};
return { process, getCacheKey };
}
module.exports = { createTransformer };
+18 -18
View File
@@ -30,12 +30,12 @@
"backstage-cli": "bin/backstage-cli"
},
"dependencies": {
"@backstage/cli-common": "^0.1.10",
"@backstage/config": "^1.0.2",
"@backstage/config-loader": "^1.1.4",
"@backstage/errors": "^1.1.1",
"@backstage/release-manifests": "^0.0.6",
"@backstage/types": "^1.0.0",
"@backstage/cli-common": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/config-loader": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/release-manifests": "workspace:^",
"@backstage/types": "workspace:^",
"@manypkg/get-packages": "^1.1.3",
"@octokit/request": "^6.0.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
@@ -55,7 +55,7 @@
"@swc/core": "^1.2.239",
"@swc/helpers": "^0.4.7",
"@swc/jest": "^0.2.22",
"@types/jest": "^27",
"@types/jest": "^29.0.0",
"@types/webpack-env": "^1.15.2",
"@typescript-eslint/eslint-plugin": "^5.9.0",
"@typescript-eslint/parser": "^5.9.0",
@@ -89,10 +89,10 @@
"handlebars": "^4.7.3",
"html-webpack-plugin": "^5.3.1",
"inquirer": "^8.2.0",
"jest": "^27.5.1",
"jest": "^29.0.2",
"jest-css-modules": "^2.1.0",
"jest-runtime": "^27.5.1",
"jest-transform-yaml": "^1.0.0",
"jest-environment-jsdom": "^29.0.2",
"jest-runtime": "^29.0.2",
"json-schema": "^0.4.0",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^2.4.2",
@@ -129,14 +129,14 @@
"zod": "^3.11.6"
},
"devDependencies": {
"@backstage/backend-common": "^0.15.1",
"@backstage/config": "^1.0.2",
"@backstage/core-app-api": "^1.1.0",
"@backstage/core-components": "^0.11.1",
"@backstage/core-plugin-api": "^1.0.6",
"@backstage/dev-utils": "^1.0.6",
"@backstage/test-utils": "^1.2.0",
"@backstage/theme": "^0.2.16",
"@backstage/backend-common": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/dev-utils": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@backstage/theme": "workspace:^",
"@types/diff": "^5.0.0",
"@types/express": "^4.17.6",
"@types/fs-extra": "^9.0.1",
+14
View File
@@ -72,6 +72,20 @@ export function registerRepoCommand(program: Command) {
.action(
lazy(() => import('./repo/list-deprecations').then(m => m.command)),
);
command
.command('test')
.allowUnknownOption(true) // Allows the command to run, but we still need to parse raw args
.option(
'--since <ref>',
'Only test packages that changed since the specified ref',
)
.option(
'--jest-help',
'Show help for Jest CLI options, which are passed through',
)
.description('Run tests, forwarding args to Jest, defaulting to watch mode')
.action(lazy(() => import('./repo/test').then(m => m.command)));
}
export function registerScriptCommand(program: Command) {
+134
View File
@@ -0,0 +1,134 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Command, OptionValues } from 'commander';
import { PackageGraph } from '../../lib/monorepo';
import { paths } from '../../lib/paths';
import { runCheck } from '../../lib/run';
function includesAnyOf(hayStack: string[], ...needles: string[]) {
for (const needle of needles) {
if (hayStack.includes(needle)) {
return true;
}
}
return false;
}
function removeOptionArg(args: string[], option: string) {
let changed = false;
do {
changed = false;
const index = args.indexOf(option);
if (index >= 0) {
changed = true;
args.splice(index, 2);
}
const indexEq = args.findIndex(arg => arg.startsWith(`${option}=`));
if (indexEq >= 0) {
changed = true;
args.splice(indexEq, 1);
}
} while (changed);
}
export async function command(opts: OptionValues, cmd: Command): Promise<void> {
// all args are forwarded to jest
let parent = cmd;
while (parent.parent) {
parent = parent.parent;
}
const allArgs = parent.args as string[];
const args = allArgs.slice(allArgs.indexOf('test') + 1);
// Only include our config if caller isn't passing their own config
if (!includesAnyOf(args, '-c', '--config')) {
args.push('--config', paths.resolveOwn('config/jest.js'));
}
if (!includesAnyOf(args, '--no-passWithNoTests', '--passWithNoTests=false')) {
args.push('--passWithNoTests');
}
// Run in watch mode unless in CI, coverage mode, or running all tests
if (
!process.env.CI &&
!args.includes('--coverage') &&
// explicitly no watching
!includesAnyOf(args, '--no-watch', '--watch=false', '--watchAll=false') &&
// already watching
!includesAnyOf(args, '--watch', '--watchAll')
) {
const isGitRepo = () =>
runCheck('git', 'rev-parse', '--is-inside-work-tree');
const isMercurialRepo = () => runCheck('hg', '--cwd', '.', 'root');
if ((await isGitRepo()) || (await isMercurialRepo())) {
args.push('--watch');
} else {
args.push('--watchAll');
}
}
if (opts.since) {
removeOptionArg(args, '--since');
}
if (opts.since && !args.some(arg => arg.startsWith('--selectProjects'))) {
const packages = await PackageGraph.listTargetPackages();
const graph = PackageGraph.fromPackages(packages);
const changedPackages = await graph.listChangedPackages({
ref: opts.since,
});
const packageNames = Array.from(
graph.collectPackageNames(
changedPackages.map(pkg => pkg.name),
pkg => pkg.allLocalDependents.keys(),
),
);
if (packageNames.length === 0) {
console.log(`No packages changed since ${opts.since}`);
return;
}
args.push('--selectProjects', ...packageNames);
}
// This is the only thing that is not implemented by jest.run(), so we do it here instead
// https://github.com/facebook/jest/blob/cd8828f7bbec6e55b4df5e41e853a5133c4a3ee1/packages/jest-cli/bin/jest.js#L12
if (!process.env.NODE_ENV) {
(process.env as any).NODE_ENV = 'test';
}
// This is to have a consistent timezone for when running tests that involve checking
// the formatting of date/times.
// https://stackoverflow.com/questions/56261381/how-do-i-set-a-timezone-in-my-jest-config
if (!process.env.TZ) {
process.env.TZ = 'UTC';
}
// This ensures that the process doesn't exit too early before stdout is flushed
if (args.includes('--jest-help')) {
removeOptionArg(args, '--jest-help');
args.push('--help');
(process.stdout as any)._handle.setBlocking(true);
}
await require('jest').run(args);
}
+1
View File
@@ -78,6 +78,7 @@ export default async (_opts: OptionValues, cmd: Command) => {
process.env.TZ = 'UTC';
}
// This ensures that the process doesn't exit too early before stdout is flushed
if (args.includes('--help')) {
(process.stdout as any)._handle.setBlocking(true);
}
+1 -1
View File
@@ -267,7 +267,7 @@ export async function createBackendConfig(
paths.targetRunFile ? paths.targetRunFile : paths.targetEntry,
],
resolve: {
extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx', '.json'],
extensions: ['.ts', '.mjs', '.js', '.json'],
mainFields: ['main'],
modules: [paths.rootNodeModules, ...moduleDirs],
plugins: [
+8
View File
@@ -81,6 +81,14 @@ export function createPackageVersionProvider(lockfile?: Lockfile) {
) {
return '*';
}
for (const specifier of ['^', '~', '*']) {
const range = `workspace:${specifier}`;
if (lockfileEntries?.some(entry => entry.range === range)) {
return range;
}
}
const validRanges = lockfileEntries?.filter(entry =>
semver.satisfies(targetVersion, entry.range),
);
@@ -170,7 +170,7 @@ a@^1:
integrity: sha512-xyz
resolved: "https://my-registry/a-1.0.01.tgz#abc123"
b@2.0.x:
"b@2.0.x, b@^2.0.1":
version: 2.0.1
b@^2:
@@ -185,7 +185,7 @@ a@^1:
integrity: sha512-xyz
resolved: "https://my-registry/a-1.0.01.tgz#abc123"
b@2.0.x:
"b@2.0.x, b@^2.0.1":
version: 2.0.1
b@^2:
@@ -206,6 +206,7 @@ describe('New Lockfile', () => {
expect(lockfile.get('a')).toEqual([{ range: '^1', version: '1.0.1' }]);
expect(lockfile.get('b')).toEqual([
{ range: '2.0.x', version: '2.0.1' },
{ range: '^2.0.1', version: '2.0.1' },
{ range: '^2', version: '2.0.0' },
]);
expect(lockfile.toString()).toBe(mockANew);
+10 -2
View File
@@ -122,7 +122,7 @@ export class Lockfile {
for (const [key, value] of Object.entries(data)) {
if (SPECIAL_OBJECT_KEYS.includes(key)) continue;
const [, name, range] = ENTRY_PATTERN.exec(key) ?? [];
const [, name, ranges] = ENTRY_PATTERN.exec(key) ?? [];
if (!name) {
throw new Error(`Failed to parse yarn.lock entry '${key}'`);
}
@@ -132,7 +132,15 @@ export class Lockfile {
queries = [];
packages.set(name, queries);
}
queries.push({ range, version: value.version });
for (let range of ranges.split(/\s*,\s*/)) {
if (range.startsWith(`${name}@`)) {
range = range.slice(`${name}@`.length);
}
if (range.startsWith('npm:')) {
range = range.slice('npm:'.length);
}
queries.push({ range, version: value.version });
}
}
return new Lockfile(path, packages, data, legacy);
+2
View File
@@ -0,0 +1,2 @@
x:
y: 'z'
+23
View File
@@ -0,0 +1,23 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import yaml from './yaml-fixture.yaml';
describe('tests', () => {
it('should load yaml', () => {
expect(yaml).toEqual({ x: { y: 'z' } });
});
});
@@ -30,18 +30,18 @@
"dependencies": {
"@backstage/backend-common": "{{versionQuery '@backstage/backend-common'}}",
"@backstage/config": "{{versionQuery '@backstage/config'}}",
"@types/express": "{{versionQuery '@types/express' '4.17.6'}}",
"express": "{{versionQuery 'express' '4.17.1'}}",
"@types/express": "{{versionQuery '@types/express' '4.17.13'}}",
"express": "{{versionQuery 'express' '4.18.1'}}",
"express-promise-router": "{{versionQuery 'express-promise-router' '4.1.0'}}",
"winston": "{{versionQuery 'winston' '3.2.1'}}",
"winston": "{{versionQuery 'winston' '3.8.1'}}",
"node-fetch": "{{versionQuery 'node-fetch' '2.6.7'}}",
"yn": "{{versionQuery 'yn' '4.0.0'}}"
},
"devDependencies": {
"@backstage/cli": "{{versionQuery '@backstage/cli'}}",
"@types/supertest": "{{versionQuery '@types/supertest' '2.0.8'}}",
"supertest": "{{versionQuery 'supertest' '4.0.2'}}",
"msw": "{{versionQuery 'msw' '0.46.0'}}"
"@types/supertest": "{{versionQuery '@types/supertest' '2.0.12'}}",
"supertest": "{{versionQuery 'supertest' '6.2.4'}}",
"msw": "{{versionQuery 'msw' '0.47.0'}}"
},
"files": [
"dist"
@@ -48,7 +48,7 @@
"@testing-library/react": "{{versionQuery '@testing-library/react' '12.1.3'}}",
"@testing-library/user-event": "{{versionQuery '@testing-library/user-event' '14.0.0'}}",
"@types/node": "{{versionQuery '@types/node' '16.11.26'}}",
"msw": "{{versionQuery 'msw' '0.46.0'}}",
"msw": "{{versionQuery 'msw' '0.47.0'}}",
"cross-fetch": "{{versionQuery 'cross-fetch' '3.1.5'}}"
},
"files": [
+2 -2
View File
@@ -33,13 +33,13 @@
"backstage-codemods": "bin/backstage-codemods"
},
"dependencies": {
"@backstage/cli-common": "^0.1.10",
"@backstage/cli-common": "workspace:^",
"chalk": "^4.0.0",
"jscodeshift": "^0.13.0",
"jscodeshift-add-imports": "^1.0.10"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"@types/jscodeshift": "^0.11.0",
"@types/node": "^16.11.26",
"commander": "^9.1.0",
+5 -5
View File
@@ -33,10 +33,10 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/cli-common": "^0.1.10",
"@backstage/config": "^1.0.2",
"@backstage/errors": "^1.1.1",
"@backstage/types": "^1.0.0",
"@backstage/cli-common": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/types": "workspace:^",
"@types/json-schema": "^7.0.6",
"ajv": "^8.10.0",
"chokidar": "^3.5.2",
@@ -50,7 +50,7 @@
"yup": "^0.32.9"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"@types/json-schema-merge-allof": "^0.6.0",
"@types/mock-fs": "^4.10.0",
"@types/node": "^16.11.26",
+3 -3
View File
@@ -32,12 +32,12 @@
"clean": "backstage-cli package clean"
},
"dependencies": {
"@backstage/types": "^1.0.0",
"@backstage/types": "workspace:^",
"lodash": "^4.17.21"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/test-utils": "^1.2.0",
"@backstage/cli": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@types/node": "^16.0.0"
},
"files": [
+6 -6
View File
@@ -32,10 +32,10 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/config": "^1.0.2",
"@backstage/core-plugin-api": "^1.0.6",
"@backstage/types": "^1.0.0",
"@backstage/version-bridge": "^1.0.1",
"@backstage/config": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/types": "workspace:^",
"@backstage/version-bridge": "workspace:^",
"@types/prop-types": "^15.7.3",
"prop-types": "^15.7.2",
"react-use": "^17.2.4",
@@ -48,8 +48,8 @@
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/test-utils": "^1.2.0",
"@backstage/cli": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@testing-library/react-hooks": "^8.0.0",
@@ -118,9 +118,10 @@ describe('ApiProvider', () => {
}).toThrow(/^API context is not available/);
}).error,
).toEqual([
expect.stringMatching(
/^Error: Uncaught \[Error: API context is not available/,
),
expect.objectContaining({
detail: new Error('API context is not available'),
type: 'unhandled exception',
}),
expect.stringMatching(
/^The above error occurred in the <MyHookConsumer> component/,
),
@@ -133,9 +134,10 @@ describe('ApiProvider', () => {
}).toThrow(/^API context is not available/);
}).error,
).toEqual([
expect.stringMatching(
/^Error: Uncaught \[Error: API context is not available/,
),
expect.objectContaining({
detail: new Error('API context is not available'),
type: 'unhandled exception',
}),
expect.stringMatching(
/^The above error occurred in the <withApis\(Component\)> component/,
),
@@ -154,9 +156,10 @@ describe('ApiProvider', () => {
}).toThrow('No implementation available for apiRef{x}');
}).error,
).toEqual([
expect.stringMatching(
/^Error: Uncaught \[Error: No implementation available for apiRef{x}\]/,
),
expect.objectContaining({
detail: new Error('No implementation available for apiRef{x}'),
type: 'unhandled exception',
}),
expect.stringMatching(
/^The above error occurred in the <MyHookConsumer> component/,
),
@@ -173,9 +176,10 @@ describe('ApiProvider', () => {
}).toThrow('No implementation available for apiRef{x}');
}).error,
).toEqual([
expect.stringMatching(
/^Error: Uncaught \[Error: No implementation available for apiRef{x}\]/,
),
expect.objectContaining({
detail: new Error('No implementation available for apiRef{x}'),
type: 'unhandled exception',
}),
expect.stringMatching(
/^The above error occurred in the <withApis\(Component\)> component/,
),
+8 -8
View File
@@ -32,11 +32,11 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/config": "^1.0.2",
"@backstage/core-plugin-api": "^1.0.6",
"@backstage/errors": "^1.1.1",
"@backstage/theme": "^0.2.16",
"@backstage/version-bridge": "^1.0.1",
"@backstage/config": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/theme": "workspace:^",
"@backstage/version-bridge": "workspace:^",
"@material-table/core": "^3.1.0",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
@@ -78,9 +78,9 @@
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/core-app-api": "^1.1.0",
"@backstage/test-utils": "^1.2.0",
"@backstage/cli": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@testing-library/react-hooks": "^8.0.0",
@@ -47,9 +47,11 @@ describe('TabbedLayout', () => {
});
expect(error).toEqual([
expect.stringMatching(
/Child of TabbedLayout must be an TabbedLayout.Route/,
),
expect.objectContaining({
detail: new Error(
'Child of TabbedLayout must be an TabbedLayout.Route',
),
}),
expect.stringMatching(
/The above error occurred in the <TabbedLayout> component/,
),
@@ -67,7 +67,9 @@ describe('<ErrorBoundary/>', () => {
});
expect(error).toEqual([
expect.stringMatching(/^Error: Uncaught \[Error: Bomb\]/),
expect.objectContaining({
detail: new Error('Bomb'),
}),
expect.stringMatching(
/^The above error occurred in the <Bomb> component:/,
),
@@ -29,7 +29,7 @@ const validBackstageToken =
describe('ProxiedSignInIdentity', () => {
describe('tokenToExpiry', () => {
beforeEach(() => jest.useFakeTimers('modern'));
beforeEach(() => jest.useFakeTimers());
afterEach(() => jest.useRealTimers());
it('handles undefined', async () => {
@@ -56,7 +56,7 @@ describe('ProxiedSignInIdentity', () => {
});
describe('ProxiedSignInIdentity', () => {
beforeEach(() => jest.useFakeTimers('modern'));
beforeEach(() => jest.useFakeTimers());
afterEach(() => jest.useRealTimers());
const worker = setupServer();
+6 -6
View File
@@ -33,9 +33,9 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/config": "^1.0.2",
"@backstage/types": "^1.0.0",
"@backstage/version-bridge": "^1.0.1",
"@backstage/config": "workspace:^",
"@backstage/types": "workspace:^",
"@backstage/version-bridge": "workspace:^",
"history": "^5.0.0",
"prop-types": "^15.7.2",
"zen-observable": "^0.8.15"
@@ -46,9 +46,9 @@
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/core-app-api": "^1.1.0",
"@backstage/test-utils": "^1.2.0",
"@backstage/cli": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@testing-library/react-hooks": "^8.0.0",
@@ -117,7 +117,7 @@ describe('extensions', () => {
render(<BrokenComponent />);
});
screen.getByText('Error in my-plugin');
expect(errors[0]).toMatch('Test error');
expect(errors[0]).toMatchObject({ detail: new Error('Test error') });
});
it('should wrap extended component with analytics context', async () => {
+4 -3
View File
@@ -29,10 +29,10 @@
"clean": "backstage-cli package clean",
"prepack": "node scripts/prepack.js",
"postpack": "node scripts/postpack.js",
"start": "nodemon --"
"start": "yarn nodemon --"
},
"dependencies": {
"@backstage/cli-common": "^0.1.10",
"@backstage/cli-common": "workspace:^",
"chalk": "^4.0.0",
"commander": "^9.1.0",
"fs-extra": "10.1.0",
@@ -42,12 +42,13 @@
"recursive-readdir": "^2.2.2"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"@types/fs-extra": "^9.0.1",
"@types/inquirer": "^8.1.3",
"@types/node": "^16.11.26",
"@types/recursive-readdir": "^2.2.0",
"mock-fs": "^5.1.1",
"nodemon": "^2.0.2",
"ts-node": "^10.0.0"
},
"nodemonConfig": {
+11 -11
View File
@@ -28,17 +28,6 @@ jest.mock('./lib/versions', () => ({
packageVersions: { root: '1.0.0' },
}));
beforeAll(() => {
mockFs({
[`${__dirname}/package.json`]: '', // required by `findPaths(__dirname)`
'templates/': mockFs.load(path.resolve(__dirname, '../templates/')),
});
});
afterAll(() => {
mockFs.restore();
});
const promptMock = jest.spyOn(inquirer, 'prompt');
const checkPathExistsMock = jest.spyOn(tasks, 'checkPathExistsTask');
const templatingMock = jest.spyOn(tasks, 'templatingTask');
@@ -51,6 +40,17 @@ const moveAppMock = jest.spyOn(tasks, 'moveAppTask');
const buildAppMock = jest.spyOn(tasks, 'buildAppTask');
describe('command entrypoint', () => {
beforeAll(() => {
mockFs({
[`${__dirname}/package.json`]: '', // required by `findPaths(__dirname)`
'templates/': mockFs.load(path.resolve(__dirname, '../templates/')),
});
});
afterAll(() => {
mockFs.restore();
});
beforeEach(() => {
promptMock.mockResolvedValueOnce({
name: 'MyApp',
+179 -173
View File
@@ -86,185 +86,191 @@ jest.mock('./versions', () => ({
},
}));
beforeEach(() => {
mockFs({
'projects/my-module.ts': '',
'projects/dir/my-file.txt': '',
'tmp/mockApp/.gitignore': '',
'tmp/mockApp/package.json': '',
'tmp/mockApp/packages/app/package.json': '',
// load templates into mock filesystem
'templates/': mockFs.load(path.resolve(__dirname, '../../templates/')),
});
});
afterEach(() => {
mockFs.restore();
});
describe('checkAppExistsTask', () => {
it('should do nothing if the directory does not exist', async () => {
const dir = 'projects/';
const name = 'MyNewApp';
await expect(checkAppExistsTask(dir, name)).resolves.not.toThrow();
describe('tasks', () => {
beforeEach(() => {
mockFs({
'projects/my-module.ts': '',
'projects/dir/my-file.txt': '',
'tmp/mockApp/.gitignore': '',
'tmp/mockApp/package.json': '',
'tmp/mockApp/packages/app/package.json': '',
// load templates into mock filesystem
'templates/': mockFs.load(path.resolve(__dirname, '../../templates/')),
});
});
it('should throw an error when a file of the same name exists', async () => {
const dir = 'projects/';
const name = 'my-module.ts';
await expect(checkAppExistsTask(dir, name)).rejects.toThrow(
'already exists',
);
afterEach(() => {
mockFs.restore();
});
it('should throw an error when a directory of the same name exists', async () => {
const dir = 'projects/';
const name = 'dir';
await expect(checkAppExistsTask(dir, name)).rejects.toThrow(
'already exists',
);
});
});
describe('checkPathExistsTask', () => {
it('should create a directory at the given path', async () => {
const appDir = 'projects/newProject';
await expect(checkPathExistsTask(appDir)).resolves.not.toThrow();
expect(fs.existsSync(appDir)).toBe(true);
});
it('should do nothing if a directory of the same name exists', async () => {
const appDir = 'projects/dir';
await expect(checkPathExistsTask(appDir)).resolves.not.toThrow();
expect(fs.existsSync(appDir)).toBe(true);
});
it('should fail if a file of the same name exists', async () => {
await expect(checkPathExistsTask('projects/my-module.ts')).rejects.toThrow(
'already exists',
);
});
});
describe('createTemporaryAppFolderTask', () => {
it('should create a directory at a given path', async () => {
const tempDir = 'projects/tmpFolder';
await expect(createTemporaryAppFolderTask(tempDir)).resolves.not.toThrow();
expect(fs.existsSync(tempDir)).toBe(true);
});
it('should fail if a directory of the same name exists', async () => {
const tempDir = 'projects/dir';
await expect(createTemporaryAppFolderTask(tempDir)).rejects.toThrow(
'file already exists',
);
});
it('should fail if a file of the same name exists', async () => {
const tempDir = 'projects/dir/my-file.txt';
await expect(createTemporaryAppFolderTask(tempDir)).rejects.toThrow(
'file already exists',
);
});
});
describe('buildAppTask', () => {
it('should change to `appDir` and run `yarn install` and `yarn tsc`', async () => {
const mockChdir = jest.spyOn(process, 'chdir');
const mockExec = child_process.exec as unknown as jest.MockedFunction<
(
command: string,
callback: (error: null, stdout: string, stderr: string) => void,
) => void
>;
// requires callback implementation to support `promisify` wrapper
// https://stackoverflow.com/a/60579617/10044859
mockExec.mockImplementation((_command, callback) => {
callback(null, 'standard out', 'standard error');
describe('checkAppExistsTask', () => {
it('should do nothing if the directory does not exist', async () => {
const dir = 'projects/';
const name = 'MyNewApp';
await expect(checkAppExistsTask(dir, name)).resolves.not.toThrow();
});
const appDir = 'projects/dir';
await expect(buildAppTask(appDir)).resolves.not.toThrow();
expect(mockChdir).toHaveBeenCalledTimes(2);
expect(mockChdir).toHaveBeenNthCalledWith(1, appDir);
expect(mockChdir).toHaveBeenNthCalledWith(2, appDir);
expect(mockExec).toHaveBeenCalledTimes(2);
expect(mockExec).toHaveBeenNthCalledWith(
1,
'yarn install',
expect.any(Function),
);
expect(mockExec).toHaveBeenNthCalledWith(
2,
'yarn tsc',
expect.any(Function),
);
});
it('should fail if project directory does not exist', async () => {
const appDir = 'projects/missingProject';
await expect(buildAppTask(appDir)).rejects.toThrow(
'no such file or directory',
);
});
});
describe('moveAppTask', () => {
const tempDir = 'tmp/mockApp/';
const id = 'myApp';
it('should move all files in the temp dir to the target dir', async () => {
const destination = 'projects/mockApp';
await moveAppTask(tempDir, destination, id);
expect(fs.existsSync('projects/mockApp/.gitignore')).toBe(true);
expect(fs.existsSync('projects/mockApp/package.json')).toBe(true);
expect(fs.existsSync('projects/mockApp/packages/app/package.json')).toBe(
true,
);
});
it('should fail to move files if destination already exists', async () => {
const destination = 'projects';
await expect(moveAppTask(tempDir, destination, id)).rejects.toThrow(
'dest already exists',
);
});
it('should remove temporary files if move succeeded', async () => {
const destination = 'projects/mockApp';
await moveAppTask(tempDir, destination, id);
expect(fs.existsSync('tmp/mockApp')).toBe(false);
});
it('should remove temporary files if move failed', async () => {
const destination = 'projects';
await expect(moveAppTask(tempDir, destination, id)).rejects.toThrow();
expect(fs.existsSync('tmp/mockApp')).toBe(false);
});
});
describe('templatingTask', () => {
it('should generate a project populating context parameters', async () => {
const templateDir = 'templates/default-app';
const destinationDir = 'templatedApp';
const context = {
name: 'SuperCoolBackstageInstance',
dbTypeSqlite: true,
};
await templatingTask(templateDir, destinationDir, context);
expect(fs.existsSync('templatedApp/package.json')).toBe(true);
expect(fs.existsSync('templatedApp/.dockerignore')).toBe(true);
await expect(fs.readJson('templatedApp/backstage.json')).resolves.toEqual({
version: '1.2.3',
it('should throw an error when a file of the same name exists', async () => {
const dir = 'projects/';
const name = 'my-module.ts';
await expect(checkAppExistsTask(dir, name)).rejects.toThrow(
'already exists',
);
});
it('should throw an error when a directory of the same name exists', async () => {
const dir = 'projects/';
const name = 'dir';
await expect(checkAppExistsTask(dir, name)).rejects.toThrow(
'already exists',
);
});
});
describe('checkPathExistsTask', () => {
it('should create a directory at the given path', async () => {
const appDir = 'projects/newProject';
await expect(checkPathExistsTask(appDir)).resolves.not.toThrow();
expect(fs.existsSync(appDir)).toBe(true);
});
it('should do nothing if a directory of the same name exists', async () => {
const appDir = 'projects/dir';
await expect(checkPathExistsTask(appDir)).resolves.not.toThrow();
expect(fs.existsSync(appDir)).toBe(true);
});
it('should fail if a file of the same name exists', async () => {
await expect(
checkPathExistsTask('projects/my-module.ts'),
).rejects.toThrow('already exists');
});
});
describe('createTemporaryAppFolderTask', () => {
it('should create a directory at a given path', async () => {
const tempDir = 'projects/tmpFolder';
await expect(
createTemporaryAppFolderTask(tempDir),
).resolves.not.toThrow();
expect(fs.existsSync(tempDir)).toBe(true);
});
it('should fail if a directory of the same name exists', async () => {
const tempDir = 'projects/dir';
await expect(createTemporaryAppFolderTask(tempDir)).rejects.toThrow(
'file already exists',
);
});
it('should fail if a file of the same name exists', async () => {
const tempDir = 'projects/dir/my-file.txt';
await expect(createTemporaryAppFolderTask(tempDir)).rejects.toThrow(
'file already exists',
);
});
});
describe('buildAppTask', () => {
it('should change to `appDir` and run `yarn install` and `yarn tsc`', async () => {
const mockChdir = jest.spyOn(process, 'chdir');
const mockExec = child_process.exec as unknown as jest.MockedFunction<
(
command: string,
callback: (error: null, stdout: string, stderr: string) => void,
) => void
>;
// requires callback implementation to support `promisify` wrapper
// https://stackoverflow.com/a/60579617/10044859
mockExec.mockImplementation((_command, callback) => {
callback(null, 'standard out', 'standard error');
});
const appDir = 'projects/dir';
await expect(buildAppTask(appDir)).resolves.not.toThrow();
expect(mockChdir).toHaveBeenCalledTimes(2);
expect(mockChdir).toHaveBeenNthCalledWith(1, appDir);
expect(mockChdir).toHaveBeenNthCalledWith(2, appDir);
expect(mockExec).toHaveBeenCalledTimes(2);
expect(mockExec).toHaveBeenNthCalledWith(
1,
'yarn install',
expect.any(Function),
);
expect(mockExec).toHaveBeenNthCalledWith(
2,
'yarn tsc',
expect.any(Function),
);
});
it('should fail if project directory does not exist', async () => {
const appDir = 'projects/missingProject';
await expect(buildAppTask(appDir)).rejects.toThrow(
'no such file or directory',
);
});
});
describe('moveAppTask', () => {
const tempDir = 'tmp/mockApp/';
const id = 'myApp';
it('should move all files in the temp dir to the target dir', async () => {
const destination = 'projects/mockApp';
await moveAppTask(tempDir, destination, id);
expect(fs.existsSync('projects/mockApp/.gitignore')).toBe(true);
expect(fs.existsSync('projects/mockApp/package.json')).toBe(true);
expect(fs.existsSync('projects/mockApp/packages/app/package.json')).toBe(
true,
);
});
it('should fail to move files if destination already exists', async () => {
const destination = 'projects';
await expect(moveAppTask(tempDir, destination, id)).rejects.toThrow(
'dest already exists',
);
});
it('should remove temporary files if move succeeded', async () => {
const destination = 'projects/mockApp';
await moveAppTask(tempDir, destination, id);
expect(fs.existsSync('tmp/mockApp')).toBe(false);
});
it('should remove temporary files if move failed', async () => {
const destination = 'projects';
await expect(moveAppTask(tempDir, destination, id)).rejects.toThrow();
expect(fs.existsSync('tmp/mockApp')).toBe(false);
});
});
describe('templatingTask', () => {
it('should generate a project populating context parameters', async () => {
const templateDir = 'templates/default-app';
const destinationDir = 'templatedApp';
const context = {
name: 'SuperCoolBackstageInstance',
dbTypeSqlite: true,
};
await templatingTask(templateDir, destinationDir, context);
expect(fs.existsSync('templatedApp/package.json')).toBe(true);
expect(fs.existsSync('templatedApp/.dockerignore')).toBe(true);
await expect(fs.readJson('templatedApp/backstage.json')).resolves.toEqual(
{
version: '1.2.3',
},
);
// catalog was populated with `context.name`
expect(
fs.readFileSync('templatedApp/catalog-info.yaml', 'utf-8'),
).toContain('name: SuperCoolBackstageInstance');
// backend dependencies include `sqlite3` from `context.SQLite`
expect(
fs.readFileSync('templatedApp/packages/backend/package.json', 'utf-8'),
).toContain('sqlite3"');
});
// catalog was populated with `context.name`
expect(
fs.readFileSync('templatedApp/catalog-info.yaml', 'utf-8'),
).toContain('name: SuperCoolBackstageInstance');
// backend dependencies include `sqlite3` from `context.SQLite`
expect(
fs.readFileSync('templatedApp/packages/backend/package.json', 'utf-8'),
).toContain('sqlite3"');
});
});
@@ -14,8 +14,8 @@
"tsc": "tsc",
"tsc:full": "tsc --skipLibCheck false --incremental false",
"clean": "backstage-cli repo clean",
"test": "backstage-cli test",
"test:all": "lerna run test -- --coverage",
"test": "backstage-cli repo test",
"test:all": "backstage-cli repo test --coverage",
"lint": "backstage-cli repo lint --since origin/master",
"lint:all": "backstage-cli repo lint",
"prettier:check": "prettier --check .",
@@ -6,6 +6,17 @@
"backstage": {
"role": "frontend"
},
"scripts": {
"start": "backstage-cli package start",
"build": "backstage-cli package build",
"clean": "backstage-cli package clean",
"test": "backstage-cli package test",
"lint": "backstage-cli package lint",
"test:e2e": "cross-env PORT=3001 start-server-and-test start http://localhost:3001 cy:dev",
"test:e2e:ci": "cross-env PORT=3001 start-server-and-test start http://localhost:3001 cy:run",
"cy:dev": "cypress open",
"cy:run": "cypress run --browser chrome"
},
"dependencies": {
"@backstage/app-defaults": "^{{version '@backstage/app-defaults'}}",
"@backstage/catalog-model": "^{{version '@backstage/catalog-model'}}",
@@ -37,33 +48,22 @@
"history": "^5.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router": "6.0.0-beta.0",
"react-router-dom": "6.0.0-beta.0",
"react-use": "^15.3.3"
"react-router": "^6.3.0",
"react-router-dom": "^6.3.0",
"react-use": "^17.2.4"
},
"devDependencies": {
"@backstage/test-utils": "^{{version '@backstage/test-utils'}}",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@testing-library/user-event": "^12.0.7",
"@types/node": "^14.14.32",
"@testing-library/user-event": "^14.0.0",
"@types/node": "^16.11.26",
"@types/react-dom": "*",
"cross-env": "^7.0.0",
"cypress": "^9.7.0",
"eslint-plugin-cypress": "^2.10.3",
"start-server-and-test": "^1.10.11"
},
"scripts": {
"start": "backstage-cli package start",
"build": "backstage-cli package build",
"clean": "backstage-cli package clean",
"test": "backstage-cli package test",
"lint": "backstage-cli package lint",
"test:e2e": "cross-env PORT=3001 start-server-and-test start http://localhost:3001 cy:dev",
"test:e2e:ci": "cross-env PORT=3001 start-server-and-test start http://localhost:3001 cy:run",
"cy:dev": "cypress open",
"cy:run": "cypress run --browser chrome"
},
"browserslist": {
"production": [
">0.2%",
@@ -31,7 +31,7 @@ import { AlertDisplay, OAuthRequestDialog } from '@backstage/core-components';
import { createApp } from '@backstage/app-defaults';
import { FlatRoutes } from '@backstage/core-app-api';
import { CatalogGraphPage } from '@backstage/plugin-catalog-graph';
import { PermissionedRoute } from '@backstage/plugin-permission-react';
import { RequirePermission } from '@backstage/plugin-permission-react';
import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha';
const app = createApp({
@@ -58,7 +58,7 @@ const AppRouter = app.getRouter();
const routes = (
<FlatRoutes>
<Navigate key="/" to="catalog" />
<Route path="/" element={<Navigate to="/catalog" />} />
<Route path="/catalog" element={<CatalogIndexPage />} />
<Route
path="/catalog/:namespace/:kind/:name"
@@ -81,10 +81,13 @@ const routes = (
path="/tech-radar"
element={<TechRadarPage width={1500} height={800} />}
/>
<PermissionedRoute
<Route
path="/catalog-import"
permission={catalogEntityCreatePermission}
element={<CatalogImportPage />}
element={
<RequirePermission permission={catalogEntityCreatePermission}>
<CatalogImportPage />
</RequirePermission>
}
/>
<Route path="/search" element={<SearchPage />}>
{searchPage}
@@ -1,19 +1,3 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { makeStyles } from '@material-ui/core';
@@ -1,19 +1,3 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { makeStyles } from '@material-ui/core';
@@ -1,19 +1,3 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { PropsWithChildren } from 'react';
import { Link, makeStyles } from '@material-ui/core';
import HomeIcon from '@material-ui/icons/Home';
@@ -1,17 +1 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { Root } from './Root';
@@ -1,18 +1,3 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { Button, Grid } from '@material-ui/core';
import {
@@ -0,0 +1 @@
# intentionally left empty
+10 -10
View File
@@ -32,15 +32,15 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/app-defaults": "^1.0.6",
"@backstage/catalog-model": "^1.1.1",
"@backstage/core-app-api": "^1.1.0",
"@backstage/core-components": "^0.11.1",
"@backstage/core-plugin-api": "^1.0.6",
"@backstage/integration-react": "^1.1.4",
"@backstage/plugin-catalog-react": "^1.1.4",
"@backstage/test-utils": "^1.2.0",
"@backstage/theme": "^0.2.16",
"@backstage/app-defaults": "workspace:^",
"@backstage/catalog-model": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/integration-react": "workspace:^",
"@backstage/plugin-catalog-react": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@backstage/theme": "workspace:^",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@testing-library/jest-dom": "^5.10.1",
@@ -57,7 +57,7 @@
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"@types/node": "^16.0.0"
},
"files": [
+5 -4
View File
@@ -18,7 +18,7 @@
"license": "Apache-2.0",
"main": "src/index.ts",
"scripts": {
"start": "nodemon --",
"start": "yarn nodemon --",
"lint": "backstage-cli package lint",
"test": "backstage-cli package test",
"test:e2e": "yarn start",
@@ -27,9 +27,9 @@
},
"bin": "bin/e2e-test",
"devDependencies": {
"@backstage/cli": "^0.19.0-next.3",
"@backstage/cli-common": "^0.1.10-next.0",
"@backstage/errors": "^1.1.1-next.0",
"@backstage/cli": "workspace:^",
"@backstage/cli-common": "workspace:^",
"@backstage/errors": "workspace:^",
"@types/fs-extra": "^9.0.1",
"@types/node": "^16.11.26",
"@types/puppeteer": "^5.4.4",
@@ -38,6 +38,7 @@
"cross-fetch": "^3.1.5",
"fs-extra": "10.1.0",
"handlebars": "^4.7.3",
"nodemon": "^2.0.2",
"pgtools": "^0.3.0",
"puppeteer": "^17.0.0",
"tree-kill": "^1.2.2",
+2 -2
View File
@@ -32,12 +32,12 @@
"clean": "backstage-cli package clean"
},
"dependencies": {
"@backstage/types": "^1.0.0",
"@backstage/types": "workspace:^",
"cross-fetch": "^3.1.5",
"serialize-error": "^8.0.1"
},
"devDependencies": {
"@backstage/cli": "^0.19.0"
"@backstage/cli": "workspace:^"
},
"files": [
"dist"
+8 -8
View File
@@ -23,11 +23,11 @@
"clean": "backstage-cli package clean"
},
"dependencies": {
"@backstage/config": "^1.0.2",
"@backstage/core-components": "^0.11.1",
"@backstage/core-plugin-api": "^1.0.6",
"@backstage/integration": "^1.3.1",
"@backstage/theme": "^0.2.16",
"@backstage/config": "workspace:^",
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/theme": "workspace:^",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
@@ -37,9 +37,9 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/dev-utils": "^1.0.6",
"@backstage/test-utils": "^1.2.0",
"@backstage/cli": "workspace:^",
"@backstage/dev-utils": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@testing-library/user-event": "^14.0.0",
+5 -5
View File
@@ -32,8 +32,8 @@
"clean": "backstage-cli package clean"
},
"dependencies": {
"@backstage/config": "^1.0.2",
"@backstage/errors": "^1.1.1",
"@backstage/config": "workspace:^",
"@backstage/errors": "workspace:^",
"@octokit/auth-app": "^4.0.0",
"@octokit/rest": "^19.0.3",
"cross-fetch": "^3.1.5",
@@ -42,9 +42,9 @@
"luxon": "^3.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/config-loader": "^1.1.4",
"@backstage/test-utils": "^1.2.0",
"@backstage/cli": "workspace:^",
"@backstage/config-loader": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@types/luxon": "^3.0.0",
"msw": "^0.47.0"
},
+1 -1
View File
@@ -62,7 +62,7 @@ describe('isValidHost', () => {
['[::]', true],
['[::1]', true],
['[1:2:3:4:5:6:7:8]', true],
['1.2.3.4.5.6.7.8', true],
['1.2.3.4.5.6.7.8', false],
['https://example.com', false],
['foo:100000', false],
['FOO', false],
+2 -2
View File
@@ -35,8 +35,8 @@
"cross-fetch": "^3.1.5"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/test-utils": "^1.2.0",
"@backstage/cli": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@types/node": "^16.0.0",
"msw": "^0.47.0"
},
+14 -14
View File
@@ -7,19 +7,19 @@
},
"bundled": true,
"dependencies": {
"@backstage/app-defaults": "^1.0.6",
"@backstage/catalog-model": "^1.1.1",
"@backstage/cli": "^0.19.0",
"@backstage/config": "^1.0.2",
"@backstage/core-app-api": "^1.1.0",
"@backstage/core-components": "^0.11.1",
"@backstage/core-plugin-api": "^1.0.6",
"@backstage/integration-react": "^1.1.4",
"@backstage/plugin-catalog": "^1.5.1",
"@backstage/plugin-techdocs": "^1.3.2",
"@backstage/plugin-techdocs-react": "^1.0.4",
"@backstage/test-utils": "^1.2.0",
"@backstage/theme": "^0.2.16",
"@backstage/app-defaults": "workspace:^",
"@backstage/catalog-model": "workspace:^",
"@backstage/cli": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/integration-react": "workspace:^",
"@backstage/plugin-catalog": "workspace:^",
"@backstage/plugin-techdocs": "workspace:^",
"@backstage/plugin-techdocs-react": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@backstage/theme": "workspace:^",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"history": "^5.0.0",
@@ -30,7 +30,7 @@
"react-use": "^17.2.4"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@testing-library/user-event": "^14.0.0",
+6 -6
View File
@@ -36,7 +36,7 @@
"techdocs-cli": "bin/techdocs-cli"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"@types/commander": "^2.12.2",
"@types/fs-extra": "^9.0.6",
"@types/http-proxy": "^1.17.4",
@@ -60,11 +60,11 @@
"ext": "ts"
},
"dependencies": {
"@backstage/backend-common": "^0.15.1",
"@backstage/catalog-model": "^1.1.1",
"@backstage/cli-common": "^0.1.10",
"@backstage/config": "^1.0.2",
"@backstage/plugin-techdocs-node": "^1.4.0",
"@backstage/backend-common": "workspace:^",
"@backstage/catalog-model": "workspace:^",
"@backstage/cli-common": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/plugin-techdocs-node": "workspace:^",
"@types/dockerode": "^3.3.0",
"commander": "^9.1.0",
"dockerode": "^3.3.1",
+9 -9
View File
@@ -32,15 +32,15 @@
"start": "backstage-cli package start"
},
"dependencies": {
"@backstage/config": "^1.0.2",
"@backstage/core-app-api": "^1.1.0",
"@backstage/core-plugin-api": "^1.0.6",
"@backstage/plugin-permission-common": "^0.6.4",
"@backstage/plugin-permission-react": "^0.4.5",
"@backstage/theme": "^0.2.16",
"@backstage/types": "^1.0.0",
"@backstage/config": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
"@backstage/plugin-permission-react": "workspace:^",
"@backstage/theme": "workspace:^",
"@backstage/types": "workspace:^",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.11.2",
"@material-ui/icons": "^4.9.1",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@testing-library/user-event": "^14.0.0",
@@ -55,7 +55,7 @@
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0",
"@backstage/cli": "workspace:^",
"@types/node": "^16.11.26",
"msw": "^0.47.0"
},
@@ -92,9 +92,11 @@ describe('wrapInTestApp', () => {
});
expect(error).toEqual([
expect.stringMatching(
/^Error: Uncaught \[Error: MockErrorApi received unexpected error, Error: NOPE\]/,
),
expect.objectContaining({
detail: new Error(
'MockErrorApi received unexpected error, Error: NOPE',
),
}),
expect.stringMatching(/^The above error occurred in the <A> component:/),
]);
});
+1 -1
View File
@@ -35,7 +35,7 @@
"@material-ui/core": "^4.12.2"
},
"devDependencies": {
"@backstage/cli": "^0.19.0-next.1"
"@backstage/cli": "workspace:^"
},
"files": [
"dist"
+1 -1
View File
@@ -32,7 +32,7 @@
"clean": "backstage-cli package clean"
},
"devDependencies": {
"@backstage/cli": "^0.19.0-next.1",
"@backstage/cli": "workspace:^",
"@types/zen-observable": "^0.8.0",
"zen-observable": "^0.8.15"
},
+1 -1
View File
@@ -36,7 +36,7 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.19.0-next.1",
"@backstage/cli": "workspace:^",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@testing-library/react-hooks": "^8.0.0"