UNPKG

@aws-cdk-testing/cli-integ

Version:

Integration tests for the AWS CDK CLI

111 lines (94 loc) 3.67 kB
import * as fs from 'fs'; import * as path from 'path'; import { MemoryStream } from './corking'; const SKIP_TESTS = fs.readFileSync(path.join(__dirname, '..', 'skip-tests.txt'), { encoding: 'utf-8' }) .split('\n') .map(x => x.trim()) .filter(x => x && !x.startsWith('#')); if (SKIP_TESTS.length > 0) { process.stderr.write(`ℹ️ Skipping tests: ${JSON.stringify(SKIP_TESTS)}\n`); } // Whether we want to stop after the first failure, for quicker debugging (hopefully). const FAIL_FAST = process.env.FAIL_FAST === 'true'; // Keep track of whether the suite has failed. If so, we stop running. let failed = false; export interface TestContext { readonly randomString: string; readonly name: string; readonly output: NodeJS.WritableStream; log(s: string): void; } /** * A wrapper for jest's 'test' which takes regression-disabled tests into account and prints a banner */ export function integTest( name: string, callback: (context: TestContext) => Promise<void>, timeoutMillis?: number, ): void { const runner = shouldSkip(name) ? test.skip : test; runner(name, async () => { const output = new MemoryStream(); output.write('================================================================\n'); output.write(`${name}\n`); output.write('================================================================\n'); const now = Date.now(); process.stderr.write(`[INTEG TEST::${name}] Starting (pid ${process.pid})...\n`); try { if (FAIL_FAST && failed) { throw new Error('FAIL_FAST requested and currently failing. Stopping test early.'); } return await callback({ output, randomString: randomString(), name, log(s: string) { output.write(`${s}\n`); }, }); } catch (e: any) { failed = true; // Print the buffered output, only if the test fails. output.write(e.message); output.write(e.stack); process.stderr.write(`[INTEG TEST::${name}] Failed: ${e}\n`); const isGitHub = !!process.env.GITHUB_RUN_ID; if (isGitHub) { // GitHub Actions compatible output formatting // https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-an-error-message let written = process.stderr.write(`::error title=Failed ${name}::${e.message}\n`); if (!written) { // Wait for drain await new Promise((ok) => process.stderr.once('drain', ok)); } // Print output only if the test fails. Use 'console.log' so the output is buffered by // jest and prints without a stack trace (if verbose: false). written = process.stdout.write([ `::group::Failure details: ${name} (click to expand)\n`, `${output.buffer().toString()}\n`, '::endgroup::\n', ].join('')); if (!written) { // Wait for drain await new Promise((ok) => process.stdout.once('drain', ok)); } } else { // Use 'console.log' so the output is buffered by // jest and prints without a stack trace (if verbose: false). // eslint-disable-next-line no-console console.log(output.buffer().toString()); } throw e; } finally { const duration = Date.now() - now; process.stderr.write(`[INTEG TEST::${name}] Done (${duration} ms).\n`); } }, timeoutMillis); } function shouldSkip(testName: string) { return SKIP_TESTS.includes(testName); } export function randomString() { // Crazy return Math.random().toString(36).replace(/[^a-z0-9]+/g, ''); }