Skip to content

Commit

Permalink
Added helper find and findAll methods (#102)
Browse files Browse the repository at this point in the history
* Added helper find and findAll methods

* PHPStan refactoring
  • Loading branch information
mnocon authored Feb 5, 2024
1 parent 3dc6022 commit 7c3c897
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 387 deletions.
355 changes: 0 additions & 355 deletions phpstan-baseline.neon

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ includes:
- vendor/phpstan/phpstan-symfony/extension.neon

parameters:
treatPhpDocTypesAsCertain: false
level: 8
paths:
- src
Expand Down
1 change: 1 addition & 0 deletions src/lib/Browser/Assert/CollectionAssertInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ public function hasElements(): ElementCollectionInterface;

public function countEquals(int $expectedCount): ElementCollectionInterface;

/** @param array<string> $expectedElementTexts */
public function containsElementsWithText(array $expectedElementTexts): ElementCollectionInterface;
}
12 changes: 12 additions & 0 deletions src/lib/Browser/Component/Component.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

use Behat\Mink\Session;
use Facebook\WebDriver\Chrome\ChromeDevToolsDriver;
use Ibexa\Behat\Browser\Element\ElementCollectionInterface;
use Ibexa\Behat\Browser\Element\ElementInterface;
use Ibexa\Behat\Browser\Element\Factory\Debug\Highlighting\ElementFactory as HighlightingDebugElementFactory;
use Ibexa\Behat\Browser\Element\Factory\Debug\Interactive\ElementFactory as InteractiveDebugElementFactory;
use Ibexa\Behat\Browser\Element\Factory\ElementFactory;
Expand Down Expand Up @@ -46,6 +48,16 @@ final protected function getHTMLPage(): RootElementInterface
return $this->elementFactory->createRootElement($this->getSession(), $this->elementFactory);
}

public function find(LocatorInterface $locator): ElementInterface
{
return $this->getHTMLPage()->find($locator);
}

public function findAll(LocatorInterface $locator): ElementCollectionInterface
{
return $this->getHTMLPage()->findAll($locator);
}

