77use Mockery ;
88use Hyde \Testing \UnitTestCase ;
99use Hyde \Foundation \HydeKernel ;
10+ use Illuminate \Process \Factory ;
1011use Illuminate \Console \OutputStyle ;
1112use Hyde \Console \Commands \ServeCommand ;
1213use Illuminate \Support \Facades \Process ;
@@ -26,6 +27,18 @@ protected function setUp(): void
2627 'hyde.server.host ' => 'localhost ' ,
2728 'hyde.server.port ' => 8080 ,
2829 ]);
30+
31+ Process::swap (new Factory ());
32+ Process::preventStrayProcesses ();
33+ }
34+
35+ protected function tearDown (): void
36+ {
37+ $ this ->addToAssertionCount (Mockery::getContainer ()->mockery_getExpectationCount ());
38+
39+ Mockery::close ();
40+
41+ parent ::tearDown ();
2942 }
3043
3144 public function testGetHostSelection ()
@@ -210,34 +223,35 @@ public function testWithOpenArgument()
210223 {
211224 HydeKernel::setInstance (new HydeKernel ());
212225
213- $ command = new class (['open ' => true ]) extends ServeCommandMock
214- {
215- public bool $ openInBrowserCalled = false ;
226+ $ command = $ this ->getOpenServeCommandMock (['open ' => true ]);
216227
217- // Void unrelated methods
218- protected function configureOutput (): void
219- {
220- }
228+ $ command ->safeHandle ();
221229
222- protected function printStartMessage (): void
223- {
224- }
230+ $ this ->assertTrue ($ command ->openInBrowserCalled );
231+ }
225232
226- protected function runServerProcess ( string $ command ): void
227- {
228- }
233+ public function testWithOpenArgumentWhenString ()
234+ {
235+ HydeKernel:: setInstance ( new HydeKernel ());
229236
230- protected function openInBrowser (): void
231- {
232- $ this ->openInBrowserCalled = true ;
233- }
234- };
237+ $ command = $ this ->getOpenServeCommandMock (['open ' => '' ]);
235238
236239 $ command ->safeHandle ();
237240
238241 $ this ->assertTrue ($ command ->openInBrowserCalled );
239242 }
240243
244+ public function testWithOpenArgumentWhenPath ()
245+ {
246+ HydeKernel::setInstance (new HydeKernel ());
247+
248+ $ command = $ this ->getOpenServeCommandMock (['open ' => 'dashboard ' ]);
249+
250+ $ command ->safeHandle ();
251+
252+ $ this ->assertSame ('dashboard ' , $ command ->openInBrowserPath );
253+ }
254+
241255 public function testOpenInBrowser ()
242256 {
243257 $ output = $ this ->createMock (OutputStyle::class);
@@ -246,11 +260,7 @@ public function testOpenInBrowser()
246260 $ command = $ this ->getMock (['--open ' => true ]);
247261 $ command ->setOutput ($ output );
248262
249- $ binary = match (PHP_OS_FAMILY ) {
250- 'Darwin ' => 'open ' ,
251- 'Windows ' => 'start ' ,
252- default => 'xdg-open ' ,
253- };
263+ $ binary = $ this ->getTestRunnerBinary ();
254264
255265 Process::shouldReceive ('command ' )->once ()->with ("$ binary http://localhost:8080 " )->andReturnSelf ();
256266 Process::shouldReceive ('run ' )->once ()->andReturnSelf ();
@@ -259,6 +269,31 @@ public function testOpenInBrowser()
259269 $ command ->openInBrowser ();
260270 }
261271
272+ public function testOpenInBrowserWithPath ()
273+ {
274+ Process::shouldReceive ('command ' )->once ()->with ("{$ this ->getTestRunnerBinary ()} http://localhost:8080/dashboard " )->andReturnSelf ();
275+ Process::shouldReceive ('run ' )->once ()->andReturnSelf ();
276+ Process::shouldReceive ('failed ' )->once ()->andReturn (false );
277+
278+ $ this ->getMock ()->openInBrowser ('dashboard ' );
279+ }
280+
281+ public function testOpenInBrowserWithPathNormalizesPaths ()
282+ {
283+ Process::shouldReceive ('run ' )->andReturnSelf ();
284+ Process::shouldReceive ('failed ' )->andReturn (false );
285+
286+ Process::shouldReceive ('command ' )->times (3 )->with ("{$ this ->getTestRunnerBinary ()} http://localhost:8080 " )->andReturnSelf ();
287+ Process::shouldReceive ('command ' )->once ()->with ("{$ this ->getTestRunnerBinary ()} http://localhost:8080/dashboard " )->andReturnSelf ();
288+ Process::shouldReceive ('command ' )->once ()->with ("{$ this ->getTestRunnerBinary ()} http://localhost:8080/foo/bar " )->andReturnSelf ();
289+
290+ $ this ->getMock ()->openInBrowser ('' );
291+ $ this ->getMock ()->openInBrowser ('/ ' );
292+ $ this ->getMock ()->openInBrowser ('// ' );
293+ $ this ->getMock ()->openInBrowser ('dashboard/ ' );
294+ $ this ->getMock ()->openInBrowser ('foo/bar/ ' );
295+ }
296+
262297 public function testOpenInBrowserThatFails ()
263298 {
264299 $ output = Mockery::mock (OutputStyle::class);
@@ -274,28 +309,57 @@ public function testOpenInBrowserThatFails()
274309 $ command = $ this ->getMock (['--open ' => true ]);
275310 $ command ->setOutput ($ output );
276311
277- $ binary = match (PHP_OS_FAMILY ) {
278- 'Darwin ' => 'open ' ,
279- 'Windows ' => 'start ' ,
280- default => 'xdg-open ' ,
281- };
312+ $ binary = $ this ->getTestRunnerBinary ();
282313
283314 Process::shouldReceive ('command ' )->once ()->with ("$ binary http://localhost:8080 " )->andReturnSelf ();
284315 Process::shouldReceive ('run ' )->once ()->andReturnSelf ();
285316 Process::shouldReceive ('failed ' )->once ()->andReturn (true );
286317 Process::shouldReceive ('errorOutput ' )->once ()->andReturn ("Missing suitable 'open' binary. " );
287318
288319 $ command ->openInBrowser ();
320+ }
289321
290- Mockery::close ();
291-
292- $ this ->assertTrue (true );
322+ protected function getTestRunnerBinary (): string
323+ {
324+ return match (PHP_OS_FAMILY ) {
325+ 'Darwin ' => 'open ' ,
326+ 'Windows ' => 'start ' ,
327+ default => 'xdg-open ' ,
328+ };
293329 }
294330
295331 protected function getMock (array $ options = []): ServeCommandMock
296332 {
297333 return new ServeCommandMock ($ options );
298334 }
335+
336+ protected function getOpenServeCommandMock (array $ arguments ): ServeCommandMock
337+ {
338+ return new class ($ arguments ) extends ServeCommandMock
339+ {
340+ public bool $ openInBrowserCalled = false ;
341+ public string $ openInBrowserPath = '' ;
342+
343+ // Void unrelated methods
344+ protected function configureOutput (): void
345+ {
346+ }
347+
348+ protected function printStartMessage (): void
349+ {
350+ }
351+
352+ protected function runServerProcess (string $ command ): void
353+ {
354+ }
355+
356+ protected function openInBrowser (string $ path = '/ ' ): void
357+ {
358+ $ this ->openInBrowserCalled = true ;
359+ $ this ->openInBrowserPath = $ path ;
360+ }
361+ };
362+ }
299363}
300364
301365/**
@@ -304,7 +368,7 @@ protected function getMock(array $options = []): ServeCommandMock
304368 * @method getEnvironmentVariables
305369 * @method parseEnvironmentOption(string $name)
306370 * @method checkArgvForOption(string $name)
307- * @method openInBrowser()
371+ * @method openInBrowser(string $path = '/' )
308372 */
309373class ServeCommandMock extends ServeCommand
310374{
0 commit comments