@@ -3,102 +3,100 @@ import type {
33 FullConfig ,
44 Suite ,
55 TestCase ,
6- TestResult ,
76 FullResult ,
8- TestStatus ,
97} from "@playwright/test/reporter" ;
108import * as core from "@actions/core" ;
119import { basename } from "path" ;
1210import { getHtmlTable } from "./utils/getHtmlTable" ;
1311import { getTableRows } from "./utils/getTableRows" ;
12+ import { checkForFailedTests } from "./utils/checkForFailedTests" ;
13+ import Convert from "ansi-to-html" ;
1414
1515interface GitHubActionOptions {
1616 title ?: string ;
1717 useDetails ?: boolean ;
18- }
19-
20- interface TestDetails {
21- total : number | undefined ;
22-
23- tests : {
24- [ fileName : string ] : TestResults ;
25- } ;
26- }
27-
28- export interface TestResults {
29- [ testTitle : string ] : {
30- status : TestStatus | "pending" ;
31- duration : number ;
32- } ;
18+ showError ?: boolean ;
3319}
3420
3521class GitHubAction implements Reporter {
36- private testDetails : TestDetails = {
37- total : undefined ,
38- tests : { } ,
39- } ;
22+ private suite : Suite | undefined ;
4023
4124 constructor ( private options : GitHubActionOptions = { } ) {
4225 console . log ( `Using GitHub Actions reporter` ) ;
4326 }
4427
45- onBegin ( config : FullConfig , suite : Suite ) {
46- this . testDetails . total = suite . allTests ( ) . length ;
47- }
48-
49- onTestBegin ( test : TestCase , result : TestResult ) {
50- const fileName = basename ( test . location . file ) ;
51-
52- if ( ! this . testDetails . tests [ fileName ] ) {
53- this . testDetails . tests [ fileName ] = { } ;
54- }
55-
56- if ( ! this . testDetails . tests [ fileName ] [ test . title ] ) {
57- this . testDetails . tests [ fileName ] [ test . title ] = {
58- status : "pending" ,
59- duration : 0 ,
60- } ;
61- }
62- }
63-
64- onTestEnd ( test : TestCase , result : TestResult ) {
65- const fileName = basename ( test . location . file ) ;
66-
67- this . testDetails . tests [ fileName ] [ test . title ] = {
68- status : result . status ,
69- duration : result . duration ,
70- } ;
28+ onBegin ( _ : FullConfig , suite : Suite ) {
29+ this . suite = suite ;
7130 }
7231
7332 async onEnd ( result : FullResult ) {
74- if ( process . env . GITHUB_ACTIONS ) {
33+ if ( process . env . GITHUB_ACTIONS && this . suite ) {
34+ const os = process . platform ;
7535 const summary = core . summary ;
7636 summary . addHeading ( this . options . title || `Test results` , 1 ) ;
7737
78- summary . addRaw ( `Total tests: ${ this . testDetails . total } ` ) ;
38+ summary . addRaw ( `Total tests: ${ this . suite . allTests ( ) . length } ` ) ;
7939
8040 if ( this . options . useDetails ) {
8141 summary . addSeparator ( ) ;
8242 }
8343
84- for ( const fileName of Object . keys ( this . testDetails . tests ) ) {
85- if ( this . options . useDetails ) {
86- const content = getHtmlTable ( this . testDetails . tests [ fileName ] ) ;
87-
88- // Check if there are any failed tests
89- const failedTests = Object . values (
90- this . testDetails . tests [ fileName ]
91- ) . filter ( ( test ) => test . status !== "passed" ) ;
92-
93- summary . addDetails (
94- `${ failedTests . length === 0 ? "✅" : "❌" } ${ fileName } ` ,
95- content
96- ) ;
97- } else {
98- summary . addHeading ( fileName , 2 ) ;
99-
100- const tableRows = getTableRows ( this . testDetails . tests [ fileName ] ) ;
101- summary . addTable ( tableRows ) ;
44+ for ( const suite of this . suite ?. suites ) {
45+ const project = suite . project ( ) ;
46+
47+ // Get all the test files
48+ const files = suite
49+ . allTests ( )
50+ . map ( ( test ) => test . location . file )
51+ . reduce ( ( acc , curr ) => {
52+ if ( ! acc . includes ( curr ) ) {
53+ acc . push ( curr ) ;
54+ }
55+
56+ return acc ;
57+ } , [ ] as string [ ] ) ;
58+
59+ // Get all the tests per file
60+ const tests = files . reduce ( ( acc , curr ) => {
61+ acc [ curr ] = suite . allTests ( ) . filter ( ( test ) => {
62+ return test . location . file === curr ;
63+ } ) ;
64+
65+ return acc ;
66+ } , { } as { [ fileName : string ] : TestCase [ ] } ) ;
67+
68+ for ( const filePath of Object . keys ( tests ) ) {
69+ const fileName = basename ( filePath ) ;
70+
71+ if ( this . options . useDetails ) {
72+ const content = getHtmlTable (
73+ tests [ filePath ] ,
74+ ! ! this . options . showError
75+ ) ;
76+
77+ // Check if there are any failed tests
78+ const hasFailedTests = checkForFailedTests ( tests [ filePath ] ) ;
79+
80+ summary . addDetails (
81+ `${ hasFailedTests ? "❌" : "✅" } ${ fileName } (${ os } ${
82+ project ! . name ? ` / ${ project ! . name } ` : ""
83+ } )`,
84+ content
85+ ) ;
86+ } else {
87+ summary . addHeading (
88+ `${ fileName } (${ os } ${
89+ project ! . name ? ` / ${ project ! . name } ` : ""
90+ } )`,
91+ 2
92+ ) ;
93+
94+ const tableRows = getTableRows (
95+ tests [ filePath ] ,
96+ ! ! this . options . showError
97+ ) ;
98+ summary . addTable ( tableRows ) ;
99+ }
102100 }
103101 }
104102
0 commit comments