updated-packages
This commit is contained in:
164
vendor/laravel/dusk/src/Browser.php
vendored
164
vendor/laravel/dusk/src/Browser.php
vendored
@@ -2,12 +2,14 @@
|
||||
|
||||
namespace Laravel\Dusk;
|
||||
|
||||
use Closure;
|
||||
use BadMethodCallException;
|
||||
use Closure;
|
||||
use Facebook\WebDriver\Remote\WebDriverBrowserType;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
use Facebook\WebDriver\WebDriverDimension;
|
||||
use Facebook\WebDriver\WebDriverPoint;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Facebook\WebDriver\WebDriverDimension;
|
||||
use Facebook\WebDriver\Remote\WebDriverBrowserType;
|
||||
|
||||
class Browser
|
||||
{
|
||||
@@ -17,6 +19,7 @@ class Browser
|
||||
Concerns\InteractsWithJavascript,
|
||||
Concerns\InteractsWithMouse,
|
||||
Concerns\MakesAssertions,
|
||||
Concerns\MakesUrlAssertions,
|
||||
Concerns\WaitsForElements,
|
||||
Macroable {
|
||||
__call as macroCall;
|
||||
@@ -43,6 +46,13 @@ class Browser
|
||||
*/
|
||||
public static $storeConsoleLogAt;
|
||||
|
||||
/**
|
||||
* The directory where source code snapshots will be stored.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $storeSourceAt;
|
||||
|
||||
/**
|
||||
* The browsers that support retrieving logs.
|
||||
*
|
||||
@@ -77,7 +87,7 @@ class Browser
|
||||
/**
|
||||
* The element resolver instance.
|
||||
*
|
||||
* @var ElementResolver
|
||||
* @var \Laravel\Dusk\ElementResolver
|
||||
*/
|
||||
public $resolver;
|
||||
|
||||
@@ -95,11 +105,18 @@ class Browser
|
||||
*/
|
||||
public $component;
|
||||
|
||||
/**
|
||||
* Indicates that the browser should be resized to fit the entire "body" before screenshotting failures.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $fitOnFailure = true;
|
||||
|
||||
/**
|
||||
* Create a browser instance.
|
||||
*
|
||||
* @param \Facebook\WebDriver\Remote\RemoteWebDriver $driver
|
||||
* @param ElementResolver $resolver
|
||||
* @param \Laravel\Dusk\ElementResolver $resolver
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($driver, $resolver = null)
|
||||
@@ -164,6 +181,21 @@ class Browser
|
||||
* @return $this
|
||||
*/
|
||||
public function on($page)
|
||||
{
|
||||
$this->onWithoutAssert($page);
|
||||
|
||||
$page->assert($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current page object without executing the assertions.
|
||||
*
|
||||
* @param mixed $page
|
||||
* @return $this
|
||||
*/
|
||||
public function onWithoutAssert($page)
|
||||
{
|
||||
$this->page = $page;
|
||||
|
||||
@@ -174,8 +206,6 @@ class Browser
|
||||
$page::siteElements(), $page->elements()
|
||||
));
|
||||
|
||||
$page->assert($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -231,6 +261,81 @@ class Browser
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the browser window as large as the content.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function fitContent()
|
||||
{
|
||||
$this->driver->switchTo()->defaultContent();
|
||||
|
||||
$html = $this->driver->findElement(WebDriverBy::tagName('html'));
|
||||
|
||||
if (! empty($html) && ($html->getSize()->getWidth() <= 0 || $html->getSize()->getHeight() <= 0)) {
|
||||
$this->resize($html->getSize()->getWidth(), $html->getSize()->getHeight());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable fit on failures.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function disableFitOnFailure()
|
||||
{
|
||||
$this->fitOnFailure = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable fit on failures.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function enableFitOnFailure()
|
||||
{
|
||||
$this->fitOnFailure = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the browser window.
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @return $this
|
||||
*/
|
||||
public function move($x, $y)
|
||||
{
|
||||
$this->driver->manage()->window()->setPosition(
|
||||
new WebDriverPoint($x, $y)
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll screen to element at the given selector.
|
||||
*
|
||||
* @param string $selector
|
||||
* @return $this
|
||||
*/
|
||||
public function scrollTo($selector)
|
||||
{
|
||||
$this->ensurejQueryIsAvailable();
|
||||
|
||||
$selector = addslashes($this->resolver->format($selector));
|
||||
|
||||
$this->driver->executeScript("jQuery(\"html, body\").animate({scrollTop: jQuery(\"$selector\").offset().top}, 0);");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a screenshot and store it with the given name.
|
||||
*
|
||||
@@ -239,9 +344,15 @@ class Browser
|
||||
*/
|
||||
public function screenshot($name)
|
||||
{
|
||||
$this->driver->takeScreenshot(
|
||||
sprintf('%s/%s.png', rtrim(static::$storeScreenshotsAt, '/'), $name)
|
||||
);
|
||||
$filePath = sprintf('%s/%s.png', rtrim(static::$storeScreenshotsAt, '/'), $name);
|
||||
|
||||
$directoryPath = dirname($filePath);
|
||||
|
||||
if (! is_dir($directoryPath)) {
|
||||
mkdir($directoryPath, 0777, true);
|
||||
}
|
||||
|
||||
$this->driver->takeScreenshot($filePath);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -257,10 +368,9 @@ class Browser
|
||||
if (in_array($this->driver->getCapabilities()->getBrowserName(), static::$supportsRemoteLogs)) {
|
||||
$console = $this->driver->manage()->getLog('browser');
|
||||
|
||||
if (!empty($console)) {
|
||||
if (! empty($console)) {
|
||||
file_put_contents(
|
||||
sprintf('%s/%s.log', rtrim(static::$storeConsoleLogAt, '/'), $name)
|
||||
, json_encode($console, JSON_PRETTY_PRINT)
|
||||
sprintf('%s/%s.log', rtrim(static::$storeConsoleLogAt, '/'), $name), json_encode($console, JSON_PRETTY_PRINT)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -269,9 +379,29 @@ class Browser
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to a specified frame in the browser.
|
||||
* Store a snapshot of the page's current source code with the given name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function storeSource($name)
|
||||
{
|
||||
$source = $this->driver->getPageSource();
|
||||
|
||||
if (! empty($source)) {
|
||||
file_put_contents(
|
||||
sprintf('%s/%s.txt', rtrim(static::$storeSourceAt, '/'), $name), $source
|
||||
);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to a specified frame in the browser and execute the given callback.
|
||||
*
|
||||
* @param string $selector
|
||||
* @param \Closure $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function withinFrame($selector, Closure $callback)
|
||||
@@ -311,7 +441,7 @@ class Browser
|
||||
);
|
||||
|
||||
if ($this->page) {
|
||||
$browser->on($this->page);
|
||||
$browser->onWithoutAssert($this->page);
|
||||
}
|
||||
|
||||
if ($selector instanceof Component) {
|
||||
@@ -355,7 +485,7 @@ class Browser
|
||||
*/
|
||||
public function ensurejQueryIsAvailable()
|
||||
{
|
||||
if ($this->driver->executeScript("return window.jQuery == null")) {
|
||||
if ($this->driver->executeScript('return window.jQuery == null')) {
|
||||
$this->driver->executeScript(file_get_contents(__DIR__.'/../bin/jquery.js'));
|
||||
}
|
||||
}
|
||||
@@ -439,6 +569,8 @@ class Browser
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
|
||||
38
vendor/laravel/dusk/src/Chrome/ChromeProcess.php
vendored
38
vendor/laravel/dusk/src/Chrome/ChromeProcess.php
vendored
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace Laravel\Dusk\Chrome;
|
||||
|
||||
use Laravel\Dusk\OperatingSystem;
|
||||
use RuntimeException;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class ChromeProcess
|
||||
@@ -11,7 +11,7 @@ class ChromeProcess
|
||||
/**
|
||||
* The path to the Chromedriver.
|
||||
*
|
||||
* @var String
|
||||
* @var string
|
||||
*/
|
||||
protected $driver;
|
||||
|
||||
@@ -20,6 +20,8 @@ class ChromeProcess
|
||||
*
|
||||
* @param string $driver
|
||||
* @return void
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __construct($driver = null)
|
||||
{
|
||||
@@ -33,37 +35,37 @@ class ChromeProcess
|
||||
/**
|
||||
* Build the process to run Chromedriver.
|
||||
*
|
||||
* @param array $arguments
|
||||
* @return \Symfony\Component\Process\Process
|
||||
*/
|
||||
public function toProcess()
|
||||
public function toProcess(array $arguments = [])
|
||||
{
|
||||
if ($this->driver) {
|
||||
return $this->process();
|
||||
return $this->process($arguments);
|
||||
}
|
||||
|
||||
if ($this->onWindows()) {
|
||||
$this->driver = realpath(__DIR__.'/../../bin/chromedriver-win.exe');
|
||||
|
||||
return $this->process();
|
||||
} 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();
|
||||
return $this->process($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Chromedriver with Symfony Process.
|
||||
*
|
||||
* @param array $arguments
|
||||
* @return \Symfony\Component\Process\Process
|
||||
*/
|
||||
protected function process()
|
||||
protected function process(array $arguments = [])
|
||||
{
|
||||
return (new Process(
|
||||
[realpath($this->driver)], null, $this->chromeEnvironment()
|
||||
));
|
||||
return new Process(
|
||||
array_merge([realpath($this->driver)], $arguments), null, $this->chromeEnvironment()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +79,7 @@ class ChromeProcess
|
||||
return [];
|
||||
}
|
||||
|
||||
return ['DISPLAY' => ':0'];
|
||||
return ['DISPLAY' => $_ENV['DISPLAY'] ?? ':0'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +89,7 @@ class ChromeProcess
|
||||
*/
|
||||
protected function onWindows()
|
||||
{
|
||||
return PHP_OS === 'WINNT' || Str::contains(php_uname(), 'Microsoft');
|
||||
return OperatingSystem::onWindows();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,6 +99,6 @@ class ChromeProcess
|
||||
*/
|
||||
protected function onMac()
|
||||
{
|
||||
return PHP_OS === 'Darwin';
|
||||
return OperatingSystem::onMac();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,14 @@ trait SupportsChrome
|
||||
/**
|
||||
* Start the Chromedriver process.
|
||||
*
|
||||
* @throws \RuntimeException if the driver file path doesn't exist.
|
||||
*
|
||||
* @param array $arguments
|
||||
* @return void
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function startChromeDriver()
|
||||
public static function startChromeDriver(array $arguments = [])
|
||||
{
|
||||
static::$chromeProcess = static::buildChromeProcess();
|
||||
static::$chromeProcess = static::buildChromeProcess($arguments);
|
||||
|
||||
static::$chromeProcess->start();
|
||||
|
||||
@@ -51,13 +52,14 @@ trait SupportsChrome
|
||||
/**
|
||||
* Build the process to run the Chromedriver.
|
||||
*
|
||||
*
|
||||
* @param array $arguments
|
||||
* @return \Symfony\Component\Process\Process
|
||||
* @throws \RuntimeException if the driver file path doesn't exist.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected static function buildChromeProcess()
|
||||
protected static function buildChromeProcess(array $arguments = [])
|
||||
{
|
||||
return (new ChromeProcess(static::$chromeDriver))->toProcess();
|
||||
return (new ChromeProcess(static::$chromeDriver))->toProcess($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@ trait InteractsWithAuthentication
|
||||
* Log into the application using a given user ID or email.
|
||||
*
|
||||
* @param object|string $userId
|
||||
* @param string $guard
|
||||
* @param string $guard
|
||||
* @return $this
|
||||
*/
|
||||
public function loginAs($userId, $guard = null)
|
||||
|
||||
@@ -17,12 +17,12 @@ trait InteractsWithCookies
|
||||
*/
|
||||
public function cookie($name, $value = null, $expiry = null, array $options = [])
|
||||
{
|
||||
if ($value) {
|
||||
if (! is_null($value)) {
|
||||
return $this->addCookie($name, $value, $expiry, $options);
|
||||
}
|
||||
|
||||
if ($cookie = $this->driver->manage()->getCookieNamed($name)) {
|
||||
return decrypt(rawurldecode($cookie['value']));
|
||||
return decrypt(rawurldecode($cookie['value']), $unserialize = false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ trait InteractsWithCookies
|
||||
*/
|
||||
public function plainCookie($name, $value = null, $expiry = null, array $options = [])
|
||||
{
|
||||
if ($value) {
|
||||
if (! is_null($value)) {
|
||||
return $this->addCookie($name, $value, $expiry, $options, false);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ trait InteractsWithCookies
|
||||
public function addCookie($name, $value, $expiry = null, array $options = [], $encrypt = true)
|
||||
{
|
||||
if ($encrypt) {
|
||||
$value = encrypt($value);
|
||||
$value = encrypt($value, $serialize = false);
|
||||
}
|
||||
|
||||
if ($expiry instanceof DateTimeInterface) {
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Facebook\WebDriver\Interactions\WebDriverActions;
|
||||
use Facebook\WebDriver\Remote\LocalFileDetector;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
use Facebook\WebDriver\WebDriverKeys;
|
||||
use Facebook\WebDriver\Remote\LocalFileDetector;
|
||||
use Facebook\WebDriver\Interactions\WebDriverActions;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait InteractsWithElements
|
||||
{
|
||||
@@ -39,11 +39,11 @@ trait InteractsWithElements
|
||||
* @param string $element
|
||||
* @return $this
|
||||
*/
|
||||
public function clickLink($link, $element = "a")
|
||||
public function clickLink($link, $element = 'a')
|
||||
{
|
||||
$this->ensurejQueryIsAvailable();
|
||||
|
||||
$selector = addslashes(trim($this->resolver->format("{$element}:contains({$link})")));
|
||||
$selector = addslashes(trim($this->resolver->format("{$element}:contains({$link}):visible")));
|
||||
|
||||
$this->driver->executeScript("jQuery.find(\"{$selector}\")[0].click();");
|
||||
|
||||
@@ -66,7 +66,7 @@ trait InteractsWithElements
|
||||
$selector = $this->resolver->format($selector);
|
||||
|
||||
$this->driver->executeScript(
|
||||
"document.querySelector('{$selector}').value = '{$value}';"
|
||||
'document.querySelector('.json_encode($selector).').value = '.json_encode($value).';'
|
||||
);
|
||||
|
||||
return $this;
|
||||
@@ -144,6 +144,21 @@ trait InteractsWithElements
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type the given value in the given field slowly.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @param int $pause
|
||||
* @return $this
|
||||
*/
|
||||
public function typeSlowly($field, $value, $pause = 100)
|
||||
{
|
||||
$this->clear($field)->appendSlowly($field, $value, $pause);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type the given value in the given field without clearing it.
|
||||
*
|
||||
@@ -158,6 +173,23 @@ trait InteractsWithElements
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type the given value in the given field slowly without clearing it.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @param int $pause
|
||||
* @return $this
|
||||
*/
|
||||
public function appendSlowly($field, $value, $pause = 100)
|
||||
{
|
||||
foreach (str_split($value) as $char) {
|
||||
$this->append($field, $char)->pause($pause);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the given field.
|
||||
*
|
||||
@@ -182,11 +214,15 @@ trait InteractsWithElements
|
||||
{
|
||||
$element = $this->resolver->resolveForSelection($field);
|
||||
|
||||
$options = $element->findElements(WebDriverBy::tagName('option'));
|
||||
$options = $element->findElements(WebDriverBy::cssSelector('option:not([disabled])'));
|
||||
|
||||
if (is_null($value)) {
|
||||
$options[array_rand($options)]->click();
|
||||
} else {
|
||||
if (is_bool($value)) {
|
||||
$value = $value ? '1' : '0';
|
||||
}
|
||||
|
||||
foreach ($options as $option) {
|
||||
if ((string) $option->getAttribute('value') === (string) $value) {
|
||||
$option->click();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Facebook\WebDriver\Interactions\WebDriverActions;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
|
||||
trait InteractsWithMouse
|
||||
{
|
||||
@@ -54,6 +55,21 @@ trait InteractsWithMouse
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the element at the given XPath expression.
|
||||
*
|
||||
* @param string $selector
|
||||
* @return $this
|
||||
*/
|
||||
public function clickAtXPath($expression)
|
||||
{
|
||||
$this->driver
|
||||
->findElement(WebDriverBy::xpath($expression))
|
||||
->click();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a mouse click and hold the mouse button down.
|
||||
*
|
||||
|
||||
378
vendor/laravel/dusk/src/Concerns/MakesAssertions.php
vendored
378
vendor/laravel/dusk/src/Concerns/MakesAssertions.php
vendored
@@ -2,10 +2,10 @@
|
||||
|
||||
namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Facebook\WebDriver\Exception\NoSuchElementException;
|
||||
use Facebook\WebDriver\Remote\RemoteWebElement;
|
||||
use Illuminate\Support\Str;
|
||||
use PHPUnit\Framework\Assert as PHPUnit;
|
||||
use Facebook\WebDriver\Remote\RemoteWebElement;
|
||||
use Facebook\WebDriver\Exception\NoSuchElementException;
|
||||
|
||||
trait MakesAssertions
|
||||
{
|
||||
@@ -41,233 +41,6 @@ trait MakesAssertions
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL matches the given URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @return $this
|
||||
*/
|
||||
public function assertUrlIs($url)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($url, '/'));
|
||||
|
||||
$segments = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
$currentUrl = sprintf(
|
||||
'%s://%s%s%s',
|
||||
$segments['scheme'],
|
||||
$segments['host'],
|
||||
array_get($segments, 'port', '') ? ':'.$segments['port'] : '',
|
||||
array_get($segments, 'path', '')
|
||||
);
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $currentUrl,
|
||||
"Actual URL [{$this->driver->getCurrentURL()}] does not equal expected URL [{$url}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path matches the given pattern.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathIs($path)
|
||||
{
|
||||
$pattern = preg_quote($path, '/');
|
||||
|
||||
$pattern = str_replace('\*', '.*', $pattern);
|
||||
|
||||
$actualPath = parse_url($this->driver->getCurrentURL())['path'];
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $actualPath,
|
||||
"Actual path [{$actualPath}] does not equal expected path [{$path}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path begins with given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathBeginsWith($path)
|
||||
{
|
||||
$actualPath = parse_url($this->driver->getCurrentURL())['path'];
|
||||
|
||||
PHPUnit::assertStringStartsWith(
|
||||
$path, $actualPath,
|
||||
"Actual path [{$actualPath}] does not begin with expected path [{$path}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path does not match the given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathIsNot($path)
|
||||
{
|
||||
$actualPath = parse_url($this->driver->getCurrentURL())['path'];
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$path, $actualPath,
|
||||
"Path [{$path}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment matches the given pattern.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentIs($fragment)
|
||||
{
|
||||
$pattern = preg_quote($fragment, '/');
|
||||
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.str_replace('\*', '.*', $pattern).'$/u', $actualFragment,
|
||||
"Actual fragment [{$actualFragment}] does not equal expected fragment [{$fragment}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment begins with given fragment.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentBeginsWith($fragment)
|
||||
{
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertStringStartsWith(
|
||||
$fragment, $actualFragment,
|
||||
"Actual fragment [$actualFragment] does not begin with expected fragment [$fragment]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment does not match the given fragment.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentIsNot($fragment)
|
||||
{
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$fragment, $actualFragment,
|
||||
"Fragment [{$fragment}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path matches the given route.
|
||||
*
|
||||
* @param string $route
|
||||
* @param array $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function assertRouteIs($route, $parameters = [])
|
||||
{
|
||||
return $this->assertPathIs(route($route, $parameters, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a query string parameter is present and has a given value.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertQueryStringHas($name, $value = null)
|
||||
{
|
||||
$output = $this->assertHasQueryStringParameter($name);
|
||||
|
||||
if (is_null($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
PHPUnit::assertEquals(
|
||||
$value, $output[$name],
|
||||
"Query string parameter [{$name}] had value [{$output[$name]}], but expected [{$value}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given query string parameter is missing.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function assertQueryStringMissing($name)
|
||||
{
|
||||
$parsedUrl = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
if (! array_key_exists('query', $parsedUrl)) {
|
||||
PHPUnit::assertTrue(true);
|
||||
return $this;
|
||||
}
|
||||
|
||||
parse_str($parsedUrl['query'], $output);
|
||||
|
||||
PHPUnit::assertArrayNotHasKey(
|
||||
$name, $output,
|
||||
"Found unexpected query string parameter [{$name}] in [".$this->driver->getCurrentURL()."]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given query string parameter is present.
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function assertHasQueryStringParameter($name)
|
||||
{
|
||||
$parsedUrl = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
PHPUnit::assertArrayHasKey(
|
||||
'query', $parsedUrl,
|
||||
"Did not see expected query string in [".$this->driver->getCurrentURL()."]."
|
||||
);
|
||||
|
||||
parse_str($parsedUrl['query'], $output);
|
||||
|
||||
PHPUnit::assertArrayHasKey(
|
||||
$name, $output,
|
||||
"Did not see expected query string parameter [{$name}] in [".$this->driver->getCurrentURL()."]."
|
||||
);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given cookie is present.
|
||||
*
|
||||
@@ -432,8 +205,8 @@ trait MakesAssertions
|
||||
*/
|
||||
public function assertSourceHas($code)
|
||||
{
|
||||
PHPUnit::assertContains(
|
||||
$code, $this->driver->getPageSource(),
|
||||
PHPUnit::assertTrue(
|
||||
Str::contains($this->driver->getPageSource(), $code),
|
||||
"Did not find expected source code [{$code}]"
|
||||
);
|
||||
|
||||
@@ -448,8 +221,8 @@ trait MakesAssertions
|
||||
*/
|
||||
public function assertSourceMissing($code)
|
||||
{
|
||||
PHPUnit::assertNotContains(
|
||||
$code, $this->driver->getPageSource(),
|
||||
PHPUnit::assertFalse(
|
||||
Str::contains($this->driver->getPageSource(), $code),
|
||||
"Found unexpected source code [{$code}]"
|
||||
);
|
||||
|
||||
@@ -682,8 +455,8 @@ JS;
|
||||
/**
|
||||
* Assert that the given array of values are available to be selected.
|
||||
*
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSelectHasOptions($field, array $values)
|
||||
@@ -696,7 +469,7 @@ JS;
|
||||
|
||||
PHPUnit::assertCount(
|
||||
count($values), $options,
|
||||
"Expected options [".implode(',', $values)."] for selection field [{$field}] to be available."
|
||||
'Expected options ['.implode(',', $values)."] for selection field [{$field}] to be available."
|
||||
);
|
||||
|
||||
return $this;
|
||||
@@ -705,15 +478,15 @@ JS;
|
||||
/**
|
||||
* Assert that the given array of values are not available to be selected.
|
||||
*
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSelectMissingOptions($field, array $values)
|
||||
{
|
||||
PHPUnit::assertCount(
|
||||
0, $this->resolver->resolveSelectOptions($field, $values),
|
||||
"Unexpected options [".implode(',', $values)."] for selection field [{$field}]."
|
||||
'Unexpected options ['.implode(',', $values)."] for selection field [{$field}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
@@ -722,8 +495,8 @@ JS;
|
||||
/**
|
||||
* Assert that the given value is available to be selected on the given field.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSelectHasOption($field, $value)
|
||||
@@ -734,8 +507,8 @@ JS;
|
||||
/**
|
||||
* Assert that the given value is not available to be selected on the given field.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSelectMissingOption($field, $value)
|
||||
@@ -752,9 +525,11 @@ JS;
|
||||
*/
|
||||
public function selected($field, $value)
|
||||
{
|
||||
$element = $this->resolver->resolveForSelection($field);
|
||||
$options = $this->resolver->resolveSelectOptions($field, (array) $value);
|
||||
|
||||
return (string) $element->getAttribute('value') === (string) $value;
|
||||
return collect($options)->contains(function (RemoteWebElement $option) {
|
||||
return $option->isSelected();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -773,6 +548,59 @@ JS;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the element at the given selector has the given attribute value.
|
||||
*
|
||||
* @param string $selector
|
||||
* @param string $attribute
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertAttribute($selector, $attribute, $value)
|
||||
{
|
||||
$fullSelector = $this->resolver->format($selector);
|
||||
|
||||
$actual = $this->resolver->findOrFail($selector)->getAttribute($attribute);
|
||||
|
||||
PHPUnit::assertNotNull(
|
||||
$actual,
|
||||
"Did not see expected attribute [{$attribute}] within element [{$fullSelector}]."
|
||||
);
|
||||
|
||||
PHPUnit::assertEquals(
|
||||
$value, $actual,
|
||||
"Expected '$attribute' attribute [{$value}] does not equal actual value [$actual]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the element at the given selector has the given data attribute value.
|
||||
*
|
||||
* @param string $selector
|
||||
* @param string $attribute
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertDataAttribute($selector, $attribute, $value)
|
||||
{
|
||||
return $this->assertAttribute($selector, 'data-'.$attribute, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the element at the given selector has the given aria attribute value.
|
||||
*
|
||||
* @param string $selector
|
||||
* @param string $attribute
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertAriaAttribute($selector, $attribute, $value)
|
||||
{
|
||||
return $this->assertAttribute($selector, 'aria-'.$attribute, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the element with the given selector is visible.
|
||||
*
|
||||
@@ -854,7 +682,8 @@ JS;
|
||||
* @param string $field
|
||||
* @return $this
|
||||
*/
|
||||
public function assertEnabled($field) {
|
||||
public function assertEnabled($field)
|
||||
{
|
||||
$element = $this->resolver->resolveForField($field);
|
||||
|
||||
PHPUnit::assertTrue(
|
||||
@@ -871,7 +700,8 @@ JS;
|
||||
* @param string $field
|
||||
* @return $this
|
||||
*/
|
||||
public function assertDisabled($field) {
|
||||
public function assertDisabled($field)
|
||||
{
|
||||
$element = $this->resolver->resolveForField($field);
|
||||
|
||||
PHPUnit::assertFalse(
|
||||
@@ -882,13 +712,50 @@ JS;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given button is enabled.
|
||||
*
|
||||
* @param string $button
|
||||
* @return $this
|
||||
*/
|
||||
public function assertButtonEnabled($button)
|
||||
{
|
||||
$element = $this->resolver->resolveForButtonPress($button);
|
||||
|
||||
PHPUnit::assertTrue(
|
||||
$element->isEnabled(),
|
||||
"Expected button [{$button}] to be enabled, but it wasn't."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given button is disabled.
|
||||
*
|
||||
* @param string $button
|
||||
* @return $this
|
||||
*/
|
||||
public function assertButtonDisabled($button)
|
||||
{
|
||||
$element = $this->resolver->resolveForButtonPress($button);
|
||||
|
||||
PHPUnit::assertFalse(
|
||||
$element->isEnabled(),
|
||||
"Expected button [{$button}] to be disabled, but it wasn't."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given field is focused.
|
||||
*
|
||||
* @param string $field
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFocused($field) {
|
||||
public function assertFocused($field)
|
||||
{
|
||||
$element = $this->resolver->resolveForField($field);
|
||||
|
||||
PHPUnit::assertTrue(
|
||||
@@ -905,7 +772,8 @@ JS;
|
||||
* @param string $field
|
||||
* @return $this
|
||||
*/
|
||||
public function assertNotFocused($field) {
|
||||
public function assertNotFocused($field)
|
||||
{
|
||||
$element = $this->resolver->resolveForField($field);
|
||||
|
||||
PHPUnit::assertFalse(
|
||||
@@ -958,7 +826,10 @@ JS;
|
||||
*/
|
||||
public function assertVueContains($key, $value, $componentSelector = null)
|
||||
{
|
||||
PHPUnit::assertContains($value, $this->vueAttribute($componentSelector, $key));
|
||||
$attribute = $this->vueAttribute($componentSelector, $key);
|
||||
|
||||
PHPUnit::assertIsArray($attribute, "The attribute for key [$key] is not an array.");
|
||||
PHPUnit::assertContains($value, $attribute);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -974,7 +845,10 @@ JS;
|
||||
*/
|
||||
public function assertVueDoesNotContain($key, $value, $componentSelector = null)
|
||||
{
|
||||
PHPUnit::assertNotContains($value, $this->vueAttribute($componentSelector, $key));
|
||||
$attribute = $this->vueAttribute($componentSelector, $key);
|
||||
|
||||
PHPUnit::assertIsArray($attribute, "The attribute for key [$key] is not an array.");
|
||||
PHPUnit::assertNotContains($value, $attribute);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -991,7 +865,7 @@ JS;
|
||||
$fullSelector = $this->resolver->format($componentSelector);
|
||||
|
||||
return $this->driver->executeScript(
|
||||
"return document.querySelector('" . $fullSelector . "').__vue__." . $key
|
||||
"return document.querySelector('".$fullSelector."').__vue__.".$key
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
353
vendor/laravel/dusk/src/Concerns/MakesUrlAssertions.php
vendored
Normal file
353
vendor/laravel/dusk/src/Concerns/MakesUrlAssertions.php
vendored
Normal file
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use PHPUnit\Framework\Assert as PHPUnit;
|
||||
|
||||
trait MakesUrlAssertions
|
||||
{
|
||||
/**
|
||||
* Assert that the current URL matches the given URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @return $this
|
||||
*/
|
||||
public function assertUrlIs($url)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($url, '/'));
|
||||
|
||||
$segments = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
$currentUrl = sprintf(
|
||||
'%s://%s%s%s',
|
||||
$segments['scheme'],
|
||||
$segments['host'],
|
||||
Arr::get($segments, 'port', '') ? ':'.$segments['port'] : '',
|
||||
Arr::get($segments, 'path', '')
|
||||
);
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $currentUrl,
|
||||
"Actual URL [{$this->driver->getCurrentURL()}] does not equal expected URL [{$url}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current scheme matches the given scheme.
|
||||
*
|
||||
* @param string $scheme
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSchemeIs($scheme)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($scheme, '/'));
|
||||
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_SCHEME) ?? '';
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $actual,
|
||||
"Actual scheme [{$actual}] does not equal expected scheme [{$pattern}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current scheme does not match the given scheme.
|
||||
*
|
||||
* @param string $scheme
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSchemeIsNot($scheme)
|
||||
{
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_SCHEME) ?? '';
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$scheme, $actual,
|
||||
"Scheme [{$scheme}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current host matches the given host.
|
||||
*
|
||||
* @param string $host
|
||||
* @return $this
|
||||
*/
|
||||
public function assertHostIs($host)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($host, '/'));
|
||||
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_HOST) ?? '';
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $actual,
|
||||
"Actual host [{$actual}] does not equal expected host [{$pattern}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current host does not match the given host.
|
||||
*
|
||||
* @param string $host
|
||||
* @return $this
|
||||
*/
|
||||
public function assertHostIsNot($host)
|
||||
{
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_HOST) ?? '';
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$host, $actual,
|
||||
"Host [{$host}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current port matches the given port.
|
||||
*
|
||||
* @param string $port
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPortIs($port)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($port, '/'));
|
||||
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_PORT) ?? '';
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $actual,
|
||||
"Actual port [{$actual}] does not equal expected port [{$pattern}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current host does not match the given host.
|
||||
*
|
||||
* @param string $port
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPortIsNot($port)
|
||||
{
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_PORT) ?? '';
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$port, $actual,
|
||||
"Port [{$port}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path matches the given pattern.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathIs($path)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($path, '/'));
|
||||
|
||||
$actualPath = parse_url($this->driver->getCurrentURL(), PHP_URL_PATH) ?? '';
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $actualPath,
|
||||
"Actual path [{$actualPath}] does not equal expected path [{$path}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path begins with given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathBeginsWith($path)
|
||||
{
|
||||
$actualPath = parse_url($this->driver->getCurrentURL(), PHP_URL_PATH) ?? '';
|
||||
|
||||
PHPUnit::assertStringStartsWith(
|
||||
$path, $actualPath,
|
||||
"Actual path [{$actualPath}] does not begin with expected path [{$path}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path does not match the given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathIsNot($path)
|
||||
{
|
||||
$actualPath = parse_url($this->driver->getCurrentURL(), PHP_URL_PATH) ?? '';
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$path, $actualPath,
|
||||
"Path [{$path}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment matches the given pattern.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentIs($fragment)
|
||||
{
|
||||
$pattern = preg_quote($fragment, '/');
|
||||
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.str_replace('\*', '.*', $pattern).'$/u', $actualFragment,
|
||||
"Actual fragment [{$actualFragment}] does not equal expected fragment [{$fragment}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment begins with given fragment.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentBeginsWith($fragment)
|
||||
{
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertStringStartsWith(
|
||||
$fragment, $actualFragment,
|
||||
"Actual fragment [$actualFragment] does not begin with expected fragment [$fragment]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment does not match the given fragment.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentIsNot($fragment)
|
||||
{
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$fragment, $actualFragment,
|
||||
"Fragment [{$fragment}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path matches the given route.
|
||||
*
|
||||
* @param string $route
|
||||
* @param array $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function assertRouteIs($route, $parameters = [])
|
||||
{
|
||||
return $this->assertPathIs(route($route, $parameters, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a query string parameter is present and has a given value.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertQueryStringHas($name, $value = null)
|
||||
{
|
||||
$output = $this->assertHasQueryStringParameter($name);
|
||||
|
||||
if (is_null($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$parsedOutputName = is_array($output[$name]) ? implode(',', $output[$name]) : $output[$name];
|
||||
|
||||
$parsedValue = is_array($value) ? implode(',', $value) : $value;
|
||||
|
||||
PHPUnit::assertEquals(
|
||||
$value, $output[$name],
|
||||
"Query string parameter [{$name}] had value [{$parsedOutputName}], but expected [{$parsedValue}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given query string parameter is missing.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function assertQueryStringMissing($name)
|
||||
{
|
||||
$parsedUrl = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
if (! array_key_exists('query', $parsedUrl)) {
|
||||
PHPUnit::assertTrue(true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
parse_str($parsedUrl['query'], $output);
|
||||
|
||||
PHPUnit::assertArrayNotHasKey(
|
||||
$name, $output,
|
||||
"Found unexpected query string parameter [{$name}] in [".$this->driver->getCurrentURL().'].'
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given query string parameter is present.
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function assertHasQueryStringParameter($name)
|
||||
{
|
||||
$parsedUrl = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
PHPUnit::assertArrayHasKey(
|
||||
'query', $parsedUrl,
|
||||
'Did not see expected query string in ['.$this->driver->getCurrentURL().'].'
|
||||
);
|
||||
|
||||
parse_str($parsedUrl['query'], $output);
|
||||
|
||||
PHPUnit::assertArrayHasKey(
|
||||
$name, $output,
|
||||
"Did not see expected query string parameter [{$name}] in [".$this->driver->getCurrentURL().'].'
|
||||
);
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Throwable;
|
||||
use ReflectionFunction;
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Support\Collection;
|
||||
use Laravel\Dusk\Browser;
|
||||
use ReflectionFunction;
|
||||
use Throwable;
|
||||
|
||||
trait ProvidesBrowser
|
||||
{
|
||||
@@ -56,6 +56,7 @@ trait ProvidesBrowser
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return \Laravel\Dusk\Browser|void
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
@@ -85,6 +86,7 @@ trait ProvidesBrowser
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return array
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function createBrowsersFor(Closure $callback)
|
||||
@@ -118,6 +120,7 @@ trait ProvidesBrowser
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return int
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function browsersNeededFor(Closure $callback)
|
||||
@@ -134,7 +137,11 @@ trait ProvidesBrowser
|
||||
protected function captureFailuresFor($browsers)
|
||||
{
|
||||
$browsers->each(function ($browser, $key) {
|
||||
$name = str_replace('\\', '_', get_class($this)).'_'.$this->getName(false);
|
||||
if (property_exists($browser, 'fitOnFailure') && $browser->fitOnFailure) {
|
||||
$browser->fitContent();
|
||||
}
|
||||
|
||||
$name = $this->getCallerName();
|
||||
|
||||
$browser->screenshot('failure-'.$name.'-'.$key);
|
||||
});
|
||||
@@ -149,7 +156,7 @@ trait ProvidesBrowser
|
||||
protected function storeConsoleLogsFor($browsers)
|
||||
{
|
||||
$browsers->each(function ($browser, $key) {
|
||||
$name = str_replace('\\', '_', get_class($this)).'_'.$this->getName(false);
|
||||
$name = $this->getCallerName();
|
||||
|
||||
$browser->storeConsoleLog($name.'-'.$key);
|
||||
});
|
||||
@@ -184,6 +191,7 @@ trait ProvidesBrowser
|
||||
* Create the remote web driver instance.
|
||||
*
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebDriver
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function createWebDriver()
|
||||
@@ -193,6 +201,16 @@ trait ProvidesBrowser
|
||||
}, 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the browser caller name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getCallerName()
|
||||
{
|
||||
return str_replace('\\', '_', get_class($this)).'_'.$this->getName(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the RemoteWebDriver instance.
|
||||
*
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
use Facebook\WebDriver\Exception\TimeOutException;
|
||||
use Facebook\WebDriver\Exception\NoSuchElementException;
|
||||
use Facebook\WebDriver\Exception\TimeOutException;
|
||||
use Facebook\WebDriver\WebDriverExpectedCondition;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait WaitsForElements
|
||||
{
|
||||
@@ -16,9 +17,10 @@ trait WaitsForElements
|
||||
* Execute the given callback in a scoped browser once the selector is available.
|
||||
*
|
||||
* @param string $selector
|
||||
* @param Closure $callback
|
||||
* @param \Closure $callback
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function whenAvailable($selector, Closure $callback, $seconds = null)
|
||||
@@ -32,13 +34,16 @@ trait WaitsForElements
|
||||
* @param string $selector
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitFor($selector, $seconds = null)
|
||||
{
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for selector', $selector);
|
||||
|
||||
return $this->waitUsing($seconds, 100, function () use ($selector) {
|
||||
return $this->resolver->findOrFail($selector)->isDisplayed();
|
||||
}, "Waited %s seconds for selector [{$selector}].");
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,10 +52,13 @@ trait WaitsForElements
|
||||
* @param string $selector
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitUntilMissing($selector, $seconds = null)
|
||||
{
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for removal of selector', $selector);
|
||||
|
||||
return $this->waitUsing($seconds, 100, function () use ($selector) {
|
||||
try {
|
||||
$missing = ! $this->resolver->findOrFail($selector)->isDisplayed();
|
||||
@@ -59,22 +67,47 @@ trait WaitsForElements
|
||||
}
|
||||
|
||||
return $missing;
|
||||
}, "Waited %s seconds for removal of selector [{$selector}].");
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the given text to be removed.
|
||||
*
|
||||
* @param string $text
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitUntilMissingText($text, $seconds = null)
|
||||
{
|
||||
$text = Arr::wrap($text);
|
||||
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for removal of text', implode("', '", $text));
|
||||
|
||||
return $this->waitUsing($seconds, 100, function () use ($text) {
|
||||
return ! Str::contains($this->resolver->findOrFail('')->getText(), $text);
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the given text to be visible.
|
||||
*
|
||||
* @param string $text
|
||||
* @param array|string $text
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForText($text, $seconds = null)
|
||||
{
|
||||
$text = Arr::wrap($text);
|
||||
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for text', implode("', '", $text));
|
||||
|
||||
return $this->waitUsing($seconds, 100, function () use ($text) {
|
||||
return Str::contains($this->resolver->findOrFail('')->getText(), $text);
|
||||
}, "Waited %s seconds for text [{$text}].");
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,13 +116,16 @@ trait WaitsForElements
|
||||
* @param string $link
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForLink($link, $seconds = null)
|
||||
{
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for link', $link);
|
||||
|
||||
return $this->waitUsing($seconds, 100, function () use ($link) {
|
||||
return $this->seeLink($link);
|
||||
}, "Waited %s seconds for link [{$link}].");
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,11 +134,14 @@ trait WaitsForElements
|
||||
* @param string $path
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForLocation($path, $seconds = null)
|
||||
{
|
||||
return $this->waitUntil("window.location.pathname == '{$path}'", $seconds, "Waited %s seconds for location [{$path}].");
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for location', $path);
|
||||
|
||||
return $this->waitUntil("window.location.pathname == '{$path}'", $seconds, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,6 +151,7 @@ trait WaitsForElements
|
||||
* @param array $parameters
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForRoute($route, $parameters = [], $seconds = null)
|
||||
@@ -126,6 +166,7 @@ trait WaitsForElements
|
||||
* @param int $seconds
|
||||
* @param string $message
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitUntil($script, $seconds = null, $message = null)
|
||||
@@ -143,6 +184,40 @@ trait WaitsForElements
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the Vue component's attribute at the given key has the given value.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @param string|null $componentSelector
|
||||
* @return $this
|
||||
*/
|
||||
public function waitUntilVue($key, $value, $componentSelector = null, $seconds = null)
|
||||
{
|
||||
$this->waitUsing($seconds, 100, function () use ($key, $value, $componentSelector) {
|
||||
return $value == $this->vueAttribute($componentSelector, $key);
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the Vue component's attribute at the given key does not have the given value.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @param string|null $componentSelector
|
||||
* @return $this
|
||||
*/
|
||||
public function waitUntilVueIsNot($key, $value, $componentSelector = null, $seconds = null)
|
||||
{
|
||||
$this->waitUsing($seconds, 100, function () use ($key, $value, $componentSelector) {
|
||||
return $value != $this->vueAttribute($componentSelector, $key);
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a JavaScript dialog to open.
|
||||
*
|
||||
@@ -163,14 +238,15 @@ trait WaitsForElements
|
||||
/**
|
||||
* Wait for the current page to reload.
|
||||
*
|
||||
* @param Closure $callback
|
||||
* @param \Closure $callback
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForReload($callback = null, $seconds = null)
|
||||
{
|
||||
$token = str_random();
|
||||
$token = Str::random();
|
||||
|
||||
$this->driver->executeScript("window['{$token}'] = {};");
|
||||
|
||||
@@ -188,9 +264,10 @@ trait WaitsForElements
|
||||
*
|
||||
* @param int $seconds
|
||||
* @param int $interval
|
||||
* @param Closure $callback
|
||||
* @param \Closure $callback
|
||||
* @param string|null $message
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitUsing($seconds, $interval, Closure $callback, $message = null)
|
||||
@@ -222,4 +299,16 @@ trait WaitsForElements
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare custom TimeOutException message for sprintf().
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $expected
|
||||
* @return string
|
||||
*/
|
||||
protected function formatTimeOutMessage($message, $expected)
|
||||
{
|
||||
return $message.' ['.str_replace('%', '%%', $expected).'].';
|
||||
}
|
||||
}
|
||||
|
||||
251
vendor/laravel/dusk/src/Console/ChromeDriverCommand.php
vendored
Normal file
251
vendor/laravel/dusk/src/Console/ChromeDriverCommand.php
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Laravel\Dusk\OperatingSystem;
|
||||
use ZipArchive;
|
||||
|
||||
/**
|
||||
* @copyright Originally created by Jonas Staudenmeir: https://github.com/staudenmeir/dusk-updater
|
||||
*/
|
||||
class ChromeDriverCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'dusk:chrome-driver {version?}
|
||||
{--all : Install a ChromeDriver binary for every OS}
|
||||
{--proxy= : The proxy to download the binary through (example: "tcp://127.0.0.1:9000")}
|
||||
{--ssl-no-verify : Bypass SSL certificate verification when installing through a proxy}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Install the ChromeDriver binary';
|
||||
|
||||
/**
|
||||
* URL to the latest stable release version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $latestVersionUrl = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE';
|
||||
|
||||
/**
|
||||
* URL to the latest release version for a major Chrome version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $versionUrl = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE_%d';
|
||||
|
||||
/**
|
||||
* URL to the ChromeDriver download.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $downloadUrl = 'https://chromedriver.storage.googleapis.com/%s/chromedriver_%s.zip';
|
||||
|
||||
/**
|
||||
* Download slugs for the available operating systems.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $slugs = [
|
||||
'linux' => '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) {
|
||||
return $this->latestVersion();
|
||||
}
|
||||
|
||||
if (! ctype_digit($version)) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
$version = (int) $version;
|
||||
|
||||
if ($version < 70) {
|
||||
return $this->legacyVersions[$version];
|
||||
}
|
||||
|
||||
return trim($this->getUrl(
|
||||
sprintf($this->versionUrl, $version)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest stable ChromeDriver version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function latestVersion()
|
||||
{
|
||||
return trim(file_get_contents($this->latestVersionUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the ChromeDriver archive.
|
||||
*
|
||||
* @param string $version
|
||||
* @param string $slug
|
||||
* @return string
|
||||
*/
|
||||
protected function download($version, $slug)
|
||||
{
|
||||
$url = sprintf($this->downloadUrl, $version, $slug);
|
||||
|
||||
file_put_contents(
|
||||
$archive = $this->directory.'chromedriver.zip',
|
||||
$this->getUrl($url)
|
||||
);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contents of a URL using the 'proxy' and 'ssl-no-verify' command options.
|
||||
*
|
||||
* @param string $url
|
||||
* @return string|bool
|
||||
*/
|
||||
protected function getUrl(string $url)
|
||||
{
|
||||
$contextOptions = [];
|
||||
|
||||
if ($this->option('proxy')) {
|
||||
$contextOptions['http'] = ['proxy' => $this->option('proxy'), 'request_fulluri' => true];
|
||||
}
|
||||
|
||||
if ($this->option('ssl-no-verify')) {
|
||||
$contextOptions['ssl'] = ['verify_peer' => false];
|
||||
}
|
||||
|
||||
$streamContext = stream_context_create($contextOptions);
|
||||
|
||||
return file_get_contents($url, false, $streamContext);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ComponentCommand extends GeneratorCommand
|
||||
{
|
||||
@@ -45,7 +46,7 @@ class ComponentCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
$name = str_replace_first($this->rootNamespace(), '', $name);
|
||||
$name = Str::replaceFirst($this->rootNamespace(), '', $name);
|
||||
|
||||
return $this->laravel->basePath().'/tests'.str_replace('\\', '/', $name).'.php';
|
||||
}
|
||||
|
||||
154
vendor/laravel/dusk/src/Console/DuskCommand.php
vendored
154
vendor/laravel/dusk/src/Console/DuskCommand.php
vendored
@@ -3,11 +3,12 @@
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessSignaledException;
|
||||
use Symfony\Component\Process\Exception\RuntimeException;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class DuskCommand extends Command
|
||||
{
|
||||
@@ -28,7 +29,7 @@ class DuskCommand extends Command
|
||||
/**
|
||||
* Indicates if the project has its own PHPUnit configuration.
|
||||
*
|
||||
* @var boolean
|
||||
* @var bool
|
||||
*/
|
||||
protected $hasPhpUnitConfiguration = false;
|
||||
|
||||
@@ -68,9 +69,15 @@ class DuskCommand extends Command
|
||||
$this->output->writeln('Warning: '.$e->getMessage());
|
||||
}
|
||||
|
||||
return $process->run(function ($type, $line) {
|
||||
$this->output->write($line);
|
||||
});
|
||||
try {
|
||||
return $process->run(function ($type, $line) {
|
||||
$this->output->write($line);
|
||||
});
|
||||
} catch (ProcessSignaledException $e) {
|
||||
if (extension_loaded('pcntl') && $e->getSignal() !== SIGINT) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -81,6 +88,10 @@ class DuskCommand extends Command
|
||||
*/
|
||||
protected function binary()
|
||||
{
|
||||
if ('phpdbg' === PHP_SAPI) {
|
||||
return [PHP_BINARY, '-qrr', 'vendor/phpunit/phpunit/phpunit'];
|
||||
}
|
||||
|
||||
return [PHP_BINARY, 'vendor/phpunit/phpunit/phpunit'];
|
||||
}
|
||||
|
||||
@@ -96,18 +107,28 @@ class DuskCommand extends Command
|
||||
return ! Str::startsWith($option, '--env=');
|
||||
}));
|
||||
|
||||
return array_merge(['-c', base_path('phpunit.dusk.xml')], $options);
|
||||
if (! file_exists($file = base_path('phpunit.dusk.xml'))) {
|
||||
$file = base_path('phpunit.dusk.xml.dist');
|
||||
}
|
||||
|
||||
return array_merge(['-c', $file], $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge the failure screenshots
|
||||
* Purge the failure screenshots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function purgeScreenshots()
|
||||
{
|
||||
$path = base_path('tests/Browser/screenshots');
|
||||
|
||||
if (! is_dir($path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$files = Finder::create()->files()
|
||||
->in(base_path('tests/Browser/screenshots'))
|
||||
->in($path)
|
||||
->name('failure-*');
|
||||
|
||||
foreach ($files as $file) {
|
||||
@@ -122,8 +143,14 @@ class DuskCommand extends Command
|
||||
*/
|
||||
protected function purgeConsoleLogs()
|
||||
{
|
||||
$path = base_path('tests/Browser/console');
|
||||
|
||||
if (! is_dir($path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$files = Finder::create()->files()
|
||||
->in(base_path('tests/Browser/console'))
|
||||
->in($path)
|
||||
->name('*.log');
|
||||
|
||||
foreach ($files as $file) {
|
||||
@@ -138,6 +165,22 @@ class DuskCommand extends Command
|
||||
* @return mixed
|
||||
*/
|
||||
protected function withDuskEnvironment($callback)
|
||||
{
|
||||
$this->setupDuskEnvironment();
|
||||
|
||||
try {
|
||||
return $callback();
|
||||
} finally {
|
||||
$this->teardownDuskEnviroment();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the Dusk environment.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setupDuskEnvironment()
|
||||
{
|
||||
if (file_exists(base_path($this->duskFile()))) {
|
||||
if (file_get_contents(base_path('.env')) !== file_get_contents(base_path($this->duskFile()))) {
|
||||
@@ -149,13 +192,7 @@ class DuskCommand extends Command
|
||||
|
||||
$this->writeConfiguration();
|
||||
|
||||
return tap($callback(), function () {
|
||||
$this->removeConfiguration();
|
||||
|
||||
if (file_exists(base_path($this->duskFile())) && file_exists(base_path('.env.backup'))) {
|
||||
$this->restoreEnvironment();
|
||||
}
|
||||
});
|
||||
$this->setupSignalHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,18 +207,6 @@ class DuskCommand extends Command
|
||||
copy(base_path($this->duskFile()), base_path('.env'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the backed-up environment file.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function restoreEnvironment()
|
||||
{
|
||||
copy(base_path('.env.backup'), base_path('.env'));
|
||||
|
||||
unlink(base_path('.env.backup'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the current environment variables.
|
||||
*
|
||||
@@ -189,7 +214,21 @@ class DuskCommand extends Command
|
||||
*/
|
||||
protected function refreshEnvironment()
|
||||
{
|
||||
(new Dotenv(base_path()))->overload();
|
||||
// BC fix to support Dotenv ^2.2...
|
||||
if (! method_exists(Dotenv::class, 'create')) {
|
||||
(new Dotenv(base_path()))->overload();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// BC fix to support Dotenv ^3.0...
|
||||
if (! method_exists(Dotenv::class, 'createMutable')) {
|
||||
Dotenv::create(base_path())->overload();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Dotenv::createMutable(base_path())->load();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,10 +238,43 @@ class DuskCommand extends Command
|
||||
*/
|
||||
protected function writeConfiguration()
|
||||
{
|
||||
if (! file_exists($file = base_path('phpunit.dusk.xml'))) {
|
||||
if (! file_exists($file = base_path('phpunit.dusk.xml')) &&
|
||||
! file_exists(base_path('phpunit.dusk.xml.dist'))) {
|
||||
copy(realpath(__DIR__.'/../../stubs/phpunit.xml'), $file);
|
||||
} else {
|
||||
$this->hasPhpUnitConfiguration = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->hasPhpUnitConfiguration = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the SIGINT signal handler for CTRL+C exits.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setupSignalHandler()
|
||||
{
|
||||
if (extension_loaded('pcntl')) {
|
||||
pcntl_async_signals(true);
|
||||
|
||||
pcntl_signal(SIGINT, function () {
|
||||
$this->teardownDuskEnviroment();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the original environment.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function teardownDuskEnviroment()
|
||||
{
|
||||
$this->removeConfiguration();
|
||||
|
||||
if (file_exists(base_path($this->duskFile())) && file_exists(base_path('.env.backup'))) {
|
||||
$this->restoreEnvironment();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,11 +285,23 @@ class DuskCommand extends Command
|
||||
*/
|
||||
protected function removeConfiguration()
|
||||
{
|
||||
if (! $this->hasPhpUnitConfiguration) {
|
||||
unlink(base_path('phpunit.dusk.xml'));
|
||||
if (! $this->hasPhpUnitConfiguration && file_exists($file = base_path('phpunit.dusk.xml'))) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the backed-up environment file.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function restoreEnvironment()
|
||||
{
|
||||
copy(base_path('.env.backup'), base_path('.env'));
|
||||
|
||||
unlink(base_path('.env.backup'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the Dusk file for the environment.
|
||||
*
|
||||
|
||||
33
vendor/laravel/dusk/src/Console/DuskFailsCommand.php
vendored
Normal file
33
vendor/laravel/dusk/src/Console/DuskFailsCommand.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
class DuskFailsCommand extends DuskCommand
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'dusk:fails {--without-tty : Disable output to TTY}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Run the failing Dusk tests from the last run and stop on failure';
|
||||
|
||||
/**
|
||||
* Get the array of arguments for running PHPUnit.
|
||||
*
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function phpunitArguments($options)
|
||||
{
|
||||
return array_unique(array_merge(parent::phpunitArguments($options), [
|
||||
'--cache-result', '--order-by=defects', '--stop-on-failure',
|
||||
]));
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,9 @@ class InstallCommand extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'dusk:install';
|
||||
protected $signature = 'dusk:install
|
||||
{--proxy= : The proxy to download the binary through (example: "tcp://127.0.0.1:9000")}
|
||||
{--ssl-no-verify : Bypass SSL certificate verification when installing through a proxy}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@@ -20,16 +22,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.
|
||||
*
|
||||
@@ -67,6 +59,20 @@ class InstallCommand extends Command
|
||||
}
|
||||
|
||||
$this->info('Dusk scaffolding installed successfully.');
|
||||
|
||||
$this->comment('Downloading ChromeDriver binaries...');
|
||||
|
||||
$driverCommandArgs = ['--all' => true];
|
||||
|
||||
if ($this->option('proxy')) {
|
||||
$driverCommandArgs['--proxy'] = $this->option('proxy');
|
||||
}
|
||||
|
||||
if ($this->option('ssl-no-verify')) {
|
||||
$driverCommandArgs['--ssl-no-verify'] = true;
|
||||
}
|
||||
|
||||
$this->call('dusk:chrome-driver', $driverCommandArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class MakeCommand extends GeneratorCommand
|
||||
{
|
||||
@@ -45,7 +46,7 @@ class MakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
$name = str_replace_first($this->rootNamespace(), '', $name);
|
||||
$name = Str::replaceFirst($this->rootNamespace(), '', $name);
|
||||
|
||||
return $this->laravel->basePath().'/tests'.str_replace('\\', '/', $name).'.php';
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class PageCommand extends GeneratorCommand
|
||||
{
|
||||
@@ -45,7 +46,7 @@ class PageCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
$name = str_replace_first($this->rootNamespace(), '', $name);
|
||||
$name = Str::replaceFirst($this->rootNamespace(), '', $name);
|
||||
|
||||
return $this->laravel->basePath().'/tests'.str_replace('\\', '/', $name).'.php';
|
||||
}
|
||||
|
||||
4
vendor/laravel/dusk/src/Dusk.php
vendored
4
vendor/laravel/dusk/src/Dusk.php
vendored
@@ -24,6 +24,8 @@ class Dusk
|
||||
*
|
||||
* @param array $options
|
||||
* @return bool
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected static function duskEnvironment($options)
|
||||
{
|
||||
@@ -36,7 +38,7 @@ class Dusk
|
||||
}
|
||||
|
||||
if (! is_array($options['environments'])) {
|
||||
throw new InvalidArgumentException("Dusk environments must be listed as an array.");
|
||||
throw new InvalidArgumentException('Dusk environments must be listed as an array.');
|
||||
}
|
||||
|
||||
return app()->environment(...$options['environments']);
|
||||
|
||||
36
vendor/laravel/dusk/src/DuskServiceProvider.php
vendored
36
vendor/laravel/dusk/src/DuskServiceProvider.php
vendored
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Laravel\Dusk;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
@@ -15,41 +14,42 @@ class DuskServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Route::get('/_dusk/login/{userId}/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@login',
|
||||
]);
|
||||
if (! $this->app->environment('production')) {
|
||||
Route::get('/_dusk/login/{userId}/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@login',
|
||||
]);
|
||||
|
||||
Route::get('/_dusk/logout/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@logout',
|
||||
]);
|
||||
Route::get('/_dusk/logout/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@logout',
|
||||
]);
|
||||
|
||||
Route::get('/_dusk/user/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@user',
|
||||
]);
|
||||
Route::get('/_dusk/user/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@user',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register any package services.
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
if ($this->app->environment('production')) {
|
||||
throw new Exception('It is unsafe to run Dusk in production.');
|
||||
}
|
||||
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->commands([
|
||||
Console\InstallCommand::class,
|
||||
Console\DuskCommand::class,
|
||||
Console\DuskFailsCommand::class,
|
||||
Console\MakeCommand::class,
|
||||
Console\PageCommand::class,
|
||||
Console\ComponentCommand::class,
|
||||
Console\ChromeDriverCommand::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
45
vendor/laravel/dusk/src/ElementResolver.php
vendored
45
vendor/laravel/dusk/src/ElementResolver.php
vendored
@@ -3,10 +3,10 @@
|
||||
namespace Laravel\Dusk;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class ElementResolver
|
||||
{
|
||||
@@ -43,7 +43,7 @@ class ElementResolver
|
||||
'findButtonBySelector',
|
||||
'findButtonByName',
|
||||
'findButtonByValue',
|
||||
'findButtonByText'
|
||||
'findButtonByText',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -77,6 +77,7 @@ class ElementResolver
|
||||
*
|
||||
* @param string $field
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveForTyping($field)
|
||||
@@ -86,7 +87,7 @@ class ElementResolver
|
||||
}
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, "input[name='{$field}']", "textarea[name='{$field}']"
|
||||
$field, "input[name='{$field}']", "textarea[name='{$field}']",
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -95,6 +96,7 @@ class ElementResolver
|
||||
*
|
||||
* @param string $field
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveForSelection($field)
|
||||
@@ -104,16 +106,17 @@ class ElementResolver
|
||||
}
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, "select[name='{$field}']"
|
||||
$field, "select[name='{$field}']",
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve all the options with the given value on the select field.
|
||||
*
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement[]
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveSelectOptions($field, array $values)
|
||||
@@ -136,7 +139,9 @@ class ElementResolver
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function resolveForRadioSelection($field, $value = null)
|
||||
{
|
||||
@@ -151,16 +156,17 @@ class ElementResolver
|
||||
}
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, "input[type=radio][name='{$field}'][value='{$value}']"
|
||||
$field, "input[type=radio][name='{$field}'][value='{$value}']",
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the element for a given checkbox "field".
|
||||
*
|
||||
* @param string $field
|
||||
* @param string|null $field
|
||||
* @param string $value
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveForChecking($field, $value = null)
|
||||
@@ -169,14 +175,18 @@ class ElementResolver
|
||||
return $element;
|
||||
}
|
||||
|
||||
$selector = "input[type=checkbox][name='{$field}']";
|
||||
$selector = 'input[type=checkbox]';
|
||||
|
||||
if (! is_null($field)) {
|
||||
$selector .= "[name='{$field}']";
|
||||
}
|
||||
|
||||
if (! is_null($value)) {
|
||||
$selector .= "[value='{$value}']";
|
||||
}
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, $selector
|
||||
$field, $selector,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -185,6 +195,7 @@ class ElementResolver
|
||||
*
|
||||
* @param string $field
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveForAttachment($field)
|
||||
@@ -194,7 +205,7 @@ class ElementResolver
|
||||
}
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, "input[type=file][name='{$field}']"
|
||||
$field, "input[type=file][name='{$field}']",
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -203,6 +214,7 @@ class ElementResolver
|
||||
*
|
||||
* @param string $field
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveForField($field)
|
||||
@@ -213,7 +225,7 @@ class ElementResolver
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, "input[name='{$field}']", "textarea[name='{$field}']",
|
||||
"select[name='{$field}']", "button[name='{$field}']"
|
||||
"select[name='{$field}']", "button[name='{$field}']",
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -222,6 +234,8 @@ class ElementResolver
|
||||
*
|
||||
* @param string $button
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function resolveForButtonPress($button)
|
||||
{
|
||||
@@ -272,7 +286,7 @@ class ElementResolver
|
||||
*/
|
||||
protected function findButtonByValue($button)
|
||||
{
|
||||
foreach ($this->all("input[type=submit]") as $element) {
|
||||
foreach ($this->all('input[type=submit]') as $element) {
|
||||
if ($element->getAttribute('value') === $button) {
|
||||
return $element;
|
||||
}
|
||||
@@ -327,6 +341,7 @@ class ElementResolver
|
||||
*
|
||||
* @param array $selectors
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function firstOrFail($selectors)
|
||||
@@ -394,7 +409,7 @@ class ElementResolver
|
||||
array_keys($sortedElements), array_values($sortedElements), $originalSelector = $selector
|
||||
);
|
||||
|
||||
if (starts_with($selector, '@') && $selector === $originalSelector) {
|
||||
if (Str::startsWith($selector, '@') && $selector === $originalSelector) {
|
||||
$selector = '[dusk="'.explode('@', $selector)[1].'"]';
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Laravel\Dusk\Http\Controllers;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UserController
|
||||
{
|
||||
@@ -31,6 +32,7 @@ class UserController
|
||||
*
|
||||
* @param string $userId
|
||||
* @param string $guard
|
||||
* @return void
|
||||
*/
|
||||
public function login($userId, $guard = null)
|
||||
{
|
||||
@@ -38,7 +40,7 @@ class UserController
|
||||
|
||||
$provider = Auth::guard($guard)->getProvider();
|
||||
|
||||
$user = str_contains($userId, '@')
|
||||
$user = Str::contains($userId, '@')
|
||||
? $provider->retrieveByCredentials(['email' => $userId])
|
||||
: $provider->retrieveById($userId);
|
||||
|
||||
@@ -49,6 +51,7 @@ class UserController
|
||||
* Log the user out of the application.
|
||||
*
|
||||
* @param string $guard
|
||||
* @return void
|
||||
*/
|
||||
public function logout($guard = null)
|
||||
{
|
||||
|
||||
38
vendor/laravel/dusk/src/OperatingSystem.php
vendored
Normal file
38
vendor/laravel/dusk/src/OperatingSystem.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Dusk;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class OperatingSystem
|
||||
{
|
||||
/**
|
||||
* Returns the current OS identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function id()
|
||||
{
|
||||
return static::onWindows() ? 'win' : (static::onMac() ? 'mac' : 'linux');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the operating system is Windows or Windows Subsystem for Linux.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function onWindows()
|
||||
{
|
||||
return PHP_OS === 'WINNT' || Str::contains(php_uname(), 'Microsoft');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the operating system is macOS.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function onMac()
|
||||
{
|
||||
return PHP_OS === 'Darwin';
|
||||
}
|
||||
}
|
||||
15
vendor/laravel/dusk/src/TestCase.php
vendored
15
vendor/laravel/dusk/src/TestCase.php
vendored
@@ -3,22 +3,22 @@
|
||||
namespace Laravel\Dusk;
|
||||
|
||||
use Exception;
|
||||
use Laravel\Dusk\Chrome\SupportsChrome;
|
||||
use Facebook\WebDriver\Remote\RemoteWebDriver;
|
||||
use Facebook\WebDriver\Remote\DesiredCapabilities;
|
||||
use Facebook\WebDriver\Remote\RemoteWebDriver;
|
||||
use Illuminate\Foundation\Testing\TestCase as FoundationTestCase;
|
||||
use Laravel\Dusk\Chrome\SupportsChrome;
|
||||
use Laravel\Dusk\Concerns\ProvidesBrowser;
|
||||
|
||||
abstract class TestCase extends FoundationTestCase
|
||||
{
|
||||
use Concerns\ProvidesBrowser,
|
||||
SupportsChrome;
|
||||
use ProvidesBrowser, SupportsChrome;
|
||||
|
||||
/**
|
||||
* Register the base URL with Dusk.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setUp()
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
@@ -28,6 +28,8 @@ abstract class TestCase extends FoundationTestCase
|
||||
|
||||
Browser::$storeConsoleLogAt = base_path('tests/Browser/console');
|
||||
|
||||
Browser::$storeSourceAt = base_path('tests/Browser/source');
|
||||
|
||||
Browser::$userResolver = function () {
|
||||
return $this->user();
|
||||
};
|
||||
@@ -59,10 +61,11 @@ abstract class TestCase extends FoundationTestCase
|
||||
* Return the default user to authenticate.
|
||||
*
|
||||
* @return \App\User|int|null
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function user()
|
||||
{
|
||||
throw new Exception("User resolver has not been set.");
|
||||
throw new Exception('User resolver has not been set.');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user