Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6.x] Add support for Mac ARM64 architecture #876

Merged
merged 4 commits into from
Feb 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,28 @@ on:
jobs:
tests:
runs-on: ubuntu-latest

strategy:
fail-fast: true
matrix:
php: [7.2, 7.3, 7.4, 8.0]
laravel: [^6.0, ^7.0, ^8.0]
phpunit: [^7.5, ^8.4, ^9.0]
phpunit: [^8.4, ^9.0]
include:
- php: 7.2
laravel: ^6.0
phpunit: ^7.5
- php: 7.3
laravel: ^6.0
phpunit: ^7.5
- php: 7.4
laravel: ^6.0
phpunit: ^7.5
exclude:
- php: 7.2
phpunit: ^9.0
- php: 7.2
laravel: ^8.0
- php: 8.0
phpunit: ^7.5
- php: 8.0
phpunit: ^8.4

Expand Down
1 change: 1 addition & 0 deletions bin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
chromedriver-*
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
},
"require-dev": {
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^7.5.15|^8.4|^9.0"
"phpunit/phpunit": "^7.5.15|^8.4|^9.0",
"orchestra/testbench": "^4.16|^5.17.1|^6.12.1"
},
"suggest": {
"ext-pcntl": "Used to gracefully terminate Dusk when tests are running."
Expand Down
28 changes: 20 additions & 8 deletions src/Chrome/ChromeProcess.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@ public function toProcess(array $arguments = [])
return $this->process($arguments);
}

if ($this->onWindows()) {
$this->driver = realpath(__DIR__.'/../../bin/chromedriver-win.exe');
} elseif ($this->onMac()) {
$this->driver = realpath(__DIR__.'/../../bin/chromedriver-mac');
} else {
$this->driver = realpath(__DIR__.'/../../bin/chromedriver-linux');
}
$filenames = [
'linux' => 'chromedriver-linux',
'mac' => 'chromedriver-mac',
'mac-intel' => 'chromedriver-mac-intel',
'mac-arm' => 'chromedriver-mac-arm',
'win' => 'chromedriver-win.exe',
];

$this->driver = realpath(__DIR__.'/../../bin').DIRECTORY_SEPARATOR.$filenames[$this->operatingSystemId()];

return $this->process($arguments);
}
Expand All @@ -64,7 +66,7 @@ public function toProcess(array $arguments = [])
protected function process(array $arguments = [])
{
return new Process(
array_merge([realpath($this->driver)], $arguments), null, $this->chromeEnvironment()
array_merge([$this->driver], $arguments), null, $this->chromeEnvironment()
);
}

Expand Down Expand Up @@ -101,4 +103,14 @@ protected function onMac()
{
return OperatingSystem::onMac();
}

/**
* Determine OS ID.
*
* @return string
*/
protected function operatingSystemId()
{
return OperatingSystem::id();
}
}
8 changes: 8 additions & 0 deletions src/Console/ChromeDriverCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class ChromeDriverCommand extends Command
protected $slugs = [
'linux' => 'linux64',
'mac' => 'mac64',
'mac-intel' => 'mac64',
'mac-arm' => 'mac64_m1',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mac key will remain for fallback in case architecture value doesn't match x86_64 or arm64.

'win' => 'win32',
];

Expand Down Expand Up @@ -119,6 +121,12 @@ class ChromeDriverCommand extends Command
'mac' => [
'/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version',
],
'mac-intel' => [
'/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version',
],
'mac-arm' => [
'/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version',
],
'win' => [
'reg query "HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon" /v version',
],
Expand Down
25 changes: 24 additions & 1 deletion src/OperatingSystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ class OperatingSystem
*/
public static function id()
{
return static::onWindows() ? 'win' : (static::onMac() ? 'mac' : 'linux');
if (static::onWindows()) {
return 'win';
} elseif (static::onMac()) {
return static::macArchitectureId();
}

return 'linux';
}

/**
Expand All @@ -35,4 +41,21 @@ public static function onMac()
{
return PHP_OS === 'Darwin';
}

/**
* Mac platform architecture.
*
* @return string
*/
public static function macArchitectureId()
{
switch (php_uname('m')) {
case 'arm64':
return 'mac-arm';
case 'x86_64':
return 'mac-intel';
default:
return 'mac';
}
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This different from PR sent to master. Instead of having onMacIntel() and onMacArm() we can just stick with onMac() and then have a new method to return architecture value.

}
72 changes: 72 additions & 0 deletions tests/ChromeProcessTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,22 @@ public function test_build_process_for_darwin()
$this->assertStringContainsString('chromedriver-mac', $process->getCommandLine());
}

