diff --git a/bin/playwright-install b/bin/playwright-install index 3419d63..7e7b162 100755 --- a/bin/playwright-install +++ b/bin/playwright-install @@ -269,8 +269,8 @@ final class PlaywrightServerInstaller return match ($packageManager) { 'pnpm' => $hasPnpmLock - ? ['pnpm', 'install', '--prod', '--frozen-lockfile'] - : ['pnpm', 'install', '--prod', '--no-frozen-lockfile'], + ? ['pnpm', 'install', '--prod', '--frozen-lockfile', '--ignore-workspace', '--lockfile-dir', $this->serverDir] + : ['pnpm', 'install', '--prod', '--no-frozen-lockfile', '--ignore-workspace', '--lockfile-dir', $this->serverDir], 'yarn' => $hasYarnLock ? ['yarn', 'install', '--production', '--frozen-lockfile'] : ['yarn', 'install', '--production'], diff --git a/tests/Integration/Installer/PlaywrightInstallDependenciesTest.php b/tests/Integration/Installer/PlaywrightInstallDependenciesTest.php new file mode 100644 index 0000000..8847066 --- /dev/null +++ b/tests/Integration/Installer/PlaywrightInstallDependenciesTest.php @@ -0,0 +1,121 @@ +serverDir = $sandbox.'/bin'; + $this->stubBinDir = $sandbox.'/stub-bin'; + mkdir($this->serverDir); + mkdir($this->stubBinDir); + + copy($projectDir.'/bin/playwright-install', $this->serverDir.'/playwright-install'); + copy($projectDir.'/bin/package.json', $this->serverDir.'/package.json'); + symlink($projectDir.'/vendor', $this->serverDir.'/vendor'); + + $this->stubCommand('node', 'v20.0.0'); + $this->stubCommand('npm', '10.0.0'); + $this->stubCommand('pnpm', '10.0.0'); + } + + protected function tearDown(): void + { + $this->removeDirectory(\dirname($this->serverDir)); + } + + #[Test] + public function itIsolatesThePnpmInstallFromAnOuterWorkspace(): void + { + $process = $this->runInstaller(); + + $this->assertSame(0, $process->getExitCode(), $process->getErrorOutput()); + $this->assertStringContainsString( + "'pnpm' 'install' '--prod' '--no-frozen-lockfile' '--ignore-workspace' '--lockfile-dir' '{$this->serverDir}'", + $process->getOutput(), + ); + } + + #[Test] + public function itIsolatesThePnpmInstallFromAnOuterWorkspaceWhenALockfileExists(): void + { + touch($this->serverDir.'/pnpm-lock.yaml'); + + $process = $this->runInstaller(); + + $this->assertSame(0, $process->getExitCode(), $process->getErrorOutput()); + $this->assertStringContainsString( + "'pnpm' 'install' '--prod' '--frozen-lockfile' '--ignore-workspace' '--lockfile-dir' '{$this->serverDir}'", + $process->getOutput(), + ); + } + + private function runInstaller(string ...$arguments): Process + { + $process = new Process( + [\PHP_BINARY, $this->serverDir.'/playwright-install', '--dry-run', '--verbose', ...$arguments], + env: ['PATH' => $this->stubBinDir.\PATH_SEPARATOR.getenv('PATH')], + ); + $process->run(); + + return $process; + } + + private function stubCommand(string $name, string $version): void + { + $path = $this->stubBinDir.'/'.$name; + + file_put_contents($path, "#!/bin/sh\necho {$version}\n"); + \chmod($path, 0o755); + } + + private function removeDirectory(string $directory): void + { + foreach (scandir($directory) ?: [] as $entry) { + if ('.' === $entry || '..' === $entry) { + continue; + } + + $path = $directory.'/'.$entry; + + if (is_dir($path) && !is_link($path)) { + $this->removeDirectory($path); + + continue; + } + + unlink($path); + } + + rmdir($directory); + } +}