11import * as childProcess from 'child_process' ;
22import * as path from 'path' ;
33import * as readline from 'readline' ;
4+ import { waitUntilPortState } from './ports' ;
45const treeKill = require ( 'tree-kill' ) ;
56const crossSpawn : typeof childProcess . spawn = require ( 'cross-spawn' ) ;
7+ const defaultPort = 5000 ;
68
7- export const defaultUrl = ' http://localhost:5000' ;
9+ export const defaultUrl = ` http://localhost:${ defaultPort } ` ;
810
911export enum AspNetCoreEnviroment {
1012 development ,
@@ -50,7 +52,7 @@ export class AspNetProcess {
5052 } ) ;
5153
5254 // Ensure the process isn't orphaned even if Node crashes before we're disposed
53- process . on ( 'exit' , ( ) => this . _killProcessSync ( ) ) ;
55+ process . on ( 'exit' , ( ) => this . _killAspNetProcess ( ) ) ;
5456
5557 // Also track whether it exited on its own already
5658 this . _process . on ( 'exit' , ( ) => {
@@ -74,7 +76,7 @@ export class AspNetProcess {
7476
7577 public dispose ( ) : Promise < any > {
7678 return new Promise ( ( resolve , reject ) => {
77- this . _killProcessSync ( err => {
79+ this . _killAspNetProcess ( err => {
7880 if ( err ) {
7981 reject ( err ) ;
8082 } else {
@@ -84,11 +86,29 @@ export class AspNetProcess {
8486 } ) ;
8587 }
8688
87- private _killProcessSync ( callback ?: ( err : any ) => void ) {
89+ private _killAspNetProcess ( callback ?: ( err : any ) => void ) {
90+ callback = callback || ( ( ) => { } ) ;
8891 if ( ! this . _processHasExited ) {
8992 // It's important to kill the whole tree, because 'dotnet run' launches a separate 'dotnet exec'
9093 // child process that would otherwise be left running
91- treeKill ( this . _process . pid , 'SIGINT' , callback ) ;
94+ treeKill ( this . _process . pid , 'SIGINT' , err => {
95+ if ( err ) {
96+ callback ( err ) ;
97+ } else {
98+ // It's not enough just to send a SIGINT to ASP.NET. It will stay open for a moment, completing
99+ // any outstanding requests. We have to wait for it really to be gone before continuing, otherwise
100+ // the next test might be unable to start because of the port still being in use.
101+ console . log ( `Waiting until port ${ defaultPort } is closed...` ) ;
102+ waitUntilPortState ( defaultPort , /* isOpen */ true , /* timeoutMs */ 15000 , err => {
103+ if ( err ) {
104+ callback ( err ) ;
105+ } else {
106+ console . log ( `Port ${ defaultPort } is now closed` ) ;
107+ callback ( null ) ;
108+ }
109+ } ) ;
110+ }
111+ } ) ;
92112 }
93113 }
94114}
0 commit comments