public function test_build_process_for_darwin_intel()
{
$process = (new ChromeProcessDarwinIntel)->toProcess();

$this->assertInstanceOf(Process::class, $process);
$this->assertStringContainsString('chromedriver-mac-intel', $process->getCommandLine());
}

public function test_build_process_for_darwin_arm()
{
$process = (new ChromeProcessDarwinArm)->toProcess();

$this->assertInstanceOf(Process::class, $process);
$this->assertStringContainsString('chromedriver-mac-arm', $process->getCommandLine());
}

public function test_build_process_for_linux()
{
$process = (new ChromeProcessLinux)->toProcess();
Expand All @@ -53,10 +69,20 @@ public function test_invalid_path()

class ChromeProcessWindows extends ChromeProcess
{
protected function onMac()
{
return false;
}

protected function onWindows()
{
return true;
}

protected function operatingSystemId()
{
return 'win';
}
}

class ChromeProcessDarwin extends ChromeProcess
Expand All @@ -70,6 +96,47 @@ protected function onWindows()
{
return false;
}

protected function operatingSystemId()
{
return 'mac';
}
}

class ChromeProcessDarwinIntel extends ChromeProcess
{
protected function onMac()
{
return true;
}

protected function onWindows()
{
return false;
}

protected function operatingSystemId()
{
return 'mac-intel';
}
}

class ChromeProcessDarwinArm extends ChromeProcess
{
protected function onMac()
{
return true;
}

protected function onWindows()
{
return false;
}

protected function operatingSystemId()
{
return 'mac-arm';
}
}

class ChromeProcessLinux extends ChromeProcess
Expand All @@ -83,4 +150,9 @@ protected function onWindows()
{
return false;
}

protected function operatingSystemId()
{
return 'linux';
}
}
29 changes: 29 additions & 0 deletions tests/Concerns/SwapsUrlGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Laravel\Dusk\Tests\Concerns;

use Illuminate\Container\Container;
use Illuminate\Http\Request;
use Illuminate\Routing\RouteCollection;
use Illuminate\Routing\UrlGenerator;

trait SwapsUrlGenerator
{
protected function swapUrlGenerator()
{
Container::getInstance()->bind('url', function () {
return new class(new RouteCollection(), new Request()) extends UrlGenerator {
public function route($name, $parameters = [], $absolute = true)
{
$route = '/'.$name.'/'.implode('/', $parameters);

if ($absolute) {
$route = 'http://www.google.com'.$route;
}

return $route;
}
};
});
}
}
8 changes: 7 additions & 1 deletion tests/ElementResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@

class ElementResolverTest extends TestCase
{
protected function tearDown(): void
{
m::close();
}

/**
* @throws \Exception
*/
Expand Down Expand Up @@ -65,10 +70,11 @@ public function test_resolve_for_radio_selection_falls_back_to_selectors_without
public function test_resolve_for_radio_selection_throws_exception_without_id_and_without_value()
{
$driver = m::mock(stdClass::class);
$driver->shouldReceive('findElement')->once()->andReturn('foo');
$resolver = new ElementResolver($driver);

$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('No value was provided for radio button [foo].');

$resolver->resolveForRadioSelection('foo');
}

Expand Down
9 changes: 7 additions & 2 deletions tests/MakesAssertionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@

class MakesAssertionsTest extends TestCase
{
protected function tearDown(): void
{
m::close();
}

public function test_assert_title()
{
$driver = m::mock(stdClass::class);
Expand Down Expand Up @@ -875,7 +880,7 @@ public function test_assert_vue()
'? JSON.parse(JSON.stringify(el.__vueParentComponent.ctx)).foo'.
': el.__vue__.foo'
)
->once()
->twice()
->andReturn('foo');

$resolver = m::mock(stdClass::class);
Expand Down Expand Up @@ -928,7 +933,7 @@ public function test_assert_vue_is_not()
'? JSON.parse(JSON.stringify(el.__vueParentComponent.ctx)).foo'.
': el.__vue__.foo'
)
->once()
->twice()
->andReturn('foo');

$resolver = m::mock(stdClass::class);
Expand Down
Loading