mirror of
https://github.com/dorny/test-reporter.git
synced 2026-03-21 23:52:12 +01:00
feat: add sort-suites input to order suites by time descending
Add a new 'sort-suites' input parameter that accepts 'name' (default, alphabetical) or 'time-desc' (slowest first). This allows consumers to surface the slowest test suites at the top of the report. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
a810f9bf83
commit
2380ffd7fe
4 changed files with 42 additions and 8 deletions
|
|
@ -46,6 +46,13 @@ inputs:
|
|||
- none
|
||||
required: false
|
||||
default: 'all'
|
||||
sort-suites:
|
||||
description: |
|
||||
Sort order for test suites. Supported options:
|
||||
- name: Sort alphabetically by name (default)
|
||||
- time-desc: Sort by execution time, slowest first
|
||||
required: false
|
||||
default: 'name'
|
||||
list-tests:
|
||||
description: |
|
||||
Limits which test cases are listed. Supported options:
|
||||
|
|
|
|||
21
dist/index.js
generated
vendored
21
dist/index.js
generated
vendored
|
|
@ -303,6 +303,7 @@ class TestReporter {
|
|||
pathReplaceBackslashes = core.getInput('path-replace-backslashes', { required: false }) === 'true';
|
||||
reporter = core.getInput('reporter', { required: true });
|
||||
listSuites = core.getInput('list-suites', { required: true });
|
||||
sortSuites = core.getInput('sort-suites', { required: false });
|
||||
listTests = core.getInput('list-tests', { required: true });
|
||||
maxAnnotations = parseInt(core.getInput('max-annotations', { required: true }));
|
||||
failOnError = core.getInput('fail-on-error', { required: true }) === 'true';
|
||||
|
|
@ -322,6 +323,10 @@ class TestReporter {
|
|||
core.setFailed(`Input parameter 'list-suites' has invalid value`);
|
||||
return;
|
||||
}
|
||||
if (this.sortSuites !== 'name' && this.sortSuites !== 'time-desc') {
|
||||
core.setFailed(`Input parameter 'sort-suites' has invalid value`);
|
||||
return;
|
||||
}
|
||||
if (this.listTests !== 'all' && this.listTests !== 'failed' && this.listTests !== 'none') {
|
||||
core.setFailed(`Input parameter 'list-tests' has invalid value`);
|
||||
return;
|
||||
|
|
@ -409,7 +414,7 @@ class TestReporter {
|
|||
throw error;
|
||||
}
|
||||
}
|
||||
const { listSuites, listTests, onlySummary, useActionsSummary, badgeTitle, reportTitle, collapsed } = this;
|
||||
const { listSuites, sortSuites, listTests, onlySummary, useActionsSummary, badgeTitle, reportTitle, collapsed } = this;
|
||||
const passed = results.reduce((sum, tr) => sum + tr.passed, 0);
|
||||
const failed = results.reduce((sum, tr) => sum + tr.failed, 0);
|
||||
const skipped = results.reduce((sum, tr) => sum + tr.skipped, 0);
|
||||
|
|
@ -418,6 +423,7 @@ class TestReporter {
|
|||
if (this.useActionsSummary) {
|
||||
const summary = (0, get_report_1.getReport)(results, {
|
||||
listSuites,
|
||||
sortSuites,
|
||||
listTests,
|
||||
baseUrl,
|
||||
onlySummary,
|
||||
|
|
@ -446,6 +452,7 @@ class TestReporter {
|
|||
baseUrl = createResp.data.html_url;
|
||||
const summary = (0, get_report_1.getReport)(results, {
|
||||
listSuites,
|
||||
sortSuites,
|
||||
listTests,
|
||||
baseUrl,
|
||||
onlySummary,
|
||||
|
|
@ -2446,6 +2453,7 @@ const MAX_ACTIONS_SUMMARY_LENGTH = 1048576;
|
|||
exports.DEFAULT_OPTIONS = {
|
||||
listSuites: 'all',
|
||||
listTests: 'all',
|
||||
sortSuites: 'name',
|
||||
baseUrl: '',
|
||||
onlySummary: false,
|
||||
useActionsSummary: true,
|
||||
|
|
@ -2454,7 +2462,7 @@ exports.DEFAULT_OPTIONS = {
|
|||
collapsed: 'auto'
|
||||
};
|
||||
function getReport(results, options = exports.DEFAULT_OPTIONS, shortSummary = '') {
|
||||
applySort(results);
|
||||
applySort(results, options);
|
||||
const opts = { ...options };
|
||||
let lines = renderReport(results, opts, shortSummary);
|
||||
let report = lines.join('\n');
|
||||
|
|
@ -2502,10 +2510,15 @@ function trimReport(lines, options) {
|
|||
reportLines.push(errorMsg);
|
||||
return reportLines.join('\n');
|
||||
}
|
||||
function applySort(results) {
|
||||
function applySort(results, options) {
|
||||
results.sort((a, b) => a.path.localeCompare(b.path, node_utils_1.DEFAULT_LOCALE));
|
||||
for (const res of results) {
|
||||
res.suites.sort((a, b) => a.name.localeCompare(b.name, node_utils_1.DEFAULT_LOCALE));
|
||||
if (options.sortSuites === 'time-desc') {
|
||||
res.suites.sort((a, b) => b.time - a.time);
|
||||
}
|
||||
else {
|
||||
res.suites.sort((a, b) => a.name.localeCompare(b.name, node_utils_1.DEFAULT_LOCALE));
|
||||
}
|
||||
}
|
||||
}
|
||||
function getByteLength(text) {
|
||||
|
|
|
|||
10
src/main.ts
10
src/main.ts
|
|
@ -42,6 +42,7 @@ class TestReporter {
|
|||
readonly pathReplaceBackslashes = core.getInput('path-replace-backslashes', {required: false}) === 'true'
|
||||
readonly reporter = core.getInput('reporter', {required: true})
|
||||
readonly listSuites = core.getInput('list-suites', {required: true}) as 'all' | 'failed' | 'none'
|
||||
readonly sortSuites = core.getInput('sort-suites', {required: false}) as 'name' | 'time-desc'
|
||||
readonly listTests = core.getInput('list-tests', {required: true}) as 'all' | 'failed' | 'none'
|
||||
readonly maxAnnotations = parseInt(core.getInput('max-annotations', {required: true}))
|
||||
readonly failOnError = core.getInput('fail-on-error', {required: true}) === 'true'
|
||||
|
|
@ -64,6 +65,11 @@ class TestReporter {
|
|||
return
|
||||
}
|
||||
|
||||
if (this.sortSuites !== 'name' && this.sortSuites !== 'time-desc') {
|
||||
core.setFailed(`Input parameter 'sort-suites' has invalid value`)
|
||||
return
|
||||
}
|
||||
|
||||
if (this.listTests !== 'all' && this.listTests !== 'failed' && this.listTests !== 'none') {
|
||||
core.setFailed(`Input parameter 'list-tests' has invalid value`)
|
||||
return
|
||||
|
|
@ -174,7 +180,7 @@ class TestReporter {
|
|||
}
|
||||
}
|
||||
|
||||
const {listSuites, listTests, onlySummary, useActionsSummary, badgeTitle, reportTitle, collapsed} = this
|
||||
const {listSuites, sortSuites, listTests, onlySummary, useActionsSummary, badgeTitle, reportTitle, collapsed} = this
|
||||
|
||||
const passed = results.reduce((sum, tr) => sum + tr.passed, 0)
|
||||
const failed = results.reduce((sum, tr) => sum + tr.failed, 0)
|
||||
|
|
@ -187,6 +193,7 @@ class TestReporter {
|
|||
results,
|
||||
{
|
||||
listSuites,
|
||||
sortSuites,
|
||||
listTests,
|
||||
baseUrl,
|
||||
onlySummary,
|
||||
|
|
@ -218,6 +225,7 @@ class TestReporter {
|
|||
baseUrl = createResp.data.html_url as string
|
||||
const summary = getReport(results, {
|
||||
listSuites,
|
||||
sortSuites,
|
||||
listTests,
|
||||
baseUrl,
|
||||
onlySummary,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const MAX_ACTIONS_SUMMARY_LENGTH = 1048576
|
|||
export interface ReportOptions {
|
||||
listSuites: 'all' | 'failed' | 'none'
|
||||
listTests: 'all' | 'failed' | 'none'
|
||||
sortSuites: 'name' | 'time-desc'
|
||||
baseUrl: string
|
||||
onlySummary: boolean
|
||||
useActionsSummary: boolean
|
||||
|
|
@ -22,6 +23,7 @@ export interface ReportOptions {
|
|||
export const DEFAULT_OPTIONS: ReportOptions = {
|
||||
listSuites: 'all',
|
||||
listTests: 'all',
|
||||
sortSuites: 'name',
|
||||
baseUrl: '',
|
||||
onlySummary: false,
|
||||
useActionsSummary: true,
|
||||
|
|
@ -35,7 +37,7 @@ export function getReport(
|
|||
options: ReportOptions = DEFAULT_OPTIONS,
|
||||
shortSummary = ''
|
||||
): string {
|
||||
applySort(results)
|
||||
applySort(results, options)
|
||||
|
||||
const opts = {...options}
|
||||
let lines = renderReport(results, opts, shortSummary)
|
||||
|
|
@ -94,10 +96,14 @@ function trimReport(lines: string[], options: ReportOptions): string {
|
|||
return reportLines.join('\n')
|
||||
}
|
||||
|
||||
function applySort(results: TestRunResult[]): void {
|
||||
function applySort(results: TestRunResult[], options: ReportOptions): void {
|
||||
results.sort((a, b) => a.path.localeCompare(b.path, DEFAULT_LOCALE))
|
||||
for (const res of results) {
|
||||
res.suites.sort((a, b) => a.name.localeCompare(b.name, DEFAULT_LOCALE))
|
||||
if (options.sortSuites === 'time-desc') {
|
||||
res.suites.sort((a, b) => b.time - a.time)
|
||||
} else {
|
||||
res.suites.sort((a, b) => a.name.localeCompare(b.name, DEFAULT_LOCALE))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue