diff --git a/borp.js b/borp.js index e8bcb1b..6ab82be 100755 --- a/borp.js +++ b/borp.js @@ -8,11 +8,12 @@ import { finished } from 'node:stream/promises' import { join, relative } from 'node:path' import posix from 'node:path/posix' import runWithTypeScript from './lib/run.js' -import { MarkdownReporter, GithubWorkflowFailuresReporter } from './lib/reporter.js' +import { MarkdownReporter, GithubWorkflowFailuresReporter } from './lib/reporters.js' import { Report } from 'c8' import os from 'node:os' import { execa } from 'execa' +/* c8 ignore next 4 */ process.on('unhandledRejection', (err) => { console.error(err) process.exit(1) @@ -96,6 +97,12 @@ try { spec: new Reporters.spec() } + // If we're running in a GitHub action, adds the gh reporter + // by default so that we can report failures to GitHub + if (process.env.GITHUB_ACTION) { + args.values.reporter.push('gh') + } + for (const input of args.values.reporter) { const [name, dest] = input.split(':') const reporter = reporters[name] diff --git a/lib/reporter.js b/lib/reporters.js similarity index 94% rename from lib/reporter.js rename to lib/reporters.js index 1bb162a..a34cb7b 100644 --- a/lib/reporter.js +++ b/lib/reporters.js @@ -14,7 +14,7 @@ function normalizeFile (file, cwd) { } function eventToLine (event) { - return `* __${event.data.name}__, duration ${event.data.details.duration_ms}ms, line ${event.data.line} \n` + return `* __${event.data.name}__, duration ${event.data.details.duration_ms}ms, line ${event.data.line}\n` } export class MarkdownReporter extends Transform { @@ -25,7 +25,7 @@ export class MarkdownReporter extends Transform { }) this._files = {} - this._cwd = opts?.cwd || process.cwd() + this._cwd = opts?.cwd } getFile (path) { @@ -87,7 +87,7 @@ export class GithubWorkflowFailuresReporter extends Transform { }) this._files = {} - this._cwd = opts?.cwd || process.cwd() + this._cwd = opts?.cwd } _transform (event, encoding, callback) { diff --git a/lib/run.js b/lib/run.js index aa2bbba..2c0720a 100644 --- a/lib/run.js +++ b/lib/run.js @@ -58,6 +58,7 @@ export default async function runWithTypeScript (config) { } config.prefix = prefix config.setup = (test) => { + /* c8 ignore next 12 */ if (test.reporter) { for (const chunk of pushable) { test.reporter.push(chunk) diff --git a/test/basic.test.js b/test/basic.test.js index bfc066a..4f32c32 100644 --- a/test/basic.test.js +++ b/test/basic.test.js @@ -186,7 +186,3 @@ test('js-esm', async (t) => { await completed }) - -test('this fails', async (t) => { - throw new Error('this fails') -}) diff --git a/test/cli.test.js b/test/cli.test.js index 72984d3..6df5b07 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -5,6 +5,8 @@ import { rejects } from 'node:assert' const borp = join(import.meta.url, '..', 'borp.js') +delete process.env.GITHUB_ACTION + test('limit concurrency', async () => { await execa('node', [ borp, diff --git a/test/coverage.test.js b/test/coverage.test.js index aff77d8..8d763c1 100644 --- a/test/coverage.test.js +++ b/test/coverage.test.js @@ -3,6 +3,7 @@ import { match, doesNotMatch } from 'node:assert' import { execa } from 'execa' import { join } from 'desm' +delete process.env.GITHUB_ACTION const borp = join(import.meta.url, '..', 'borp.js') test('coverage', async () => { diff --git a/test/reporters.test.js b/test/reporters.test.js new file mode 100644 index 0000000..a525dad --- /dev/null +++ b/test/reporters.test.js @@ -0,0 +1,169 @@ +import { MarkdownReporter, GithubWorkflowFailuresReporter } from '../lib/reporters.js' +import { test, describe } from 'node:test' +import { strictEqual } from 'node:assert' + +describe('MarkdownReporter', async () => { + test('should write a report', async () => { + const reporter = new MarkdownReporter({ cwd: '/foo' }) + + // This is skipped + reporter.write({ + type: 'test:start', + data: {} + }) + + reporter.write({ + type: 'test:pass', + data: { + name: 'add', + file: 'file:///foo/test/add.test.ts', + line: 1, + details: { + duration_ms: 100 + } + } + }) + + reporter.write({ + type: 'test:pass', + data: { + name: 'add2', + file: 'file:///foo/test/add.test.ts', + line: 2, + details: { + duration_ms: 100 + } + } + }) + + reporter.write({ + type: 'test:fail', + data: { + name: 'add3', + file: 'file:///foo/test/add.test.ts', + line: 10, + details: { + duration_ms: 100 + } + } + }) + reporter.end() + + let output = '' + for await (const chunk of reporter) { + output += chunk + } + + strictEqual(output, `# Summary +## test/add.test.ts +### :white_check_mark: Pass +* __add__, duration 100ms, line 1 +* __add2__, duration 100ms, line 2 +### :x: Fail +* __add3__, duration 100ms, line 10 +`) + }) + + test('skip fail heading if no failing tests', async () => { + const reporter = new MarkdownReporter({ cwd: '/foo' }) + + reporter.write({ + type: 'test:pass', + data: { + name: 'add', + file: 'file:///foo/test/add.test.ts', + line: 1, + details: { + duration_ms: 100 + } + } + }) + + reporter.write({ + type: 'test:pass', + data: { + name: 'add2', + file: 'file:///foo/test/add.test.ts', + line: 2, + details: { + duration_ms: 100 + } + } + }) + + reporter.end() + + let output = '' + for await (const chunk of reporter) { + output += chunk + } + + strictEqual(output, `# Summary +## test/add.test.ts +### :white_check_mark: Pass +* __add__, duration 100ms, line 1 +* __add2__, duration 100ms, line 2 +`) + }) +}) + +describe('GithubWorkflowFailuresReporter', async () => { + test('should write error in github format', async () => { + const reporter = new GithubWorkflowFailuresReporter({ cwd: '/foo' }) + + // This is skipped + reporter.write({ + type: 'test:start', + data: {} + }) + + reporter.write({ + type: 'test:pass', + data: { + name: 'add', + file: 'file:///foo/test/add.test.ts', + line: 1, + details: { + duration_ms: 100 + } + } + }) + + reporter.write({ + type: 'test:fail', + data: { + name: 'add2', + file: 'file:///foo/test/add.test.ts', + line: 2, + details: { + duration_ms: 100 + } + } + }) + + reporter.write({ + type: 'test:fail', + data: { + name: 'add3', + file: 'file:///foo/test/add.test.ts', + line: 10, + details: { + duration_ms: 100 + } + } + }) + reporter.end() + + let output = '' + for await (const chunk of reporter) { + output += chunk + } + + const expected = [ + '::error file=test/add.test.ts,line=2::add2\n', + '::error file=test/add.test.ts,line=10::add3\n' + ].join('') + + strictEqual(output, expected) + }) +})