Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"name": "codeception/lib-innerbrowser",
"description": "Parent library for all Codeception framework modules and PhpBrowser",
"keywords": [ "codeception" ],
"homepage": "https://codeception.com/",
"type": "library",
"license": "MIT",
"type": "library",
"keywords": [
"codeception"
],
"authors": [
{
"name": "Michael Bodnarchuk",
Expand All @@ -15,29 +16,31 @@
"name": "Gintautas Miselis"
}
],
"minimum-stability": "dev",
"homepage": "https://codeception.com/",
"require": {
"php": "^8.0",
"ext-dom": "*",
"ext-json": "*",
"ext-mbstring": "*",
"codeception/codeception": "^5.0.0-alpha1",
"symfony/browser-kit": "^4.4 | ^5.4 | ^6.0",
"symfony/dom-crawler": "^4.4 | ^5.4 | ^6.0"
"codeception/codeception": "dev-5.0-interfaces as 5.0.0",
"symfony/browser-kit": "^4.4 || ^5.4 || ^6.0",
"symfony/dom-crawler": "^4.4 || ^5.4 || ^6.0"
},
"require-dev": {
"codeception/util-universalframework": "dev-master"
},
"conflict": {
"codeception/codeception": "<5.0"
},
"minimum-stability": "dev",
"autoload": {
"classmap": [
"src/"
]
},
"config": {
"classmap-authoritative": true
"classmap-authoritative": true,
"sort-packages": true
},
"scripts": {
"test": "codecept run --coverage-xml"
Expand Down
84 changes: 36 additions & 48 deletions src/Codeception/Lib/InnerBrowser.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public function _failed(TestInterface $test, $fail)
if (!$this->client || !$this->client->getInternalResponse()) {
return;
}
} catch (BadMethodCallException $exception) {
} catch (BadMethodCallException) {
//Symfony 5 throws exception if request() method threw an exception.
//The "request()" method must be called before "Symfony\Component\BrowserKit\AbstractBrowser::getInternalResponse()"
return;
Expand All @@ -93,7 +93,7 @@ public function _failed(TestInterface $test, $fail)

try {
$internalResponse = $this->client->getInternalResponse();
} catch (BadMethodCallException $exception) {
} catch (BadMethodCallException) {
$internalResponse = false;
}

Expand Down Expand Up @@ -124,7 +124,7 @@ public function _conflicts(): string
return \Codeception\Lib\Interfaces\Web::class;
}

