@@ -20,20 +20,39 @@ export interface ParserOutput {
2020}
2121
2222const r = {
23- start :/ ^ 1 \. \. [ 0 - 9 ] + $ / ,
24- fail :/ ^ n o t o k \d + \s ( \- \s ) ? ( .+ ) + $ / ,
25- pass :/ ^ o k \d + \s ( \- \s ) ? ( .+ ) + $ / ,
26- details :/ ^ # \s { 2 } ( .+ ) $ / ,
27- ignore :/ ^ # \s + ( t e s t s | p a s s | f a i l | s k i p ) \s + [ 0 - 9 ] + $ / ,
23+ start :/ ^ ( n o t o k ) | ( o k ) / ,
24+ fail :/ ^ n o t o k (?< index > \d + ) \s ( \- \s ) ? (?< message > .+ ) $ / ,
25+ pass :/ ^ o k (?< index > \d + ) \s ( \- \s ) ? (?< message > .+ ) $ / ,
26+ details :/ ^ # \s { 2 } (?< message > .+ ) $ / ,
27+ ignore :/ ^ ( 1 \. \. [ 0 - 9 ] + ) | ( # \s + ( t e s t s | p a s s | f a i l | s k i p ) \s + [ 0 - 9 ] + ) $ / ,
2828}
2929
30- const detect = ( type :'fail' | 'pass' | 'details' , text :string ) => r [ type ] . exec ( text )
30+ const detect = ( type :'fail' | 'pass' | 'details' , text :string ) => {
31+ const match = r [ type ] . exec ( text )
32+ if ( ! match ) {
33+ return null
34+ }
35+ return match . groups
36+ }
37+
38+ // see comment below for extracting logic into custom consumer later
39+ const formatMessage = ( message :string ) :string => {
40+ // specific for python tap.py output
41+ const isTappy = message . match ( / ^ t e s t _ (?< underscoredMessage > .+ ) \s (?< testPath > .+ ) $ / )
42+ if ( isTappy ?. groups ?. underscoredMessage ) {
43+ return isTappy . groups . underscoredMessage . split ( '_' ) . join ( ' ' ) . trim ( )
44+ }
45+ return message . trim ( )
46+ }
3147
48+ // TODO: consider creating custom TAP consumers for languages
49+ // otherwise code here will eventually get out of hand
50+ // currently supports: mocha, python tap.py
3251const parser = ( text :string ) :ParserOutput => {
3352const lineList = text . split ( '\n' )
3453// start after 1..n output
3554const startingPoint = lineList . findIndex ( ( t ) => t . match ( r . start ) )
36- const lines = lineList . slice ( startingPoint + 1 )
55+ const lines = lineList . slice ( startingPoint )
3756
3857const result :ParserOutput = {
3958ok :true ,
@@ -59,10 +78,10 @@ const parser = (text: string): ParserOutput => {
5978if ( ! line . length ) {
6079continue
6180}
62- // be optimistic! check for success
81+ // be optimistic! check for success first
6382const isPass = detect ( 'pass' , line )
6483if ( ! ! isPass ) {
65- const message = isPass [ 2 ] . trim ( )
84+ const message = formatMessage ( isPass . message )
6685const pass :Pass = { message}
6786if ( logs . length ) {
6887pass . logs = logs
@@ -79,7 +98,7 @@ const parser = (text: string): ParserOutput => {
7998if ( ! ! isFail ) {
8099result . ok = false
81100addCurrentDetails ( )
82- const message = isFail [ 2 ] . trim ( )
101+ const message = formatMessage ( isFail . message )
83102const fail :Fail = { message}
84103if ( logs . length ) {
85104fail . logs = logs
@@ -93,7 +112,7 @@ const parser = (text: string): ParserOutput => {
93112// check for error details
94113const isDetails = detect ( 'details' , line )
95114if ( ! ! isDetails ) {
96- const lineDetails :string = isDetails [ 1 ] . trim ( )
115+ const lineDetails :string = isDetails . message . trim ( )
97116if ( ! currentDetails ) {
98117currentDetails = lineDetails
99118} else {