Skip to content

Commit

Permalink
refactor(@jest/reporters): improve annotation formatting of `GitHubAc…
Browse files Browse the repository at this point in the history
…tionsReporter` (#12826)
  • Loading branch information
mrazauskas committed May 9, 2022
1 parent 346c95f commit 1004ee2
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 171 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Expand Up @@ -2,6 +2,8 @@

### Features

- `[@jest/reporters]` Improve `GitHubActionsReporter`s annotation format ([#12826](https://github.com/facebook/jest/pull/12826))

### Fixes

### Chore & Maintenance
Expand All @@ -14,7 +16,7 @@

### Features

- `[jest-circus]` Add `failing` test modifier that inverts the behaviour of tests ([#12610](https://github.com/facebook/jest/pull/12610))
- `[jest-circus]` Add `failing` test modifier that inverts the behavior of tests ([#12610](https://github.com/facebook/jest/pull/12610))
- `[jest-environment-node, jest-environment-jsdom]` Allow specifying `customExportConditions` ([#12774](https://github.com/facebook/jest/pull/12774))

### Fixes
Expand Down
10 changes: 5 additions & 5 deletions packages/jest-message-util/src/index.ts
Expand Up @@ -234,11 +234,11 @@ const removeInternalStackEntries = (
});
};

const formatPaths = (
config: StackTraceConfig,
relativeTestPath: string | null,
export const formatPath = (
line: string,
) => {
config: StackTraceConfig,
relativeTestPath: string | null = null,
): string => {
// Extract the file path from the trace line.
const match = line.match(/(^\s*at .*?\(?)([^()]+)(:[0-9]+:[0-9]+\)?.*$)/);
if (!match) {
Expand Down Expand Up @@ -317,7 +317,7 @@ export const formatStackTrace = (
.filter(Boolean)
.map(
line =>
STACK_INDENT + formatPaths(config, relativeTestPath, trimPaths(line)),
STACK_INDENT + formatPath(trimPaths(line), config, relativeTestPath),
)
.join('\n');

Expand Down
1 change: 1 addition & 0 deletions packages/jest-reporters/package.json
Expand Up @@ -29,6 +29,7 @@
"istanbul-lib-report": "^3.0.0",
"istanbul-lib-source-maps": "^4.0.0",
"istanbul-reports": "^3.1.3",
"jest-message-util": "^28.1.0",
"jest-util": "^28.1.0",
"jest-worker": "^28.1.0",
"slash": "^3.0.0",
Expand Down
105 changes: 65 additions & 40 deletions packages/jest-reporters/src/GitHubActionsReporter.ts
Expand Up @@ -6,54 +6,79 @@
*/

import stripAnsi = require('strip-ansi');
import type {
AggregatedResult,
TestContext,
TestResult,
} from '@jest/test-result';
import type {Test, TestResult} from '@jest/test-result';
import type {Config} from '@jest/types';
import {
formatPath,
getStackTraceLines,
getTopFrame,
separateMessageFromStack,
} from 'jest-message-util';
import BaseReporter from './BaseReporter';

const lineAndColumnInStackTrace = /^.*?:([0-9]+):([0-9]+).*$/;
type AnnotationOptions = {
file?: string;
line?: number | string;
message: string;
title: string;
type: 'error' | 'warning';
};

function replaceEntities(s: string): string {
// https://github.com/actions/toolkit/blob/b4639928698a6bfe1c4bdae4b2bfdad1cb75016d/packages/core/src/command.ts#L80-L85
const substitutions: Array<[RegExp, string]> = [
[/%/g, '%25'],
[/\r/g, '%0D'],
[/\n/g, '%0A'],
];
return substitutions.reduce((acc, sub) => acc.replace(...sub), s);
}
const titleSeparator = ' \u203A ';

export default class GitHubActionsReporter extends BaseReporter {
static readonly filename = __filename;

override onRunComplete(
_testContexts?: Set<TestContext>,
aggregatedResults?: AggregatedResult,
): void {
const messages = getMessages(aggregatedResults?.testResults);
onTestFileResult({context}: Test, {testResults}: TestResult): void {
testResults.forEach(result => {
const title = [...result.ancestorTitles, result.title].join(
titleSeparator,
);

result.retryReasons?.forEach((retryReason, index) => {
this.#createAnnotation({
...this.#getMessageDetails(retryReason, context.config),
title: `RETRY ${index + 1}: ${title}`,
type: 'warning',
});
});

for (const message of messages) {
this.log(message);
}
result.failureMessages.forEach(failureMessage => {
this.#createAnnotation({
...this.#getMessageDetails(failureMessage, context.config),
title,
type: 'error',
});
});
});
}
}

function getMessages(results: Array<TestResult> | undefined) {
if (!results) return [];

return results.flatMap(({testFilePath, testResults}) =>
testResults
.filter(r => r.status === 'failed')
.flatMap(r => r.failureMessages)
.map(m => stripAnsi(m))
.map(m => replaceEntities(m))
.map(m => lineAndColumnInStackTrace.exec(m))
.filter((m): m is RegExpExecArray => m !== null)
.map(
([message, line, col]) =>
`\n::error file=${testFilePath},line=${line},col=${col}::${message}`,
),
);
#getMessageDetails(failureMessage: string, config: Config.ProjectConfig) {
const {message, stack} = separateMessageFromStack(failureMessage);

const stackLines = getStackTraceLines(stack);
const topFrame = getTopFrame(stackLines);

const normalizedStackLines = stackLines.map(line =>
formatPath(line, config),
);
const messageText = [message, ...normalizedStackLines].join('\n');

return {
file: topFrame?.file,
line: topFrame?.line,
message: messageText,
};
}

#createAnnotation({file, line, message, title, type}: AnnotationOptions) {
message = stripAnsi(
// copied from: https://github.com/actions/toolkit/blob/main/packages/core/src/command.ts
message.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A'),
);

this.log(
`\n::${type} file=${file},line=${line},title=${title}::${message}`,
);
}
}
118 changes: 0 additions & 118 deletions packages/jest-reporters/src/__tests__/GitHubActionsReporter.test.js

This file was deleted.

0 comments on commit 1004ee2

Please sign in to comment.