From 7de1004f03435f50bd635bd7bc354d92fccbcdd2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 10 Oct 2020 17:26:27 +0200 Subject: [PATCH] e2e-test: converted into a CLI --- .changeset/fuzzy-falcons-happen.md | 5 ++ .github/workflows/e2e-win.yml | 2 +- .github/workflows/e2e.yml | 2 +- packages/e2e-test/README.md | 2 +- .../e2e-test/{src/index.js => bin/e2e-test} | 7 ++- packages/e2e-test/package.json | 7 ++- packages/e2e-test/src/commands/index.ts | 22 +++++++ .../src/{e2e-test.ts => commands/run.ts} | 20 +------ packages/e2e-test/src/index.ts | 58 +++++++++++++++++++ .../e2e-test/src/{ => lib}/helpers.test.ts | 0 packages/e2e-test/src/{ => lib}/helpers.ts | 4 +- 11 files changed, 104 insertions(+), 25 deletions(-) create mode 100644 .changeset/fuzzy-falcons-happen.md rename packages/e2e-test/{src/index.js => bin/e2e-test} (85%) mode change 100644 => 100755 create mode 100644 packages/e2e-test/src/commands/index.ts rename packages/e2e-test/src/{e2e-test.ts => commands/run.ts} (94%) create mode 100644 packages/e2e-test/src/index.ts rename packages/e2e-test/src/{ => lib}/helpers.test.ts (100%) rename packages/e2e-test/src/{ => lib}/helpers.ts (97%) diff --git a/.changeset/fuzzy-falcons-happen.md b/.changeset/fuzzy-falcons-happen.md new file mode 100644 index 0000000000..461ac195d9 --- /dev/null +++ b/.changeset/fuzzy-falcons-happen.md @@ -0,0 +1,5 @@ +--- +'e2e-test': minor +--- + +Converted into a CLI, use `yarn e2e-test run` to run diff --git a/.github/workflows/e2e-win.yml b/.github/workflows/e2e-win.yml index c48d779962..570d857c48 100644 --- a/.github/workflows/e2e-win.yml +++ b/.github/workflows/e2e-win.yml @@ -40,4 +40,4 @@ jobs: - name: yarn build run: yarn build --ignore example-app --ignore example-backend --ignore @techdocs/cli - name: run E2E test - run: yarn workspace e2e-test start + run: yarn e2e-test run diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index e280bf59a3..62be0a6cea 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -70,7 +70,7 @@ jobs: - name: run E2E test run: | sudo sysctl fs.inotify.max_user_watches=524288 - yarn workspace e2e-test start + yarn e2e-test run env: POSTGRES_HOST: localhost POSTGRES_PORT: ${{ job.services.postgres.ports[5432] }} diff --git a/packages/e2e-test/README.md b/packages/e2e-test/README.md index 6cf50283c5..e3706b6131 100644 --- a/packages/e2e-test/README.md +++ b/packages/e2e-test/README.md @@ -14,7 +14,7 @@ yarn tsc yarn build ``` -Once those tasks have completed, you can now run the test using `yarn start` inside this package. +Once those tasks have completed, you can now run the test using `yarn e2e-test run`. If you make changes to other packages you will need to rerun `yarn tsc && yarn build`. Changes to this package do not require a rebuild. diff --git a/packages/e2e-test/src/index.js b/packages/e2e-test/bin/e2e-test old mode 100644 new mode 100755 similarity index 85% rename from packages/e2e-test/src/index.js rename to packages/e2e-test/bin/e2e-test index 525f20cdd1..d6d449fe31 --- a/packages/e2e-test/src/index.js +++ b/packages/e2e-test/bin/e2e-test @@ -1,3 +1,4 @@ +#!/usr/bin/env node /* * Copyright 2020 Spotify AB * @@ -14,13 +15,15 @@ * limitations under the License. */ +const path = require('path'); + require('ts-node').register({ transpileOnly: true, /* eslint-disable-next-line no-restricted-syntax */ - project: require('path').resolve(__dirname, '../../../tsconfig.json'), + project: path.resolve(__dirname, '../../../tsconfig.json'), compilerOptions: { module: 'CommonJS', }, }); -require('./e2e-test'); +require('../src'); diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 8dcfd98ab5..c746fc7dbc 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -13,17 +13,22 @@ "backstage" ], "license": "Apache-2.0", - "main": "src/index.js", + "main": "src/index.ts", "scripts": { "start": "node .", "lint": "backstage-cli lint", "test": "backstage-cli test", "test:e2e": "yarn start" }, + "bin": { + "e2e-test": "bin/e2e-test" + }, "devDependencies": { "@backstage/cli-common": "^0.1.1-alpha.24", "@types/fs-extra": "^9.0.1", "@types/node": "^13.7.2", + "chalk": "^4.0.0", + "commander": "^6.1.0", "fs-extra": "^9.0.0", "handlebars": "^4.7.3", "node-fetch": "^2.6.0", diff --git a/packages/e2e-test/src/commands/index.ts b/packages/e2e-test/src/commands/index.ts new file mode 100644 index 0000000000..78ff3343f1 --- /dev/null +++ b/packages/e2e-test/src/commands/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { CommanderStatic } from 'commander'; +import { run } from './run'; + +export function registerCommands(program: CommanderStatic) { + program.command('run').description('Run e2e tests').action(run); +} diff --git a/packages/e2e-test/src/e2e-test.ts b/packages/e2e-test/src/commands/run.ts similarity index 94% rename from packages/e2e-test/src/e2e-test.ts rename to packages/e2e-test/src/commands/run.ts index 2ead11c429..2a0f641014 100644 --- a/packages/e2e-test/src/e2e-test.ts +++ b/packages/e2e-test/src/commands/run.ts @@ -24,16 +24,15 @@ import Browser from 'zombie'; import { spawnPiped, runPlain, - handleError, waitForPageWithText, waitFor, waitForExit, print, -} from './helpers'; +} from '../lib/helpers'; import pgtools from 'pgtools'; import { findPaths } from '@backstage/cli-common'; -/* eslint-disable-next-line no-restricted-syntax */ +// eslint-disable-next-line no-restricted-syntax const paths = findPaths(__dirname); const templatePackagePaths = [ @@ -42,7 +41,7 @@ const templatePackagePaths = [ 'packages/create-app/templates/default-app/packages/backend/package.json.hbs', ]; -async function main() { +export async function run() { const rootDir = await fs.mkdtemp(resolvePath(os.tmpdir(), 'backstage-e2e-')); print(`CLI E2E test root: ${rootDir}\n`); @@ -413,16 +412,3 @@ async function testBackendStart(appDir: string, isPostgres: boolean) { print('Backend startup test finished successfully'); } } - -process.on('unhandledRejection', (error: Error) => { - // Try to avoid exiting if the unhandled error is coming from jsdom, i.e. zombie. - // Those are typically errors on the page that should be benign, at least in the - // context of this test. We have other ways of asserting that the page is being - // rendered correctly. - if (error?.stack?.includes('node_modules/jsdom/lib')) { - console.log(`Ignored error inside jsdom, ${error}`); - } else { - handleError(error); - } -}); -main().catch(handleError); diff --git a/packages/e2e-test/src/index.ts b/packages/e2e-test/src/index.ts new file mode 100644 index 0000000000..2266439973 --- /dev/null +++ b/packages/e2e-test/src/index.ts @@ -0,0 +1,58 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 program from 'commander'; +import chalk from 'chalk'; +import { registerCommands } from './commands'; +import { version } from '../package.json'; +import { exitWithError } from './lib/helpers'; + +async function main(argv: string[]) { + program.name('e2e-test').version(version); + + registerCommands(program); + + program.on('command:*', () => { + console.log(); + console.log(chalk.red(`Invalid command: ${program.args.join(' ')}`)); + console.log(); + program.outputHelp(); + process.exit(1); + }); + + program.parse(argv); +} + +process.on('unhandledRejection', (rejection: unknown) => { + // Try to avoid exiting if the unhandled error is coming from jsdom, i.e. zombie. + // Those are typically errors on the page that should be benign, at least in the + // context of this test. We have other ways of asserting that the page is being + // rendered correctly. + if ( + rejection instanceof Error && + rejection?.stack?.includes('node_modules/jsdom/lib') + ) { + console.log(`Ignored error inside jsdom, ${rejection?.stack ?? rejection}`); + } else { + if (rejection instanceof Error) { + exitWithError(rejection); + } else { + exitWithError(new Error(`Unknown rejection: '${rejection}'`)); + } + } +}); + +main(process.argv).catch(exitWithError); diff --git a/packages/e2e-test/src/helpers.test.ts b/packages/e2e-test/src/lib/helpers.test.ts similarity index 100% rename from packages/e2e-test/src/helpers.test.ts rename to packages/e2e-test/src/lib/helpers.test.ts diff --git a/packages/e2e-test/src/helpers.ts b/packages/e2e-test/src/lib/helpers.ts similarity index 97% rename from packages/e2e-test/src/helpers.ts rename to packages/e2e-test/src/lib/helpers.ts index b59de75860..aded184f5c 100644 --- a/packages/e2e-test/src/helpers.ts +++ b/packages/e2e-test/src/lib/helpers.ts @@ -42,7 +42,7 @@ export function spawnPiped(cmd: string[], options?: SpawnOptions) { shell: true, ...options, }); - child.on('error', handleError); + child.on('error', exitWithError); const logPrefix = cmd.map(s => s.replace(/.+\//, '')).join(' '); child.stdout?.on( @@ -75,7 +75,7 @@ export async function runPlain(cmd: string[], options?: SpawnOptions) { } } -export function handleError(err: Error & { code?: unknown }) { +export function exitWithError(err: Error & { code?: unknown }) { process.stdout.write(`${err.name}: ${err.stack || err.message}\n`); if (typeof err.code === 'number') {