Build: Bump the github-actions group with 2 updates
[jquery.git] / test / runner / reporter.js
blobe79059648f920bdc2c32a271a9bfa60e4bd5a692
1 import chalk from "chalk";
2 import { getBrowserString } from "./lib/getBrowserString.js";
3 import { prettyMs } from "./lib/prettyMs.js";
4 import * as Diff from "diff";
6 function serializeForDiff( value ) {
8         // Use naive serialization for everything except types with confusable values
9         if ( typeof value === "string" ) {
10                 return JSON.stringify( value );
11         }
12         if ( typeof value === "bigint" ) {
13                 return `${ value }n`;
14         }
15         return `${ value }`;
18 export function reportTest( test, reportId, { browser, headless } ) {
19         if ( test.status === "passed" ) {
21                 // Write to console without newlines
22                 process.stdout.write( "." );
23                 return;
24         }
26         let message = `${ chalk.bold( `${ test.suiteName }: ${ test.name }` ) }`;
27         message += `\nTest ${ test.status } on ${ chalk.yellow(
28                 getBrowserString( browser, headless )
29         ) } (${ chalk.bold( reportId ) }).`;
31         // test.assertions only contains passed assertions;
32         // test.errors contains all failed asssertions
33         if ( test.errors.length ) {
34                 for ( const error of test.errors ) {
35                         message += "\n";
36                         if ( error.message ) {
37                                 message += `\n${ error.message }`;
38                         }
39                         message += `\n${ chalk.gray( error.stack ) }`;
41                         // Show expected and actual values
42                         // if either is defined and non-null.
43                         // error.actual is set to null for failed
44                         // assert.expect() assertions, so skip those as well.
45                         // This should be fine because error.expected would
46                         // have to also be null for this to be skipped.
47                         if ( error.expected != null || error.actual != null ) {
48                                 message += `\nexpected: ${ chalk.red( JSON.stringify( error.expected ) ) }`;
49                                 message += `\nactual: ${ chalk.green( JSON.stringify( error.actual ) ) }`;
50                                 let diff;
52                                 if ( Array.isArray( error.expected ) && Array.isArray( error.actual ) ) {
54                                         // Diff arrays
55                                         diff = Diff.diffArrays( error.expected, error.actual );
56                                 } else if (
57                                         typeof error.expected === "object" &&
58                                         typeof error.actual === "object"
59                                 ) {
61                                         // Diff objects
62                                         diff = Diff.diffJson( error.expected, error.actual );
63                                 } else if (
64                                         typeof error.expected === "number" &&
65                                         typeof error.actual === "number"
66                                 ) {
68                                         // Diff numbers directly
69                                         const value = error.actual - error.expected;
70                                         if ( value > 0 ) {
71                                                 diff = [ { added: true, value: `+${ value }` } ];
72                                         } else {
73                                                 diff = [ { removed: true, value: `${ value }` } ];
74                                         }
75                                 } else if (
76                                         typeof error.expected === "string" &&
77                                         typeof error.actual === "string"
78                                 ) {
80                                         // Diff the characters of strings
81                                         diff = Diff.diffChars( error.expected, error.actual );
82                                 } else {
84                                         // Diff everything else as words
85                                         diff = Diff.diffWords(
86                                                 serializeForDiff( error.expected ),
87                                                 serializeForDiff( error.actual )
88                                         );
89                                 }
91                                 if ( diff ) {
92                                         message += "\n";
93                                         message += diff
94                                                 .map( ( part ) => {
95                                                         if ( part.added ) {
96                                                                 return chalk.green( part.value );
97                                                         }
98                                                         if ( part.removed ) {
99                                                                 return chalk.red( part.value );
100                                                         }
101                                                         return chalk.gray( part.value );
102                                                 } )
103                                                 .join( "" );
104                                 }
105                         }
106                 }
107         }
109         console.log( `\n\n${ message }` );
111         // Only return failed messages
112         if ( test.status === "failed" ) {
113                 return message;
114         }
117 export function reportEnd( result, reportId, { browser, headless, modules } ) {
118         const fullBrowser = getBrowserString( browser, headless );
119         console.log(
120                 `\n\nTests finished in ${ prettyMs( result.runtime ) } ` +
121                         `for ${ chalk.yellow( modules.join( "," ) ) } ` +
122                         `in ${ chalk.yellow( fullBrowser ) } (${ chalk.bold( reportId ) })...`
123         );
124         console.log(
125                 ( result.status !== "passed" ?
126                         `${ chalk.red( result.testCounts.failed ) } failed. ` :
127                         "" ) +
128                         `${ chalk.green( result.testCounts.total ) } passed. ` +
129                         `${ chalk.gray( result.testCounts.skipped ) } skipped.`
130         );
131         return result.testCounts;