public function _findElements($locator)
public function _findElements(mixed $locator): iterable
{
return $this->match($locator);
}
Expand Down Expand Up @@ -215,7 +215,7 @@ protected function clientRequest(
if (preg_match('#^(//|https?://(?!localhost))#', $uri)) {
$hostname = parse_url($uri, PHP_URL_HOST);
if (!$this->isInternalDomain($hostname)) {
throw new ExternalUrlException(get_class($this) . " can't open external URL: " . $uri);
throw new ExternalUrlException($this::class . " can't open external URL: " . $uri);
}
}

Expand Down Expand Up @@ -308,7 +308,7 @@ private function getRunningClient(): AbstractBrowser
"Page not loaded. Use `\$I->amOnPage` (or hidden API methods `_request` and `_loadPage`) to open it"
);
}
} catch (BadMethodCallException $e) {
} catch (BadMethodCallException) {
//Symfony 5
throw new ModuleException(
$this,
Expand Down Expand Up @@ -421,15 +421,15 @@ public function click($link, $context = null): void

try {
$this->clickByLocator($link);
} catch (MalformedLocatorException $exception) {
} catch (MalformedLocatorException) {
throw new ElementNotFound("name={$link}", "'{$link}' is invalid CSS and XPath selector and Link or Button");
}
}

/**
* @param string|string[] $link
*/
protected function clickByLocator($link): ?bool
protected function clickByLocator(string|array $link): ?bool
{
$nodes = $this->match($link);
if ($nodes->count() === 0) {
Expand Down Expand Up @@ -633,7 +633,7 @@ public function dontSeeCurrentUrlMatches(string $uri): void
$this->assertNotRegExp($uri, $this->_getCurrentUri());
}

public function grabFromCurrentUrl($uri = null)
public function grabFromCurrentUrl(string $uri = null): mixed
{
if (!$uri) {
return $this->_getCurrentUri();
Expand Down Expand Up @@ -722,7 +722,6 @@ protected function proceedSeeInFormFields($formSelector, array $params, $assertN
* @param SymfonyCrawler $form The form in which to search for fields.
* @param string $name The field's name.
* @param mixed $values
* @return void
*/
protected function pushFormField(array &$fields, SymfonyCrawler $form, string $name, $values): void
{
Expand Down Expand Up @@ -770,10 +769,8 @@ protected function proceedSeeInField(Crawler $fields, $value): array

/**
* Get the values of a set of fields and also the texts of selected options.
*
* @return array|string
*/
protected function getValueAndTextFromField(Crawler $nodes)
protected function getValueAndTextFromField(Crawler $nodes): array|string
{
if ($nodes->filter('textarea')->count() !== 0) {
return (new TextareaFormField($nodes->filter('textarea')->getNode(0)))->getValue();
Expand Down Expand Up @@ -802,10 +799,8 @@ protected function getValueAndTextFromField(Crawler $nodes)

/**
* Get the values of a set of input fields.
*
* @return array|string
*/
protected function getInputValue(SymfonyCrawler $input)
protected function getInputValue(SymfonyCrawler $input): array|string
{
$inputType = $input->attr('type');
if ($inputType === 'checkbox' || $inputType === 'radio') {
Expand All @@ -830,7 +825,7 @@ protected function getInputValue(SymfonyCrawler $input)
*/
protected function getSubmissionFormFieldName(string $name): string
{
if (substr($name, -2) === '[]') {
if (str_ends_with($name, '[]')) {
return substr($name, 0, -2);
}

Expand All @@ -857,7 +852,7 @@ protected function setCheckboxBoolValues(Crawler $form, array $params): array
$chFoundByName = [];
foreach ($checkboxes as $checkbox) {
$fieldName = $this->getSubmissionFormFieldName($checkbox->getAttribute('name'));
$pos = (isset($chFoundByName[$fieldName])) ? $chFoundByName[$fieldName] : 0;
$pos = $chFoundByName[$fieldName] ?? 0;
$skip = !isset($params[$fieldName])
|| (!is_array($params[$fieldName]) && !is_bool($params[$fieldName]))
|| (is_array($params[$fieldName]) &&
Expand Down Expand Up @@ -966,7 +961,7 @@ public function submitForm($selector, array $params, string $button = null): voi
protected function getAbsoluteUrlFor(string $uri): string
{
$currentUrl = $this->getRunningClient()->getHistory()->current()->getUri();
if (empty($uri) || strpos($uri, '#') === 0) {
if (empty($uri) || str_starts_with($uri, '#')) {
return $currentUrl;
}

Expand Down Expand Up @@ -1111,7 +1106,7 @@ protected function getFormValuesFor(SymfonyForm $form): array


$fieldName = $this->getSubmissionFormFieldName($field->getName());
if (substr($field->getName(), -2) === '[]') {
if (str_ends_with($field->getName(), '[]')) {
if (!isset($values[$fieldName])) {
$values[$fieldName] = [];
}
Expand Down Expand Up @@ -1146,6 +1141,7 @@ public function fillField($field, $value): void

protected function getFieldsByLabelOrCss($field): SymfonyCrawler
{
$input = null;
if (is_array($field)) {
$input = $this->strictMatch($field);
if (count($input) === 0) {
Expand Down Expand Up @@ -1233,10 +1229,9 @@ public function selectOption($select, $option): void
}

/**
* @param string|array $option
* @return mixed
*/
protected function matchOption(Crawler $field, $option)
protected function matchOption(Crawler $field, string|array $option)
{
if (isset($option['value'])) {
return $option['value'];
Expand Down Expand Up @@ -1280,7 +1275,7 @@ public function uncheckOption($option): void
/**
* @param string|string[] $option
*/
protected function proceedCheckOption($option): ChoiceFormField
protected function proceedCheckOption(string|array $option): ChoiceFormField
{
$form = $this->getFormFor($field = $this->getFieldByLabelOrCss($option));
$name = $field->attr('name');
Expand Down Expand Up @@ -1419,7 +1414,7 @@ protected function getResponseStatusCode()
/**
* @param string|string[] $selector
*/
protected function match($selector): SymfonyCrawler
protected function match(string|array $selector): SymfonyCrawler
{
if (is_array($selector)) {
return $this->strictMatch($selector);
Expand All @@ -1444,24 +1439,17 @@ protected function strictMatch(array $by): SymfonyCrawler
{
$type = key($by);
$locator = $by[$type];
switch ($type) {
case 'id':
return $this->filterByCSS(sprintf('#%s', $locator));
case 'name':
return $this->filterByXPath(sprintf('.//*[@name=%s]', SymfonyCrawler::xpathLiteral($locator)));
case 'css':
return $this->filterByCSS($locator);
case 'xpath':
return $this->filterByXPath($locator);
case 'link':
return $this->filterByXPath(sprintf('.//a[.=%s or contains(./@title, %s)]', SymfonyCrawler::xpathLiteral($locator), SymfonyCrawler::xpathLiteral($locator)));
case 'class':
return $this->filterByCSS(".{$locator}");
default:
throw new TestRuntimeException(
"Locator type '{$by}' is not defined. Use either: xpath, css, id, link, class, name"
);
}
return match ($type) {
'id' => $this->filterByCSS(sprintf('#%s', $locator)),
'name' => $this->filterByXPath(sprintf('.//*[@name=%s]', SymfonyCrawler::xpathLiteral($locator))),
'css' => $this->filterByCSS($locator),
'xpath' => $this->filterByXPath($locator),
'link' => $this->filterByXPath(sprintf('.//a[.=%s or contains(./@title, %s)]', SymfonyCrawler::xpathLiteral($locator), SymfonyCrawler::xpathLiteral($locator))),
'class' => $this->filterByCSS(".{$locator}"),
default => throw new TestRuntimeException(
"Locator type '{$by}' is not defined. Use either: xpath, css, id, link, class, name"
),
};
}

protected function filterByAttributes(Crawler $nodes, array $attributes)
Expand All @@ -1475,7 +1463,7 @@ protected function filterByAttributes(Crawler $nodes, array $attributes)
return $nodes;
}

public function grabTextFrom($cssOrXPathOrRegex)
public function grabTextFrom($cssOrXPathOrRegex): mixed
{
if (is_string($cssOrXPathOrRegex) && @preg_match($cssOrXPathOrRegex, $this->client->getInternalResponse()->getContent(), $matches)) {
return $matches[1];
Expand All @@ -1489,7 +1477,7 @@ public function grabTextFrom($cssOrXPathOrRegex)
throw new ElementNotFound($cssOrXPathOrRegex, 'Element that matches CSS or XPath or Regex');
}

public function grabAttributeFrom($cssOrXpath, $attribute)
public function grabAttributeFrom($cssOrXpath, string $attribute): mixed
{
$nodes = $this->match($cssOrXpath);
if ($nodes->count() === 0) {
Expand All @@ -1511,7 +1499,7 @@ public function grabMultiple($cssOrXpath, string $attribute = null): array
return $result;
}

public function grabValueFrom($field)
public function grabValueFrom($field): mixed
{
$nodes = $this->match($field);
if ($nodes->count() === 0) {
Expand Down Expand Up @@ -1566,7 +1554,7 @@ public function setCookie($name, $val, $params = [])
$this->debugCookieJar();
}

public function grabCookie($cookie, $params = [])
public function grabCookie(string $cookie, array $params = []): mixed
{
$params = array_merge($this->defaultCookieParameters, $params);
$this->debugCookieJar();
Expand Down Expand Up @@ -1869,11 +1857,10 @@ protected function assertPageSourceNotContains(string $needle, string $message =

/**
* @param array|object $form
* @return FormField|array
*/
protected function matchFormField(string $name, $form, FormField $dynamicField)
protected function matchFormField(string $name, $form, FormField $dynamicField): FormField|array
{
if (substr($name, -2) !== '[]') {
if (!str_ends_with($name, '[]')) {
return $form[$name];
}

Expand Down Expand Up @@ -1986,6 +1973,7 @@ public function switchToIframe(string $name): void
*/
public function moveBack(int $numberOfSteps = 1): void
{
$request = null;
if (!is_int($numberOfSteps) || $numberOfSteps < 1) {
throw new InvalidArgumentException('numberOfSteps must be positive integer');
}
Expand Down
Loading