3
3
const {
4
4
ArrayPrototypeJoin,
5
5
ArrayPrototypePop,
6
+ ArrayPrototypePush,
6
7
ArrayPrototypeShift,
7
8
ArrayPrototypeUnshift,
8
9
hardenRegExp,
@@ -36,6 +37,7 @@ class SpecReporter extends Transform {
36
37
#stack = [ ] ;
37
38
#reported = [ ] ;
38
39
#indentMemo = new SafeMap ( ) ;
40
+ #failedTests = [ ] ;
39
41
40
42
constructor ( ) {
41
43
super ( { writableObjectMode : true } ) ;
@@ -60,54 +62,74 @@ class SpecReporter extends Transform {
60
62
) , `\n${ indent } ` ) ;
61
63
return `\n${ indent } ${ message } \n` ;
62
64
}
63
- #handleEvent ( { type, data } ) {
65
+ #formatTestReport ( type , data , prefix = '' , indent = '' , hasChildren = false , skippedSubtest = false ) {
64
66
let color = colors [ type ] ?? white ;
65
67
let symbol = symbols [ type ] ?? ' ' ;
66
-
68
+ const duration_ms = data . details ?. duration_ms ? ` ${ gray } (${ data . details . duration_ms } ms)${ white } ` : '' ;
69
+ const title = `${ data . name } ${ duration_ms } ${ skippedSubtest ? ' # SKIP' : '' } ` ;
70
+ if ( hasChildren ) {
71
+ // If this test has had children - it was already reported, so slightly modify the output
72
+ return `${ prefix } ${ indent } ${ color } ${ symbols [ 'arrow:right' ] } ${ white } ${ title } \n` ;
73
+ }
74
+ const error = this . #formatError( data . details ?. error , indent ) ;
75
+ if ( skippedSubtest ) {
76
+ color = gray ;
77
+ symbol = symbols [ 'hyphen:minus' ] ;
78
+ }
79
+ return `${ prefix } ${ indent } ${ color } ${ symbol } ${ title } ${ white } ${ error } ` ;
80
+ }
81
+ #handleTestReportEvent( type , data ) {
82
+ const subtest = ArrayPrototypeShift ( this . #stack) ; // This is the matching `test:start` event
83
+ if ( subtest ) {
84
+ assert ( subtest . type === 'test:start' ) ;
85
+ assert ( subtest . data . nesting === data . nesting ) ;
86
+ assert ( subtest . data . name === data . name ) ;
87
+ }
88
+ let prefix = '' ;
89
+ while ( this . #stack. length ) {
90
+ // Report all the parent `test:start` events
91
+ const parent = ArrayPrototypePop ( this . #stack) ;
92
+ assert ( parent . type === 'test:start' ) ;
93
+ const msg = parent . data ;
94
+ ArrayPrototypeUnshift ( this . #reported, msg ) ;
95
+ prefix += `${ this . #indent( msg . nesting ) } ${ symbols [ 'arrow:right' ] } ${ msg . name } \n` ;
96
+ }
97
+ let hasChildren = false ;
98
+ if ( this . #reported[ 0 ] && this . #reported[ 0 ] . nesting === data . nesting && this . #reported[ 0 ] . name === data . name ) {
99
+ ArrayPrototypeShift ( this . #reported) ;
100
+ hasChildren = true ;
101
+ }
102
+ const skippedSubtest = subtest && data . skip && data . skip !== undefined ;
103
+ const indent = this . #indent( data . nesting ) ;
104
+ return `${ this . #formatTestReport( type , data , prefix , indent , hasChildren , skippedSubtest ) } \n` ;
105
+ }
106
+ #handleEvent( { type, data } ) {
67
107
switch ( type ) {
68
108
case 'test:fail' :
69
- case 'test:pass' : {
70
- const subtest = ArrayPrototypeShift ( this . #stack) ; // This is the matching `test:start` event
71
- if ( subtest ) {
72
- assert ( subtest . type === 'test:start' ) ;
73
- assert ( subtest . data . nesting === data . nesting ) ;
74
- assert ( subtest . data . name === data . name ) ;
75
- }
76
- let prefix = '' ;
77
- while ( this . #stack. length ) {
78
- // Report all the parent `test:start` events
79
- const parent = ArrayPrototypePop ( this . #stack) ;
80
- assert ( parent . type === 'test:start' ) ;
81
- const msg = parent . data ;
82
- ArrayPrototypeUnshift ( this . #reported, msg ) ;
83
- prefix += `${ this . #indent( msg . nesting ) } ${ symbols [ 'arrow:right' ] } ${ msg . name } \n` ;
84
- }
85
- const skippedSubtest = subtest && data . skip && data . skip !== undefined ;
86
- const indent = this . #indent( data . nesting ) ;
87
- const duration_ms = data . details ?. duration_ms ? ` ${ gray } (${ data . details . duration_ms } ms)${ white } ` : '' ;
88
- const title = `${ data . name } ${ duration_ms } ${ skippedSubtest ? ' # SKIP' : '' } ` ;
89
- if ( this . #reported[ 0 ] && this . #reported[ 0 ] . nesting === data . nesting && this . #reported[ 0 ] . name === data . name ) {
90
- // If this test has had children - it was already reported, so slightly modify the output
91
- ArrayPrototypeShift ( this . #reported) ;
92
- return `${ prefix } ${ indent } ${ color } ${ symbols [ 'arrow:right' ] } ${ white } ${ title } \n\n` ;
93
- }
94
- const error = this . #formatError( data . details ?. error , indent ) ;
95
- if ( skippedSubtest ) {
96
- color = gray ;
97
- symbol = symbols [ 'hyphen:minus' ] ;
98
- }
99
- return `${ prefix } ${ indent } ${ color } ${ symbol } ${ title } ${ error } ${ white } \n` ;
100
- }
109
+ ArrayPrototypePush ( this . #failedTests, data ) ;
110
+ return this . #handleTestReportEvent( type , data ) ;
111
+ case 'test:pass' :
112
+ return this . #handleTestReportEvent( type , data ) ;
101
113
case 'test:start' :
102
114
ArrayPrototypeUnshift ( this . #stack, { __proto__ : null , data, type } ) ;
103
115
break ;
104
116
case 'test:diagnostic' :
105
- return `${ color } ${ this . #indent( data . nesting ) } ${ symbol } ${ data . message } ${ white } \n` ;
117
+ return `${ colors [ type ] } ${ this . #indent( data . nesting ) } ${ symbols [ type ] } ${ data . message } ${ white } \n` ;
106
118
}
107
119
}
108
120
_transform ( { type, data } , encoding , callback ) {
109
121
callback ( null , this . #handleEvent( { type, data } ) ) ;
110
122
}
123
+ _flush ( callback ) {
124
+ const results = [ `\n${ colors [ 'test:fail' ] } ${ symbols [ 'test:fail' ] } failing tests:${ white } \n` ] ;
125
+ for ( let i = 0 ; i < this . #failedTests. length ; i ++ ) {
126
+ ArrayPrototypePush ( results , this . #formatTestReport(
127
+ 'test:fail' ,
128
+ this . #failedTests[ i ] ,
129
+ ) ) ;
130
+ }
131
+ callback ( null , ArrayPrototypeJoin ( results , '\n' ) ) ;
132
+ }
111
133
}
112
134
113
135
module . exports = SpecReporter ;
0 commit comments