diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index f641a58..c8ed2ad 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -32,6 +32,7 @@ use Codeception\Util\Locator; use Codeception\Util\Uri; use Exception; +use Facebook\WebDriver\Cookie; use Facebook\WebDriver\Cookie as WebDriverCookie; use Facebook\WebDriver\Exception\InvalidElementStateException; use Facebook\WebDriver\Exception\InvalidSelectorException; @@ -53,6 +54,7 @@ use Facebook\WebDriver\WebDriverSelect; use InvalidArgumentException; use PHPUnit\Framework\AssertionFailedError as PHPUnitAssertionFailedError; +use PHPUnit\Framework\SelfDescribing; /** * Run tests in real browsers using the W3C [WebDriver protocol](https://www.w3.org/TR/webdriver/). @@ -109,7 +111,7 @@ * * ## Local Chrome and/or Firefox * - * Tests can be executed directly throgh ChromeDriver or GeckoDriver (for Firefox). Consider using this option if you don't plan to use Selenium. + * Tests can be executed directly through ChromeDriver or GeckoDriver (for Firefox). Consider using this option if you don't plan to use Selenium. * * ### ChromeDriver * @@ -137,7 +139,7 @@ * * ### GeckoDriver * - * * [GeckoDriver])(https://github.com/mozilla/geckodriver/releases) must be installed + * * [GeckoDriver](https://github.com/mozilla/geckodriver/releases) must be installed * * Start GeckoDriver in a separate console window: `geckodriver`. * * Configuration in `acceptance.suite.yml`: @@ -431,8 +433,6 @@ class WebDriver extends CodeceptionModule implements */ protected $requestTimeoutInMs; - protected $test; - protected array $sessions = []; protected array $sessionSnapshots = []; @@ -449,10 +449,7 @@ class WebDriver extends CodeceptionModule implements public ?RemoteWebDriver $webDriver = null; - /** - * @var RemoteWebDriver|RemoteWebElement - */ - protected $baseElement = null; + protected ?WebDriverSearchContext $baseElement = null; public function _requires(): array { @@ -461,9 +458,8 @@ public function _requires(): array /** * @throws ModuleException - * @return RemoteWebDriver|RemoteWebElement|WebDriverSearchContext */ - protected function getBaseElement() + protected function getBaseElement(): WebDriverSearchContext { if (!$this->baseElement) { throw new ModuleException($this, "Page not loaded. Use `\$I->amOnPage` (or hidden API methods `_request` and `_loadPage`) to open it"); @@ -635,6 +631,10 @@ public function _after(TestInterface $test) public function _failed(TestInterface $test, $fail) { + if (!$test instanceof SelfDescribing) { + // this exception should never been throw because all existing test types implement SelfDescribing + throw new InvalidArgumentException('Test class does not implement SelfDescribing interface'); + } $this->debugWebDriverLogs($test); $filename = preg_replace('#[^a-zA-Z0-9\x80-\xff]#', '.', Descriptor::getTestSignatureUnique($test)); $outputDir = codecept_output_dir(); @@ -759,8 +759,8 @@ protected function stopAllSessions(): void public function amOnSubdomain($subdomain) { $url = $this->config['url']; - $url = preg_replace('#(https?:\/\/)(.*\.)(.*\.)#', "$1$3", $url); // removing current subdomain - $url = preg_replace('#(https?:\/\/)(.*)#', sprintf('$1%s.$2', $subdomain), $url); // inserting new + $url = preg_replace('#(https?://)(.*\.)(.*\.)#', "$1$3", $url); // removing current subdomain + $url = preg_replace('#(https?://)(.*)#', sprintf('$1%s.$2', $subdomain), $url); // inserting new $this->_reconfigure(['url' => $url]); } @@ -839,7 +839,7 @@ public function _saveScreenshot(string $filename) } /** - * @param WebDriverBy|array $selector + * @param string|array|WebDriverBy $selector */ public function _saveElementScreenshot($selector, string $filename): void { @@ -856,7 +856,7 @@ public function _saveElementScreenshot($selector, string $filename): void } } - public function _findElements($locator) + public function _findElements($locator): array { return $this->match($this->webDriver, $locator); } @@ -980,7 +980,7 @@ private function debugCookies(): void $this->debugSection('Cookies', json_encode($result, JSON_THROW_ON_ERROR)); } - public function seeCookie($cookie, array $params = []) + public function seeCookie($cookie, array $params = []): void { $cookies = $this->filterCookies($this->webDriver->manage()->getCookies(), $params); $cookies = array_map( @@ -991,7 +991,7 @@ public function seeCookie($cookie, array $params = []) $this->assertContains($cookie, $cookies); } - public function dontSeeCookie($cookie, array $params = []) + public function dontSeeCookie($cookie, array $params = []): void { $cookies = $this->filterCookies($this->webDriver->manage()->getCookies(), $params); $cookies = array_map( @@ -1002,9 +1002,9 @@ public function dontSeeCookie($cookie, array $params = []) $this->assertNotContains($cookie, $cookies); } - public function setCookie($cookie, $value, array $params = [], $showDebug = true) + public function setCookie($name, $value, array $params = [], $showDebug = true): void { - $params['name'] = $cookie; + $params['name'] = $name; $params['value'] = $value; if (isset($params['expires'])) { // PhpBrowser compatibility $params['expiry'] = $params['expires']; @@ -1029,7 +1029,7 @@ public function setCookie($cookie, $value, array $params = [], $showDebug = true } } - public function resetCookie($cookie, array $params = []) + public function resetCookie($cookie, array $params = []): void { $this->webDriver->manage()->deleteCookieNamed($cookie); $this->debugCookies(); @@ -1061,7 +1061,12 @@ public function grabPageSource(): string return $this->webDriver->getPageSource(); } - protected function filterCookies($cookies, $params = []) + /** + * @param Cookie[] $cookies + * @param array $params + * @return Cookie[] + */ + protected function filterCookies(array $cookies, array $params = []): array { foreach (['domain', 'path', 'name'] as $filter) { if (!isset($params[$filter])) { @@ -1077,7 +1082,7 @@ protected function filterCookies($cookies, $params = []) return $cookies; } - public function amOnUrl($url) + public function amOnUrl($url): void { $host = Uri::retrieveHost($url); $this->_reconfigure(['url' => $host]); @@ -1085,17 +1090,18 @@ public function amOnUrl($url) $this->webDriver->get($url); } - public function amOnPage($page) + public function amOnPage($page): void { $url = Uri::appendPath($this->config['url'], $page); $this->debugSection('GET', $url); $this->webDriver->get($url); } - public function see($text, $selector = null) + public function see($text, $selector = null): void { if (!$selector) { - return $this->assertPageContains($text); + $this->assertPageContains($text); + return; } $this->enableImplicitWait(); @@ -1104,22 +1110,22 @@ public function see($text, $selector = null) $this->assertNodesContain($text, $nodes, $selector); } - public function dontSee($text, $selector = null) + public function dontSee($text, $selector = null): void { if (!$selector) { - return $this->assertPageNotContains($text); + $this->assertPageNotContains($text); + } else { + $nodes = $this->matchVisible($selector); + $this->assertNodesNotContain($text, $nodes, $selector); } - - $nodes = $this->matchVisible($selector); - $this->assertNodesNotContain($text, $nodes, $selector); } - public function seeInSource($raw) + public function seeInSource($raw): void { $this->assertPageSourceContains($raw); } - public function dontSeeInSource($raw) + public function dontSeeInSource($raw): void { $this->assertPageSourceNotContains($raw); } @@ -1194,12 +1200,11 @@ public function click($link, $context = null) * $el = $module->_findClickable($topBar, 'Click Me'); * * ``` - * @param RemoteWebDriver|RemoteWebElement $page WebDriver instance or an element to search within - * @param WebDriverBy|array $link A link text or locator to click - * @return RemoteWebElement|WebDriverElement|null + * @param WebDriverSearchContext $page WebDriver instance or an element to search within + * @param string|array|WebDriverBy $link A link text or locator to click * @api */ - public function _findClickable($page, $link) + public function _findClickable(WebDriverSearchContext $page, $link): ?WebDriverElement { if (is_array($link) || $link instanceof WebDriverBy) { return $this->matchFirstOrFail($page, $link); @@ -1245,7 +1250,7 @@ public function _findClickable($page, $link) /** * @param WebDriverElement|WebDriverBy|array|string $selector - * @return RemoteWebElement[]|WebDriverElement[] + * @return WebDriverElement[] * @throws ElementNotFound */ protected function findFields($selector): array @@ -1294,10 +1299,10 @@ protected function findFields($selector): array } /** - * @return WebDriverElement|false + * @param string|array|WebDriverBy|WebDriverElement $selector * @throws ElementNotFound */ - protected function findField($selector) + protected function findField($selector): WebDriverElement { $arr = $this->findFields($selector); return reset($arr); @@ -1428,7 +1433,11 @@ public function dontSeeInFormFields($formSelector, array $params) $this->proceedSeeInFormFields($formSelector, $params, true); } - protected function proceedSeeInFormFields($formSelector, array $params, $assertNot) + /** + * @param string|array|WebDriverBy $formSelector + * @throws ModuleException + */ + protected function proceedSeeInFormFields($formSelector, array $params, bool $assertNot) { $form = $this->match($this->getBaseElement(), $formSelector); if (empty($form)) { @@ -1465,11 +1474,11 @@ protected function proceedSeeInFormFields($formSelector, array $params, $assertN * recursing through array values if the field is not found. * * @param array $els The previously found elements. - * @param RemoteWebElement $form The form in which to search for fields. + * @param WebDriverElement $form The form in which to search for fields. * @param string $name The field's name. * @param mixed $values */ - protected function pushFormField(array &$els, RemoteWebElement $form, string $name, $values): void + protected function pushFormField(array &$els, WebDriverElement $form, string $name, $values): void { $el = $form->findElements(WebDriverBy::name($name)); @@ -1485,7 +1494,7 @@ protected function pushFormField(array &$els, RemoteWebElement $form, string $na } /** - * @param RemoteWebElement[] $elements + * @param WebDriverElement[] $elements * @param mixed $value */ protected function proceedSeeInField(array $elements, $value): array @@ -1545,7 +1554,7 @@ protected function proceedSeeInField(array $elements, $value): array ]; } - public function selectOption($select, $option) + public function selectOption($select, $option): void { $el = $this->findField($select); if ($el->getTagName() != 'select') { @@ -1676,7 +1685,7 @@ public function _loadSession($session) * * @api */ - public function _backupSession() + public function _backupSession(): ?RemoteWebDriver { return $this->webDriver; } @@ -1694,7 +1703,7 @@ public function _backupSession() * ``` * * @api - * @param $webDriver (optional) a specific webdriver session instance + * @param RemoteWebDriver|null $webDriver a specific webdriver session instance */ public function _closeSession($webDriver = null) { @@ -1717,9 +1726,10 @@ public function _closeSession($webDriver = null) /** * Unselect an option in the given select box. * - * @param mixed $option + * @param string|array|WebDriverBy $select + * @param string|array|WebDriverBy $option */ - public function unselectOption(WebDriverElement $select, $option): void + public function unselectOption($select, $option): void { $el = $this->findField($select); @@ -1755,11 +1765,9 @@ public function unselectOption(WebDriverElement $select, $option): void } /** - * @param $context - * @param WebDriverElement|WebDriverBy $radioOrCheckbox - * @return mixed + * @param string|array|WebDriverBy|WebDriverElement $radioOrCheckbox */ - protected function findCheckable($context, $radioOrCheckbox, bool $byValue = false) + protected function findCheckable(WebDriverSearchContext $context, $radioOrCheckbox, bool $byValue = false): ?WebDriverElement { if ($radioOrCheckbox instanceof WebDriverElement) { return $radioOrCheckbox; @@ -1818,6 +1826,10 @@ protected function findCheckable($context, $radioOrCheckbox, bool $byValue = fal return null; } + /** + * @param string|array|WebDriverBy $selector + * @return WebDriverElement[] + */ protected function matchCheckables($selector): array { $els = $this->match($this->webDriver, $selector); @@ -1828,7 +1840,7 @@ protected function matchCheckables($selector): array return $els; } - public function checkOption($option) + public function checkOption($option): void { $field = $this->findCheckable($this->webDriver, $option); if (!$field) { @@ -1842,7 +1854,7 @@ public function checkOption($option) $field->click(); } - public function uncheckOption($option) + public function uncheckOption($option): void { $field = $this->findCheckable($this->getBaseElement(), $option); if (!$field) { @@ -1856,7 +1868,7 @@ public function uncheckOption($option) $field->click(); } - public function fillField($field, $value) + public function fillField($field, $value): void { $el = $this->findField($field); $el->clear(); @@ -1871,7 +1883,7 @@ public function fillField($field, $value) * $I->clearField('#username'); * ``` * - * @param mixed $field + * @param string|array|WebDriverBy $field */ public function clearField($field): void { @@ -1966,13 +1978,13 @@ public function grabTextFrom($cssOrXPathOrRegex) throw new ElementNotFound($cssOrXPathOrRegex, 'CSS or XPath or Regex'); } - public function grabAttributeFrom($cssOrXpath, $attribute) + public function grabAttributeFrom($cssOrXpath, $attribute): ?string { $el = $this->matchFirstOrFail($this->getBaseElement(), $cssOrXpath); return $el->getAttribute($attribute); } - public function grabValueFrom($field) + public function grabValueFrom($field): ?string { $el = $this->findField($field); // value of multiple select is the value of the first selected option @@ -1984,7 +1996,7 @@ public function grabValueFrom($field) return $el->getAttribute('value'); } - public function grabMultiple($cssOrXpath, $attribute = null) + public function grabMultiple($cssOrXpath, $attribute = null): array { $els = $this->match($this->getBaseElement(), $cssOrXpath); return array_map( @@ -2035,7 +2047,7 @@ public function dontSeeElement($selector, $attributes = []) * $I->seeElementInDOM('//form/input[type=hidden]'); * ``` * - * @param $selector + * @param string|array|WebDriverBy $selector */ public function seeElementInDOM($selector, array $attributes = []): void { @@ -2050,7 +2062,7 @@ public function seeElementInDOM($selector, array $attributes = []): void /** * Opposite of `seeElementInDOM`. * - * @param mixed $selector + * @param string|array|WebDriverBy $selector */ public function dontSeeElementInDOM($selector, array $attributes = []): void { @@ -2077,6 +2089,11 @@ public function seeNumberOfElements($selector, $expected) } } + /** + * @param string|array|WebDriverBy $selector + * @param int|array $expected + * @throws ModuleException + */ public function seeNumberOfElementsInDOM($selector, $expected) { $counted = count($this->match($this->getBaseElement(), $selector)); @@ -2095,7 +2112,7 @@ public function seeNumberOfElementsInDOM($selector, $expected) } } - public function seeOptionIsSelected($selector, $optionText) + public function seeOptionIsSelected($selector, $optionText): void { $el = $this->findField($selector); if ($el->getTagName() !== 'select') { @@ -2110,14 +2127,13 @@ public function seeOptionIsSelected($selector, $optionText) fn($e): bool => $e && $e->isSelected() ) ); - return; + } else { + $select = new WebDriverSelect($el); + $this->assertNodesContain($optionText, $select->getAllSelectedOptions(), 'option'); } - - $select = new WebDriverSelect($el); - $this->assertNodesContain($optionText, $select->getAllSelectedOptions(), 'option'); } - public function dontSeeOptionIsSelected($selector, $optionText) + public function dontSeeOptionIsSelected($selector, $optionText): void { $el = $this->findField($selector); if ($el->getTagName() !== 'select') { @@ -2132,11 +2148,10 @@ public function dontSeeOptionIsSelected($selector, $optionText) fn($e): bool => $e && $e->isSelected() ) ); - return; + } else { + $select = new WebDriverSelect($el); + $this->assertNodesNotContain($optionText, $select->getAllSelectedOptions(), 'option'); } - - $select = new WebDriverSelect($el); - $this->assertNodesNotContain($optionText, $select->getAllSelectedOptions(), 'option'); } public function seeInTitle($title) @@ -2421,8 +2436,11 @@ protected function getSubmissionFormFieldName(string $name): string * - 'submitButton' * - ['name' => 'submitButton'] * - WebDriverBy::name('submitButton') + * + * @param string|array|WebDriverBy $selector + * @param string|array|WebDriverBy|null $button */ - public function submitForm($selector, array $params, $button = null) + public function submitForm($selector, array $params, $button = null): void { $form = $this->matchFirstOrFail($this->getBaseElement(), $selector); @@ -2430,7 +2448,7 @@ public function submitForm($selector, array $params, $button = null) WebDriverBy::cssSelector('input:enabled[name],textarea:enabled[name],select:enabled[name],input[type=hidden][name]') ); foreach ($fields as $field) { - $fieldName = $this->getSubmissionFormFieldName($field->getAttribute('name')); + $fieldName = $this->getSubmissionFormFieldName($field->getAttribute('name') ?? ''); if (!isset($params[$fieldName])) { continue; } @@ -2517,8 +2535,7 @@ public function submitForm($selector, array $params, $button = null) * }, 100); * ``` * - * @param $element - * @param int $timeout seconds + * @param string|array|WebDriverBy $element * @throws ElementNotFound */ public function waitForElementChange($element, Closure $callback, int $timeout = 30): void @@ -2538,7 +2555,7 @@ public function waitForElementChange($element, Closure $callback, int $timeout = * $I->click('#agree_button'); * ``` * - * @param $element + * @param string|array|WebDriverBy $element * @param int $timeout seconds * @throws Exception */ @@ -2558,7 +2575,7 @@ public function waitForElement($element, int $timeout = 10): void * $I->click('#agree_button'); * ``` * - * @param $element + * @param string|array|WebDriverBy $element * @param int $timeout seconds * @throws Exception */ @@ -2577,7 +2594,7 @@ public function waitForElementVisible($element, int $timeout = 10): void * $I->waitForElementNotVisible('#agree_button', 30); // secs * ``` * - * @param $element + * @param string|array|WebDriverBy $element * @param int $timeout seconds * @throws Exception */ @@ -2597,7 +2614,7 @@ public function waitForElementNotVisible($element, int $timeout = 10): void * $I->click('#agree_button'); * ``` * - * @param $element + * @param string|array|WebDriverBy $element * @param int $timeout seconds * @throws Exception */ @@ -2621,9 +2638,10 @@ public function waitForElementClickable($element, int $timeout = 10): void * ``` * * @param int $timeout seconds + * @param null|string|array|WebDriverBy $selector * @throws Exception */ - public function waitForText(string $text, int $timeout = 10, string $selector = null): void + public function waitForText(string $text, int $timeout = 10, $selector = null): void { $message = sprintf( 'Waited for %d secs but text %s still not found', @@ -2675,6 +2693,7 @@ public function wait($timeout): void * If Codeception lacks a feature you need, please implement it and submit a patch. * * @param Closure $function + * @return mixed */ public function executeInSelenium(Closure $function) { @@ -2883,8 +2902,8 @@ public function maximizeWindow(): void * $I->dragAndDrop('#drag', '#drop'); * ``` * - * @param string $source (CSS ID or XPath) - * @param string $target (CSS ID or XPath) + * @param string|array|WebDriverBy $source (CSS ID or XPath) + * @param string|array|WebDriverBy $target (CSS ID or XPath) */ public function dragAndDrop(string $source, string $target): void { @@ -2909,10 +2928,10 @@ public function dragAndDrop(string $source, string $target): void * $I->moveMouseOver(['css' => '.checkout'], 20, 50); * ``` * - * @param string|null $cssOrXPath css or xpath of the web element + * @param null|string|array|WebDriverBy $cssOrXPath css or xpath of the web element * @throws ElementNotFound */ - public function moveMouseOver(string $cssOrXPath = null, int $offsetX = null, int $offsetY = null): void + public function moveMouseOver($cssOrXPath = null, int $offsetX = null, int $offsetY = null): void { $where = null; if (null !== $cssOrXPath) { @@ -2937,11 +2956,11 @@ public function moveMouseOver(string $cssOrXPath = null, int $offsetX = null, in * $I->clickWithLeftButton(['css' => '.checkout'], 20, 50); * ``` * - * @param string|null $cssOrXPath css or xpath of the web element (body by default). + * @param null|string|array|WebDriverBy $cssOrXPath css or xpath of the web element (body by default). * * @throws ElementNotFound */ - public function clickWithLeftButton(string $cssOrXPath = null, int $offsetX = null, int $offsetY = null): void + public function clickWithLeftButton($cssOrXPath = null, int $offsetX = null, int $offsetY = null): void { $this->moveMouseOver($cssOrXPath, $offsetX, $offsetY); $this->webDriver->getMouse()->click(); @@ -2961,10 +2980,10 @@ public function clickWithLeftButton(string $cssOrXPath = null, int $offsetX = nu * $I->clickWithRightButton(['css' => '.checkout'], 20, 50); * ``` * - * @param string|null $cssOrXPath css or xpath of the web element (body by default). + * @param null|string|array|WebDriverBy $cssOrXPath css or xpath of the web element (body by default). * @throws ElementNotFound */ - public function clickWithRightButton(string $cssOrXPath = null, int $offsetX = null, int $offsetY = null): void + public function clickWithRightButton($cssOrXPath = null, int $offsetX = null, int $offsetY = null): void { $this->moveMouseOver($cssOrXPath, $offsetX, $offsetY); $this->webDriver->getMouse()->contextClick(); @@ -2974,7 +2993,7 @@ public function clickWithRightButton(string $cssOrXPath = null, int $offsetX = n /** * Performs a double click on an element matched by CSS or XPath. * - * @param $cssOrXPath + * @param string|array|WebDriverBy $cssOrXPath * @throws ElementNotFound */ public function doubleClick($cssOrXPath): void @@ -2983,7 +3002,11 @@ public function doubleClick($cssOrXPath): void $this->webDriver->getMouse()->doubleClick($el->getCoordinates()); } - protected function match($page, $selector, bool $throwMalformed = true): array + /** + * @param string|array|WebDriverBy $selector + * @return WebDriverElement[] + */ + protected function match(WebDriverSearchContext $page, $selector, bool $throwMalformed = true): array { if (is_array($selector)) { try { @@ -3078,9 +3101,10 @@ protected function getStrictLocator(array $by): WebDriverBy } /** + * @param string|array|WebDriverBy $selector * @throws ElementNotFound */ - protected function matchFirstOrFail($page, $selector): WebDriverElement + protected function matchFirstOrFail(WebDriverSearchContext $page, $selector): WebDriverElement { $this->enableImplicitWait(); $els = $this->match($page, $selector); @@ -3108,36 +3132,36 @@ protected function matchFirstOrFail($page, $selector): WebDriverElement * $I->pressKey('#name', array('ctrl', 'a'), \Facebook\WebDriver\WebDriverKeys::DELETE); //=>'' * ``` * - * @param $char string|array Can be char or array with modifier. You can provide several chars. + * @param string|array|WebDriverBy $element + * @param array$chars Can be char or array with modifier. You can provide several chars. * @throws ElementNotFound */ - public function pressKey($element, $char): void + public function pressKey($element, ...$chars): void { $el = $this->matchFirstOrFail($this->getBaseElement(), $element); - $args = func_get_args(); - array_shift($args); $keys = []; - foreach ($args as $key) { - $keys[] = $this->convertKeyModifier($key); + foreach ($chars as $char) { + $keys[] = $this->convertKeyModifier($char); } $el->sendKeys($keys); } /** - * @return array|string + * @param string|string[] $char + * @return string|string[] */ - protected function convertKeyModifier($keys) + protected function convertKeyModifier($char) { - if (!is_array($keys)) { - return $keys; + if (is_string($char)) { + return $char; } - if (!isset($keys[1])) { - return $keys; + if (!isset($char[1])) { + return $char; } - [$modifier, $key] = $keys; + [$modifier, $key] = $char; switch ($modifier) { case 'ctrl': @@ -3151,7 +3175,7 @@ protected function convertKeyModifier($keys) return [WebDriverKeys::META, $key]; } - return $keys; + return $char; } protected function assertNodesContain($text, $nodes, $selector = null): void @@ -3176,7 +3200,7 @@ protected function assertNodeConstraint($nodes, WebDriverConstraint $constraint, $this->assertThat($nodes, $constraint, $message); } - protected function assertPageContains($needle, $message = ''): void + protected function assertPageContains($needle, string $message = ''): void { $this->assertThat( htmlspecialchars_decode($this->getVisibleText()), @@ -3185,7 +3209,7 @@ protected function assertPageContains($needle, $message = ''): void ); } - protected function assertPageNotContains($needle, $message = ''): void + protected function assertPageNotContains($needle, string $message = ''): void { $this->assertThatItsNot( htmlspecialchars_decode($this->getVisibleText()), @@ -3194,7 +3218,7 @@ protected function assertPageNotContains($needle, $message = ''): void ); } - protected function assertPageSourceContains($needle, $message = ''): void + protected function assertPageSourceContains($needle, string $message = ''): void { $this->assertThat( $this->webDriver->getPageSource(), @@ -3203,7 +3227,7 @@ protected function assertPageSourceContains($needle, $message = ''): void ); } - protected function assertPageSourceNotContains($needle, $message = ''): void + protected function assertPageSourceNotContains($needle, string $message = ''): void { $this->assertThatItsNot( $this->webDriver->getPageSource(), @@ -3222,9 +3246,11 @@ protected function assertPageSourceNotContains($needle, $message = ''): void * $I->appendField('#myTextField', 'appended'); * ``` * + * @param string|array|WebDriverBy $field + * @param string $value * @throws ElementNotFound */ - public function appendField(string $field, string $value): void + public function appendField($field, string $value): void { $el = $this->findField($field); @@ -3288,6 +3314,9 @@ public function appendField(string $field, string $value): void throw new ElementNotFound($field, "Field by name, label, CSS or XPath"); } + /** + * @param string|array|WebDriverBy $selector + */ protected function matchVisible($selector): array { $els = $this->match($this->getBaseElement(), $selector); @@ -3298,6 +3327,7 @@ protected function matchVisible($selector): array } /** + * @param string|array|WebDriverBy $selector * @throws InvalidArgumentException */ protected function getLocator($selector): WebDriverBy @@ -3342,7 +3372,7 @@ public function saveSessionSnapshot($name) $this->debugSection('Snapshot', sprintf('Saved "%s" session snapshot', $name)); } - public function loadSessionSnapshot($name) + public function loadSessionSnapshot($name): bool { if (!isset($this->sessionSnapshots[$name])) { return false; @@ -3421,7 +3451,7 @@ protected function isPhantom(): bool * $I->scrollTo(['css' => '.checkout'], 20, 50); * ``` * - * @param $selector + * @param string|array|WebDriverBy $selector */ public function scrollTo($selector, int $offsetX = null, int $offsetY = null): void { @@ -3563,8 +3593,8 @@ protected function getRelativeTabHandle($offset) * * In 3rd argument you can set number a seconds to wait for element to appear * - * @param $element - * @param callable|array $actions + * @param string|array|WebDriverBy $element + * @param callable|array|ActionSequence $actions */ public function performOn($element, $actions, int $timeout = 10): void { @@ -3590,6 +3620,9 @@ public function performOn($element, $actions, int $timeout = 10): void $this->setBaseElement(); } + /** + * @param string|array|WebDriverBy $element + */ protected function setBaseElement($element = null): void { if ($element === null) { @@ -3639,29 +3672,29 @@ protected function disableImplicitWait(): void * @return string Converted string */ private static function xPathLiteral($s): string - { - if (false === strpos($s, "'")) { - return sprintf("'%s'", $s); - } + { + if (false === strpos($s, "'")) { + return sprintf("'%s'", $s); + } - if (false === strpos($s, '"')) { - return sprintf('"%s"', $s); - } + if (false === strpos($s, '"')) { + return sprintf('"%s"', $s); + } - $string = $s; - $parts = []; - while (true) { - if (false !== $pos = strpos($string, "'")) { - $parts[] = sprintf("'%s'", substr($string, 0, $pos)); - $parts[] = "\"'\""; - $string = substr($string, $pos + 1); - } else { - $parts[] = "'{$string}'"; - break; - } + $string = $s; + $parts = []; + while (true) { + if (false !== $pos = strpos($string, "'")) { + $parts[] = sprintf("'%s'", substr($string, 0, $pos)); + $parts[] = "\"'\""; + $string = substr($string, $pos + 1); + } else { + $parts[] = "'{$string}'"; + break; } - - return sprintf('concat(%s)', implode(', ', $parts)); } + return sprintf('concat(%s)', implode(', ', $parts)); + } + }