From 93c681305cfbd670c2fec9b2d63596d92f8472fc Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 26 Apr 2019 13:22:25 +0200 Subject: [PATCH 1/4] Cleanup toProcess method --- src/Chrome/ChromeProcess.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Chrome/ChromeProcess.php b/src/Chrome/ChromeProcess.php index e07e2eb3b..d8b1666d7 100644 --- a/src/Chrome/ChromeProcess.php +++ b/src/Chrome/ChromeProcess.php @@ -44,14 +44,12 @@ public function toProcess(array $arguments = []) if ($this->onWindows()) { $this->driver = realpath(__DIR__.'/../../bin/chromedriver-win.exe'); - - return $this->process($arguments); + } elseif ($this->onMac()) { + $this->driver = realpath(__DIR__.'/../../bin/chromedriver-mac'); + } else { + $this->driver = realpath(__DIR__.'/../../bin/chromedriver-linux'); } - $this->driver = $this->onMac() - ? realpath(__DIR__.'/../../bin/chromedriver-mac') - : realpath(__DIR__.'/../../bin/chromedriver-linux'); - return $this->process($arguments); } From ae27d7ee9d975e86617235b8733928e5d954e7df Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 26 Apr 2019 13:24:04 +0200 Subject: [PATCH 2/4] Remove unnecessary construct override --- src/Console/InstallCommand.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index 158cf66e2..9c36d54ce 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -20,16 +20,6 @@ class InstallCommand extends Command */ protected $description = 'Install Dusk into the application'; - /** - * Create a new command instance. - * - * @return void - */ - public function __construct() - { - parent::__construct(); - } - /** * Execute the console command. * From e60d567802a6ea4d8f6cca7b90a91569f1066acc Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 26 Apr 2019 16:32:34 +0200 Subject: [PATCH 3/4] Add ChromeDriver command This command will allow users to update their chrome driver for their OS. It has a flag that will also allow users to update every binary if they want. I've added this to the install command so the driver is updated whenever the install command is run. This means we don't have to update the docs. I wrote this as an install command so we can remove the binaries in a future version of Dusk and always have them installed with this command. This will save having them to be packaged with the repo. It's also written in such a way that it only installs the binary for the current OS. Fixes https://github.com/laravel/dusk/issues/641 --- LICENSE.md | 1 + composer.json | 2 + src/Chrome/ChromeProcess.php | 6 +- src/Console/ChromeDriverCommand.php | 220 ++++++++++++++++++++++++++++ src/Console/InstallCommand.php | 4 + src/DuskServiceProvider.php | 3 +- src/OperatingSystem.php | 38 +++++ 7 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 src/Console/ChromeDriverCommand.php create mode 100644 src/OperatingSystem.php diff --git a/LICENSE.md b/LICENSE.md index 79810c848..656e4b794 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,7 @@ The MIT License (MIT) Copyright (c) Taylor Otwell +Copyright (c) Jonas Staudenmeir Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/composer.json b/composer.json index e73af996e..8158e73d7 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,8 @@ ], "require": { "php": ">=7.1.0", + "ext-json": "*", + "ext-zip": "*", "facebook/webdriver": "^1.3", "nesbot/carbon": "^1.20|^2.0", "illuminate/console": "~5.7.0|~5.8.0|~5.9.0", diff --git a/src/Chrome/ChromeProcess.php b/src/Chrome/ChromeProcess.php index d8b1666d7..db44e1633 100644 --- a/src/Chrome/ChromeProcess.php +++ b/src/Chrome/ChromeProcess.php @@ -3,7 +3,7 @@ namespace Laravel\Dusk\Chrome; use RuntimeException; -use Illuminate\Support\Str; +use Laravel\Dusk\OperatingSystem; use Symfony\Component\Process\Process; class ChromeProcess @@ -87,7 +87,7 @@ protected function chromeEnvironment() */ protected function onWindows() { - return PHP_OS === 'WINNT' || Str::contains(php_uname(), 'Microsoft'); + return OperatingSystem::onWindows(); } /** @@ -97,6 +97,6 @@ protected function onWindows() */ protected function onMac() { - return PHP_OS === 'Darwin'; + return OperatingSystem::onMac(); } } diff --git a/src/Console/ChromeDriverCommand.php b/src/Console/ChromeDriverCommand.php new file mode 100644 index 000000000..1784ebee6 --- /dev/null +++ b/src/Console/ChromeDriverCommand.php @@ -0,0 +1,220 @@ + 'linux64', + 'mac' => 'mac64', + 'win' => 'win32', + ]; + + /** + * The legacy versions for the ChromeDriver. + * + * @var array + */ + protected $legacyVersions = [ + 43 => '2.20', + 44 => '2.20', + 45 => '2.20', + 46 => '2.21', + 47 => '2.21', + 48 => '2.21', + 49 => '2.22', + 50 => '2.22', + 51 => '2.23', + 52 => '2.24', + 53 => '2.26', + 54 => '2.27', + 55 => '2.28', + 56 => '2.29', + 57 => '2.29', + 58 => '2.31', + 59 => '2.32', + 60 => '2.33', + 61 => '2.34', + 62 => '2.35', + 63 => '2.36', + 64 => '2.37', + 65 => '2.38', + 66 => '2.40', + 67 => '2.41', + 68 => '2.42', + 69 => '2.44', + ]; + + /** + * Path to the bin directory. + * + * @var string + */ + protected $directory = __DIR__.'/../../bin/'; + + /** + * Execute the console command. + * + * @return void + */ + public function handle() + { + $version = $this->version(); + $all = $this->option('all'); + $currentOS = OperatingSystem::id(); + + foreach ($this->slugs as $os => $slug) { + if ($all || ($os === $currentOS)) { + $archive = $this->download($version, $slug); + + $binary = $this->extract($archive); + + $this->rename($binary, $os); + } + } + + $message = 'ChromeDriver %s successfully installed for version %s.'; + + $this->info(sprintf($message, $all ? 'binaries' : 'binary', $version)); + } + + /** + * Get the desired ChromeDriver version. + * + * @return string + */ + protected function version() + { + $version = $this->argument('version'); + + if ($version) { + if (! ctype_digit($version)) { + return $version; + } + + $version = (int) $version; + + if ($version < 70) { + return $this->legacyVersions[$version]; + } + } else { + $version = $this->latestChromeVersion(); + } + + $url = sprintf($this->versionUrl, $version); + + return trim(file_get_contents($url)); + } + + /** + * Get the latest major Chrome version. + * + * @return int + */ + protected function latestChromeVersion() + { + $index = file_get_contents($this->indexUrl); + + preg_match('#.*LATEST_RELEASE_(\d+)#', $index, $matches); + + return (int) $matches[1]; + } + + /** + * Download the ChromeDriver archive. + * + * @param string $version + * @param string $slug + * @return string + */ + protected function download($version, $slug) + { + $archive = $this->directory.'chromedriver.zip'; + $url = sprintf($this->downloadUrl, $version, $slug); + + file_put_contents($archive, fopen($url, 'r')); + + return $archive; + } + + /** + * Extract the ChromeDriver binary from the archive and delete the archive. + * + * @param string $archive + * @return string + */ + protected function extract($archive) + { + $zip = new ZipArchive; + $zip->open($archive); + $zip->extractTo($this->directory); + + $binary = $zip->getNameIndex(0); + + $zip->close(); + + unlink($archive); + + return $binary; + } + + /** + * Rename the ChromeDriver binary and make it executable. + * + * @param string $binary + * @param string $os + * @return void + */ + protected function rename($binary, $os) + { + $newName = str_replace('chromedriver', 'chromedriver-'.$os, $binary); + + rename($this->directory.$binary, $this->directory.$newName); + + chmod($this->directory.$newName, 0755); + } +} diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index 9c36d54ce..1dffe4226 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -57,6 +57,10 @@ public function handle() } $this->info('Dusk scaffolding installed successfully.'); + + $this->info('Installing ChromeDriver binaries...'); + + $this->call('dusk:chrome-driver', ['--all']); } /** diff --git a/src/DuskServiceProvider.php b/src/DuskServiceProvider.php index c612201d9..156a4f305 100644 --- a/src/DuskServiceProvider.php +++ b/src/DuskServiceProvider.php @@ -35,7 +35,7 @@ public function boot() * Register any package services. * * @return void - * @throws Exception + * @throws \Exception */ public function register() { @@ -51,6 +51,7 @@ public function register() Console\MakeCommand::class, Console\PageCommand::class, Console\ComponentCommand::class, + Console\ChromeDriverCommand::class, ]); } } diff --git a/src/OperatingSystem.php b/src/OperatingSystem.php new file mode 100644 index 000000000..d32a99c84 --- /dev/null +++ b/src/OperatingSystem.php @@ -0,0 +1,38 @@ + Date: Fri, 26 Apr 2019 21:21:23 +0200 Subject: [PATCH 4/4] Make sure all option is executed --- src/Console/InstallCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index 1dffe4226..dd672391d 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -60,7 +60,7 @@ public function handle() $this->info('Installing ChromeDriver binaries...'); - $this->call('dusk:chrome-driver', ['--all']); + $this->call('dusk:chrome-driver', ['--all' => true]); } /**