public function setElementFactory(ElementFactoryInterface $elementFactory): void
{
$this->elementFactory = $elementFactory;
Expand Down
18 changes: 8 additions & 10 deletions src/lib/Browser/Element/BaseElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,18 @@

namespace Ibexa\Behat\Browser\Element;

use Behat\Mink\Element\ElementInterface as MinkElementInterface;
use Ibexa\Behat\Browser\Element\Condition\ConditionInterface;
use Ibexa\Behat\Browser\Element\Factory\ElementFactoryInterface;
use Ibexa\Behat\Browser\Exception\TimeoutException;
use Ibexa\Behat\Browser\Locator\LocatorInterface;
use Traversable;

class BaseElement implements BaseElementInterface
abstract class BaseElement implements BaseElementInterface
{
/** @var int */
protected $timeout = 1;
protected int $timeout = 1;

/** @var \Behat\Mink\Element\TraversableElement */
protected $decoratedElement;

/** @var \Ibexa\Behat\Browser\Element\Factory\ElementFactoryInterface */
private $elementFactory;
private ElementFactoryInterface $elementFactory;

public function __construct(ElementFactoryInterface $elementFactory)
{
Expand Down Expand Up @@ -83,7 +79,7 @@ public function find(LocatorInterface $locator): ElementInterface
{
return $this->waitUntil(
function () use ($locator) {
$foundMinkElements = $this->decoratedElement->findAll($locator->getType(), $locator->getSelector());
$foundMinkElements = $this->getDecoratedElement()->findAll($locator->getType(), $locator->getSelector());

foreach ($foundMinkElements as $foundMinkElement) {
$wrappedElement = $this->elementFactory->createElement($this->elementFactory, $locator, $foundMinkElement);
Expand Down Expand Up @@ -116,7 +112,7 @@ private function internalFindAll(LocatorInterface $locator): Traversable
{
try {
$minkElements = $this->waitUntil(function () use ($locator) {
$minkElements = $this->decoratedElement->findAll($locator->getType(), $locator->getSelector());
$minkElements = $this->getDecoratedElement()->findAll($locator->getType(), $locator->getSelector());
foreach ($minkElements as $minkElement) {
if (!$minkElement->isValid()) {
return false;
Expand All @@ -138,4 +134,6 @@ private function internalFindAll(LocatorInterface $locator): Traversable
}
}
}

abstract protected function getDecoratedElement(): MinkElementInterface;
}
5 changes: 5 additions & 0 deletions src/lib/Browser/Element/BaseElementInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,10 @@ public function findAll(LocatorInterface $locator): ElementCollectionInterface;

public function waitUntilCondition(ConditionInterface $condition): BaseElementInterface;

/**
* @param callable(mixed): mixed $callback
*
* @return mixed
*/
public function waitUntil(callable $callback, string $errorMessage);
}
12 changes: 9 additions & 3 deletions src/lib/Browser/Element/Element.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@

final class Element extends BaseElement implements ElementInterface
{
/** @var \Ibexa\Behat\Browser\Locator\LocatorInterface */
private $locator;
private LocatorInterface $locator;

private NodeElement $decoratedElement;

public function __construct(ElementFactoryInterface $elementFactory, LocatorInterface $locator, NodeElement $baseElement)
{
Expand Down Expand Up @@ -116,7 +117,7 @@ public function assert(): ElementAssertInterface

public function isValid(): bool
{
return null !== $this->decoratedElement ? $this->decoratedElement->isValid() : false;
return $this->decoratedElement->isValid();
}

public function selectOption(string $option): void
Expand Down Expand Up @@ -153,4 +154,9 @@ public function execute(ActionInterface $action): void
{
$action->execute($this);
}

protected function getDecoratedElement(): NodeElement
{
return $this->decoratedElement;
}
}
18 changes: 9 additions & 9 deletions src/lib/Browser/Element/ElementCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,10 @@

class ElementCollection implements ElementCollectionInterface
{
/** @var ElementInterface[]|\Traversable */
/** @var iterable<ElementInterface> */
private $elements;

/**
* @var \Ibexa\Behat\Browser\Locator\LocatorInterface
*/
private $locator;
private LocatorInterface $locator;

public function __construct(LocatorInterface $locator, iterable $elements)
{
Expand All @@ -38,9 +35,6 @@ public function setElements(array $elements): void
$this->elements = $elements;
}

/**
* @return \Ibexa\Behat\Browser\Element\ElementInterface[]
*/
public function getIterator(): Traversable
{
if (is_array($this->elements)) {
Expand All @@ -64,7 +58,7 @@ public function getByCriterion(CriterionInterface $criterion): ElementInterface
}

/**
* @param callable Callable accepting a NodeElement parameter
* @param callable(ElementInterface): bool $callable
*/
public function getBy(callable $callable): ElementInterface
{
Expand Down Expand Up @@ -208,6 +202,11 @@ public function assert(): CollectionAssertInterface
return new CollectionAssert($this->locator, $this);
}

/**
* @param callable(ElementInterface $element): bool $callable
*
* @return iterable<ElementInterface>
*/
private function internalFilter(callable $callable): iterable
{
foreach ($this->elements as $element) {
Expand All @@ -217,6 +216,7 @@ private function internalFilter(callable $callable): iterable
}
}

/** @return iterable<ElementInterface> */
private function internalFilterBy(CriterionInterface $criterion): iterable
{
foreach ($this->elements as $element) {
Expand Down
14 changes: 13 additions & 1 deletion src/lib/Browser/Element/ElementCollectionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@
interface ElementCollectionInterface extends \Countable, \IteratorAggregate
{
/**
* @return \Ibexa\Behat\Browser\Element\ElementInterface[]
* @return Traversable<ElementInterface>
*/
public function getIterator(): Traversable;

/**
* @param array<ElementInterface> $elements
*/
public function setElements(array $elements): void;

public function getByCriterion(CriterionInterface $criterion): ElementInterface;
Expand All @@ -44,10 +47,19 @@ public function any(): bool;

public function single(): ElementInterface;

/**
* @param callable(ElementInterface): mixed $callable
*
* @return array<mixed>
*/
public function map(callable $callable): array;

/** @return array<mixed> */
public function mapBy(MapperInterface $mapper): array;

/**
* @param callable(ElementInterface): bool $callable
*/
public function filter(callable $callable): ElementCollectionInterface;

public function filterBy(CriterionInterface $criterion): ElementCollectionInterface;
Expand Down
1 change: 1 addition & 0 deletions src/lib/Browser/Element/Mapper/MapperInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@

interface MapperInterface
{
/** @return mixed */
public function map(ElementInterface $element);
}
12 changes: 9 additions & 3 deletions src/lib/Browser/Element/RootElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@

final class RootElement extends BaseElement implements RootElementInterface
{
/** @vat \Behat\Mink\Session */
private $session;
private Session $session;

private DocumentElement $decoratedElement;

public function __construct(ElementFactoryInterface $elementFactory, Session $session, DocumentElement $baseElement)
{
Expand All @@ -42,6 +43,11 @@ private function isDraggingLibraryLoaded(): bool

public function executeJavaScript(string $script): string
{
return (string) $this->session->evaluateScript($script) ?? '';
return $this->session->evaluateScript($script) ?? '';
}

protected function getDecoratedElement(): DocumentElement
{
return $this->decoratedElement;
}
}
4 changes: 2 additions & 2 deletions src/lib/Browser/Locator/BaseLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@

abstract class BaseLocator implements LocatorInterface
{
protected $selector;
protected string $selector;

protected $identifier;
protected string $identifier;

public function __construct(string $identifier, string $selector)
{
Expand Down
6 changes: 3 additions & 3 deletions src/lib/Browser/Page/LoginPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ public function logout(): void

public function loginSuccessfully($username, $password): void
{
$this->getHTMLPage()->find($this->getLocator('username'))->setValue($username);
$this->getHTMLPage()->find($this->getLocator('password'))->setValue($password);
$this->getHTMLPage()->findAll($this->getLocator('button'))
$this->find($this->getLocator('username'))->setValue($username);
$this->find($this->getLocator('password'))->setValue($password);
$this->findAll($this->getLocator('button'))
->filterBy(new LogicalOrCriterion([
new ElementTextCriterion('Login'),
new ElementTextCriterion('Log in'),
Expand Down
2 changes: 1 addition & 1 deletion src/lib/Browser/Page/Preview/FolderPreview.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function setExpectedPreviewData(array $data)

public function verifyPreviewData()
{
$this->getHTMLPage()->find($this->getLocator('title'))->assert()->textEquals($this->expectedPageTitle);
$this->find($this->getLocator('title'))->assert()->textEquals($this->expectedPageTitle);
}

public function supports(string $contentTypeIdentifier, string $viewType): bool
Expand Down

0 comments on commit 7c3c897

Please sign in to comment.