1- import * as vscode from 'vscode'
2- import node from '../../services/node'
3-
4- // TODO: use tap parser to make it easier to support other test runners
5-
6- // ensure only latest run_test action is taken
7- let currentId = 0
8-
9- // quick solution to prevent processing multiple results
10- // NOTE: may be possible to kill child process early
11- const shouldExitEarly = ( processId : number ) : boolean => {
12- return currentId !== processId
13- }
14-
15- let channel : vscode . OutputChannel
16-
17- const getOutputChannel = ( name : string ) : vscode . OutputChannel => {
18- if ( ! channel ) {
19- channel = vscode . window . createOutputChannel ( name )
20- }
21- return channel
22- }
23-
24- interface Callbacks {
25- onSuccess ( ) : void
26- onFail ( ) : void
27- onRun ( ) : void
28- onError ( ) : void
29- }
30-
31- interface TestRunnerConfig {
32- command : string
33- parser ( output : string ) : boolean
34- }
35-
36- export const createTestRunner = ( config : TestRunnerConfig , callbacks : Callbacks ) => {
37-
38- const outputChannelName = 'TEST_OUTPUT'
39-
40- return {
41- run ( ) {
42- console . log ( '------------------- run test ------------------' )
43- const processId = ++ currentId
44- callbacks . onRun ( )
45-
46- try {
47- const { stdout} = await node . exec ( config . command )
48- }
49- }
50- }
51- }
52-
53- async function runTest ( { onSuccess, onFail, onRun, onError} : Callbacks ) : Promise < void > {
54-
55-
56-
57-
58- // TODO: verify test runner for args
59- // jest CLI docs https://jestjs.io/docs/en/cli
60- // const testArgs = [
61- // '--json',
62- // '--onlyChanged',
63- // '--env=node',
64- // '--maxConcurrency=4',
65- // '--maxWorkers=4'
66- // ]
67-
68- const commandLine = `npm test -- ${ testArgs . join ( ' ' ) } `
69-
70- try {
71- // capture position early on test start
72- // in case position changes
73- const { stdout} = await node . exec ( commandLine )
74- if ( shouldExitEarly ( processId ) ) {
75- // exit early
76- return
77- }
78-
79- if ( stdout ) {
80- const lines = stdout . split ( / \r { 0 , 1 } \n / )
81- for ( const line of lines ) {
82- if ( line . length > 0 ) {
83- const regExp = / ^ { \" n u m F a i l e d T e s t S u i t e s /
84- const matches = regExp . exec ( line )
85- if ( matches && matches . length ) {
86- const result = JSON . parse ( line )
87-
88- if ( result . success ) {
89- if ( shouldExitEarly ( processId ) ) {
90- // exit early
91- return
92- }
93- console . log ( 'success!' )
94- onSuccess ( )
95- } else {
96- console . log ( 'NOT SUCCESS?' )
97- }
98- }
99- }
100- }
101- }
102- } catch ( err ) {
103- if ( shouldExitEarly ( processId ) ) {
104- // exit early
105- return
106- }
107- // error contains output & error message
108- // output can be parsed as json
109- const { stdout, stderr} = err
110- console . log ( 'TEST FAILED' , stdout )
111-
112- if ( ! stdout ) {
113- console . error ( 'SOMETHING WENT WRONG WITH A PASSING TEST' )
114- onError ( )
115- return
116- }
117- // test runner failed
118- channel = getOutputChannel ( outputChannelName )
119-
120- if ( stdout ) {
121- const lines = stdout . split ( / \r { 0 , 1 } \n / )
122-
123- for ( const line of lines ) {
124- if ( line . length > 0 ) {
125- const dataRegExp = / ^ { \" n u m F a i l e d T e s t S u i t e s " /
126- const matches = dataRegExp . exec ( line )
127-
128- if ( matches && matches . length ) {
129- const result = JSON . parse ( line )
130- const firstError = result . testResults . find ( ( t : any ) => t . status === 'failed' )
131-
132- if ( firstError ) {
133- if ( shouldExitEarly ( processId ) ) {
134- // exit early
135- return
136- }
137- onFail ( )
138- } else {
139- console . error ( 'NOTE: PARSER DID NOT WORK FOR ' , line )
140- }
141- }
142- }
143- }
144- }
145-
146- if ( stderr ) {
147- channel . show ( false )
148- channel . appendLine ( stderr )
149- }
150- }
151- }
152-
153- export default runTest
0 commit comments