1414 * limitations under the License.
1515 */
1616
17- package com .microsoft .playwright ;
17+ package com .microsoft .playwright . impl . driver . jar ;
1818
1919import com .microsoft .playwright .impl .driver .Driver ;
20- import com . microsoft . playwright . impl . driver . jar . DriverJar ;
20+ import org . junit . jupiter . api . AfterEach ;
2121import org .junit .jupiter .api .BeforeEach ;
2222import org .junit .jupiter .api .Test ;
2323import org .junit .jupiter .api .io .TempDir ;
2424
2525import java .io .IOException ;
2626import java .lang .reflect .Field ;
2727import java .net .ServerSocket ;
28+ import java .net .URISyntaxException ;
29+ import java .nio .charset .StandardCharsets ;
2830import java .nio .file .Files ;
2931import java .nio .file .Path ;
3032import java .util .Collections ;
3133import java .util .HashMap ;
3234import java .util .Map ;
3335import java .util .concurrent .TimeUnit ;
3436
37+ import static com .microsoft .playwright .impl .driver .jar .DriverJar .PLAYWRIGHT_NODEJS_PATH ;
38+ import static java .util .Collections .singletonMap ;
3539import static org .junit .jupiter .api .Assertions .*;
3640
3741public class TestInstall {
@@ -57,6 +61,7 @@ void clearSystemProperties() {
5761 // Clear system property to ensure that the driver is loaded from jar.
5862 System .clearProperty ("playwright.cli.dir" );
5963 System .clearProperty ("playwright.driver.tmpdir" );
64+ System .clearProperty ("playwright.nodejs.path" );
6065 // Clear system property to ensure that the default driver is loaded.
6166 System .clearProperty ("playwright.driver.impl" );
6267 }
@@ -72,27 +77,20 @@ void shouldThrowWhenBrowserPathIsInvalid(@TempDir Path tmpDir) throws NoSuchFiel
7277 env .put ("PLAYWRIGHT_BROWSERS_PATH" , tmpDir .toString ());
7378 env .put ("PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD" , "false" );
7479
75- // Reset instance field value to null for the test.
76- Field field = Driver .class .getDeclaredField ("instance" );
77- field .setAccessible (true );
78- Object value = field .get (Driver .class );
79- field .set (Driver .class , null );
80-
8180 for (int i = 0 ; i < 2 ; i ++){
8281 RuntimeException exception = assertThrows (RuntimeException .class , () -> Driver .ensureDriverInstalled (env , true ));
8382 String message = exception .getMessage ();
8483 assertTrue (message .contains ("Failed to create driver" ), message );
8584 }
86-
87- field .set (Driver .class , value );
8885 }
8986
9087 @ Test
9188 void playwrightCliInstalled () throws Exception {
92- Path cli = Driver .ensureDriverInstalled (Collections .emptyMap (), false );
93- assertTrue (Files .exists (cli ));
89+ Driver driver = Driver .createAndInstall (Collections .emptyMap (), false );
90+ assertTrue (Files .exists (driver . driverPath () ));
9491
95- ProcessBuilder pb = new ProcessBuilder (cli .toString (), "install" );
92+ ProcessBuilder pb = driver .createProcessBuilder ();
93+ pb .command ().add ("install" );
9694 pb .redirectError (ProcessBuilder .Redirect .INHERIT );
9795 pb .redirectOutput (ProcessBuilder .Redirect .INHERIT );
9896 Process p = pb .start ();
@@ -109,24 +107,62 @@ void playwrightDriverInAlternativeTmpdir(@TempDir Path tmpdir) throws Exception
109107
110108 @ Test
111109 void playwrightDriverDefaultImpl () {
112- assertDoesNotThrow (() -> Driver .ensureDriverInstalled (Collections .emptyMap (), false ));
110+ assertDoesNotThrow (() -> Driver .createAndInstall (Collections .emptyMap (), false ));
113111 }
114112
115113 @ Test
116114 void playwrightDriverAlternativeImpl () throws NoSuchFieldException , IllegalAccessException {
117- // Reset instance field value to null for the test.
118- Field field = Driver .class .getDeclaredField ("instance" );
119- field .setAccessible (true );
120- Object value = field .get (Driver .class );
121- field .set (Driver .class , null );
122-
123115 System .setProperty ("playwright.driver.impl" , "com.microsoft.playwright.impl.AlternativeDriver" );
124116 RuntimeException thrown =
125117 assertThrows (
126118 RuntimeException .class ,
127119 () -> Driver .ensureDriverInstalled (Collections .emptyMap (), false ));
128120 assertEquals ("Failed to create driver" , thrown .getMessage ());
121+ }
122+
123+ @ Test
124+ void canPassPreinstalledNodeJsAsSystemProperty (@ TempDir Path tmpDir ) throws IOException , URISyntaxException , InterruptedException {
125+ String nodePath = extractNodeJsToTemp ();
126+ System .setProperty ("playwright.nodejs.path" , nodePath );
127+ Driver driver = Driver .createAndInstall (Collections .emptyMap (), false );
128+ canSpecifyPreinstalledNodeJsShared (driver , tmpDir );
129+ }
130+
131+ @ Test
132+ void canSpecifyPreinstalledNodeJsAsEnv (@ TempDir Path tmpDir ) throws IOException , URISyntaxException , InterruptedException {
133+ String nodePath = extractNodeJsToTemp ();
134+ Driver driver = Driver .createAndInstall (singletonMap (PLAYWRIGHT_NODEJS_PATH , nodePath ), false );
135+ canSpecifyPreinstalledNodeJsShared (driver , tmpDir );
136+ }
129137
130- field .set (Driver .class , value );
138+
139+ private static String extractNodeJsToTemp () throws URISyntaxException , IOException {
140+ DriverJar auxDriver = new DriverJar ();
141+ auxDriver .extractDriverToTempDir ();
142+ String nodePath = auxDriver .driverPath ().getParent ().resolve (isWindows () ? "node.exe" : "node" ).toString ();
143+ return nodePath ;
144+ }
145+
146+ private static boolean isWindows () {
147+ String name = System .getProperty ("os.name" ).toLowerCase ();
148+ return name .contains ("win" );
149+ }
150+
151+ private static void canSpecifyPreinstalledNodeJsShared (Driver driver , Path tmpDir ) throws IOException , URISyntaxException , InterruptedException {
152+ Path builtinNode = driver .driverPath ().getParent ().resolve ("node" );
153+ assertFalse (Files .exists (builtinNode ), builtinNode .toString ());
154+ Path builtinNodeExe = driver .driverPath ().getParent ().resolve ("node.exe" );
155+ assertFalse (Files .exists (builtinNodeExe ), builtinNodeExe .toString ());
156+
157+ ProcessBuilder pb = driver .createProcessBuilder ();
158+ pb .command ().add ("--version" );
159+ pb .redirectError (ProcessBuilder .Redirect .INHERIT );
160+ Path out = tmpDir .resolve ("out.txt" );
161+ pb .redirectOutput (out .toFile ());
162+ Process p = pb .start ();
163+ boolean result = p .waitFor (1 , TimeUnit .MINUTES );
164+ assertTrue (result , "Timed out waiting for version to be printed" );
165+ String stdout = new String (Files .readAllBytes (out ), StandardCharsets .UTF_8 );
166+ assertTrue (stdout .contains ("Version " ), stdout );
131167 }
132168}
0 commit comments