1
1
/// <reference types="node" />
2
2
// tslint:disable:no-null-keyword
3
3
4
+ import minimist = require( "minimist" ) ;
4
5
import http = require( "http" ) ;
5
6
import fs = require( "fs" ) ;
6
7
import path = require( "path" ) ;
@@ -20,7 +21,8 @@ const baseUrl = new URL(`http://localhost:${port}/`);
20
21
const rootDir = path . dirname ( __dirname ) ;
21
22
const useCaseSensitiveFileNames = isFileSystemCaseSensitive ( ) ;
22
23
23
- let browser = "IE" ;
24
+ const defaultBrowser = os . platform ( ) === "win32" ? "edge" : "chrome" ;
25
+ let browser : "edge" | "chrome" | "none" = defaultBrowser ;
24
26
let grep : string | undefined ;
25
27
let verbose = false ;
26
28
@@ -862,93 +864,137 @@ function startServer() {
862
864
return http . createServer ( handleRequest ) . listen ( port ) ;
863
865
}
864
866
867
+ const REG_COLUMN_PADDING = 4 ;
868
+
869
+ function queryRegistryValue ( keyPath : string , callback : ( error : Error | null , value : string ) => void ) {
870
+ const args = [ "query" , keyPath ] ;
871
+ child_process . execFile ( "reg" , [ "query" , keyPath , "/ve" ] , { encoding : "utf8" } , ( error , stdout ) => {
872
+ if ( error ) return callback ( error , null ) ;
873
+
874
+ const valueLine = stdout . replace ( / ^ \r \n .+ ?\r \n | \r \n \r \n $ / g, "" ) ;
875
+ if ( ! valueLine ) {
876
+ return callback ( new Error ( "Unable to retrieve value." ) , null ) ;
877
+ }
878
+
879
+ const valueNameColumnOffset = REG_COLUMN_PADDING ;
880
+ if ( valueLine . lastIndexOf ( "(Default)" , valueNameColumnOffset ) !== valueNameColumnOffset ) {
881
+ return callback ( new Error ( "Unable to retrieve value." ) , null ) ;
882
+ }
883
+
884
+ const dataTypeColumnOffset = valueNameColumnOffset + "(Default)" . length + REG_COLUMN_PADDING ;
885
+ if ( valueLine . lastIndexOf ( "REG_SZ" , dataTypeColumnOffset ) !== dataTypeColumnOffset ) {
886
+ return callback ( new Error ( "Unable to retrieve value." ) , null ) ;
887
+ }
888
+
889
+ const valueColumnOffset = dataTypeColumnOffset + "REG_SZ" . length + REG_COLUMN_PADDING ;
890
+ const value = valueLine . slice ( valueColumnOffset ) ;
891
+ return callback ( null , value ) ;
892
+ } ) ;
893
+ }
894
+
895
+ interface Browser {
896
+ description : string ;
897
+ command : string ;
898
+ }
899
+
900
+ function createBrowserFromPath ( path : string ) : Browser {
901
+ return { description : path , command : path } ;
902
+ }
903
+
904
+ function getChromePath ( callback : ( error : Error | null , browser : Browser | string | null ) => void ) {
905
+ switch ( os . platform ( ) ) {
906
+ case "win32" :
907
+ return queryRegistryValue ( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe" , ( error , value ) => {
908
+ if ( error ) return callback ( null , "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe" ) ;
909
+ return callback ( null , createBrowserFromPath ( value ) ) ;
910
+ } ) ;
911
+ case "darwin" : return callback ( null , "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" ) ;
912
+ case "linux" : return callback ( null , "/opt/google/chrome/chrome" ) ;
913
+ default : return callback ( new Error ( `Chrome location is unknown for platform '${ os . platform ( ) } '` ) , null ) ;
914
+ }
915
+ }
916
+
917
+ function getEdgePath ( callback : ( error : Error | null , browser : Browser | null ) => void ) {
918
+ switch ( os . platform ( ) ) {
919
+ case "win32" : return callback ( null , { description : "Microsoft Edge" , command : "cmd /c start microsoft-edge:%1" } ) ;
920
+ default : return callback ( new Error ( `Edge location is unknown for platform '${ os . platform ( ) } '` ) , null ) ;
921
+ }
922
+ }
923
+
924
+ function getBrowserPath ( callback : ( error : Error | null , browser : Browser | null ) => void ) {
925
+ switch ( browser ) {
926
+ case "chrome" : return getChromePath ( afterGetBrowserPath ) ;
927
+ case "edge" : return getEdgePath ( afterGetBrowserPath ) ;
928
+ default : return callback ( new Error ( `Browser location is unknown for '${ browser } '` ) , null ) ;
929
+ }
930
+
931
+ function afterGetBrowserPath ( error : Error | null , browser : Browser | string | null ) {
932
+ if ( error ) return callback ( error , null ) ;
933
+ if ( typeof browser === "object" ) return callback ( null , browser ) ;
934
+ return fs . stat ( browser , ( error , stats ) => {
935
+ if ( ! error && stats . isFile ( ) ) {
936
+ return callback ( null , createBrowserFromPath ( browser ) ) ;
937
+ }
938
+ if ( browser === "chrome" ) return callback ( null , createBrowserFromPath ( "chrome" ) ) ;
939
+ return callback ( new Error ( `Browser location is unknown for '${ browser } '` ) , null ) ;
940
+ } ) ;
941
+ }
942
+ }
943
+
865
944
function startClient ( server : http . Server ) {
866
945
let browserPath : string ;
867
946
if ( browser === "none" ) {
868
947
return ;
869
948
}
870
949
871
- if ( browser === "chrome" ) {
872
- let defaultChromePath = "" ;
873
- switch ( os . platform ( ) ) {
874
- case "win32" :
875
- defaultChromePath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe" ;
876
- break ;
877
- case "darwin" :
878
- defaultChromePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" ;
879
- break ;
880
- case "linux" :
881
- defaultChromePath = "/opt/google/chrome/chrome" ;
882
- break ;
883
- default :
884
- console . log ( `default Chrome location is unknown for platform '${ os . platform ( ) } '` ) ;
885
- break ;
886
- }
887
- if ( fs . existsSync ( defaultChromePath ) ) {
888
- browserPath = defaultChromePath ;
889
- }
890
- else {
891
- browserPath = browser ;
892
- }
893
- }
894
- else {
895
- const defaultIEPath = "C:/Program Files/Internet Explorer/iexplore.exe" ;
896
- if ( fs . existsSync ( defaultIEPath ) ) {
897
- browserPath = defaultIEPath ;
950
+ getBrowserPath ( ( error , browser ) => {
951
+ if ( error ) return console . error ( error ) ;
952
+ console . log ( `Using browser: ${ browser . description } ` ) ;
953
+ const queryString = grep ? `?grep=${ grep } ` : "" ;
954
+ const args = [ `http://localhost:${ port } /tests/webTestResults.html${ queryString } ` ] ;
955
+ if ( browser . command . indexOf ( "%" ) === - 1 ) {
956
+ child_process . spawn ( browser . command , args ) ;
898
957
}
899
958
else {
900
- browserPath = browser ;
959
+ const command = browser . command . replace ( / % ( \d + ) / g, ( _ , offset ) => args [ + offset - 1 ] ) ;
960
+ child_process . exec ( command ) ;
901
961
}
902
- }
903
-
904
- console . log ( `Using browser: ${ browserPath } ` ) ;
905
-
906
- const queryString = grep ? `?grep=${ grep } ` : "" ;
907
- const child = child_process . spawn ( browserPath , [ `http://localhost:${ port } /tests/webTestResults.html${ queryString } ` ] , {
908
- stdio : "inherit"
909
962
} ) ;
910
963
}
911
964
912
965
function printHelp ( ) {
913
966
console . log ( "Runs an http server on port 8888, looking for tests folder in the current directory\n" ) ;
914
967
console . log ( "Syntax: node webTestServer.js [browser] [tests] [--verbose]\n" ) ;
915
968
console . log ( "Options:" ) ;
916
- console . log ( " <browser> The browser to launch. One of 'IE ', 'chrome', or 'none' (default 'IE' )." ) ;
969
+ console . log ( " <browser> The browser to launch. One of 'edge ', 'chrome', or 'none' (default 'edge' on Windows, otherwise `chrome` )." ) ;
917
970
console . log ( " <tests> A regular expression to pass to Mocha." ) ;
918
971
console . log ( " --verbose Enables verbose logging." ) ;
919
972
}
920
973
921
974
function parseCommandLine ( args : string [ ] ) {
922
- let offset = 0 ;
923
- for ( const arg of args ) {
924
- const argLower = arg . toLowerCase ( ) ;
925
- if ( argLower === "--help" ) {
926
- printHelp ( ) ;
927
- return false ;
928
- }
929
- else if ( argLower === "--verbose" ) {
930
- verbose = true ;
931
- }
932
- else {
933
- if ( offset === 0 ) {
934
- browser = arg ;
935
- }
936
- else if ( offset === 1 ) {
937
- grep = arg ;
938
- }
939
- else {
940
- console . log ( `Unrecognized argument: ${ arg } \n` ) ;
941
- return false ;
942
- }
943
- offset ++ ;
944
- }
975
+ const parsed = minimist ( args , { boolean : [ "help" , "verbose" ] } ) ;
976
+ if ( parsed . help ) {
977
+ printHelp ( ) ;
978
+ return false ;
979
+ }
980
+
981
+ if ( parsed . verbose ) {
982
+ verbose = true ;
983
+ }
984
+
985
+ const [ parsedBrowser = defaultBrowser , parsedGrep , ...unrecognized ] = parsed . _ ;
986
+ if ( parsedBrowser !== "edge" && parsedBrowser !== "chrome" && parsedBrowser !== "none" ) {
987
+ console . log ( `Unrecognized browser '${ parsedBrowser } ', expected 'edge', 'chrome', or 'none'.` ) ;
988
+ return false ;
945
989
}
946
990
947
- if ( browser !== "IE" && browser !== "chrome" && browser !== "none" ) {
948
- console . log ( `Unrecognized browser ' ${ browser } ', expected 'IE' or 'chrome'. ` ) ;
991
+ if ( unrecognized . length > 0 ) {
992
+ console . log ( `Unrecognized argument: ${ unrecognized [ 0 ] } ` ) ;
949
993
return false ;
950
994
}
951
995
996
+ browser = parsedBrowser ;
997
+ grep = parsedGrep ;
952
998
return true ;
953
999
}
954
1000
0 commit comments