Skip to content

Commit

Permalink
Decoupled the DriverInterface from the NodeElement
Browse files Browse the repository at this point in the history
This avoids a circular dependency. The driver interface now returns an
array of XPath for found elements, and Element::find() instantiates the
NodeElement for them.
The driver is now the low level API which does not depend on any other
part of Mink (but used by other parts).
The ElementFinder is responsible for instantiating the NodeElement.
  • Loading branch information
stof committed Jun 13, 2023
1 parent c73d508 commit c76a7e6
Show file tree
Hide file tree
Showing 10 changed files with 25 additions and 102 deletions.
27 changes: 2 additions & 25 deletions src/Driver/CoreDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@

namespace Behat\Mink\Driver;

use Behat\Mink\Element\NodeElement;
use Behat\Mink\Exception\UnsupportedDriverActionException;
use Behat\Mink\KeyModifier;
use Behat\Mink\Session;

/**
* Core driver.
Expand All @@ -23,21 +21,6 @@
*/
abstract class CoreDriver implements DriverInterface
{
/**
* @var Session
*/
private $session;

/**
* @return void
*
* @final since 1.11
*/
public function setSession(Session $session)
{
$this->session = $session;
}

/**
* @return void
*/
Expand Down Expand Up @@ -99,19 +82,13 @@ public function getContent()
/**
* @param string $xpath
*
* @return NodeElement[]
* @return string[]
*
* @final since 1.11
*/
public function find($xpath)
{
$elements = array();

foreach ($this->findElementXpaths($xpath) as $xpath) {
$elements[] = new NodeElement($xpath, $this, $this->session->getElementFinder());
}

return $elements;
return $this->findElementXpaths($xpath);
}

/**
Expand Down
13 changes: 1 addition & 12 deletions src/Driver/DriverInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@

namespace Behat\Mink\Driver;

use Behat\Mink\Element\NodeElement;
use Behat\Mink\Exception\DriverException;
use Behat\Mink\Exception\UnsupportedDriverActionException;
use Behat\Mink\KeyModifier;
use Behat\Mink\Session;

/**
* Driver interface.
Expand All @@ -23,15 +21,6 @@
*/
interface DriverInterface
{
/**
* Sets driver's current session.
*
* @param Session $session
*
* @return void
*/
public function setSession(Session $session);

/**
* Starts driver.
*
Expand Down Expand Up @@ -299,7 +288,7 @@ public function getWindowName();
*
* @param string $xpath
*
* @return NodeElement[]
* @return string[] An array of XPath queries for the found elements
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
Expand Down
2 changes: 1 addition & 1 deletion src/Element/Element.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public function find($selector, $locator)
{
$items = $this->findAll($selector, $locator);

return count($items) ? current($items) : null;
return count($items) ? $items[0] : null;
}

/**
Expand Down
12 changes: 9 additions & 3 deletions src/Element/ElementFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ public function __construct(DriverInterface $driver, SelectorsHandler $selectors
/**
* @param string|array $locator
*
* @return NodeElement[]
* @return list<NodeElement>
*/
public function findAll(string $selector, $locator, string $parentXpath)
public function findAll(string $selector, $locator, string $parentXpath): array
{
if ('named' === $selector) {
$items = $this->findAll('named_exact', $locator, $parentXpath);
Expand All @@ -59,6 +59,12 @@ public function findAll(string $selector, $locator, string $parentXpath)
$xpath = $this->selectorsHandler->selectorToXpath($selector, $locator);
$xpath = $this->xpathManipulator->prepend($xpath, $parentXpath);

return $this->driver->find($xpath);
$elements = array();

foreach ($this->driver->find($xpath) as $elementXpath) {
$elements[] = new NodeElement($elementXpath, $this->driver, $this);
}

return $elements;
}
}
2 changes: 1 addition & 1 deletion src/Element/NodeElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class NodeElement extends TraversableElement
/**
* Initializes node element.
*
* @param string $xpath element xpath
* @param string $xpath element xpath
* @param DriverInterface $driver
* @param ElementFinder $elementFinder
*/
Expand Down
20 changes: 3 additions & 17 deletions src/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

use Behat\Mink\Driver\DriverInterface;
use Behat\Mink\Element\ElementFinder;
use Behat\Mink\Selector\SelectorsHandler;
use Behat\Mink\Element\DocumentElement;
use Behat\Mink\Selector\SelectorsHandler;

/**
* Mink session.
Expand All @@ -30,18 +30,12 @@ class Session
* @var DocumentElement
*/
private $page;
/**
* @var ElementFinder
*/
private $elementFinder;

public function __construct(DriverInterface $driver, SelectorsHandler $selectorsHandler = null)
{
$this->driver = $driver;
$this->elementFinder = new ElementFinder($driver, $selectorsHandler ?? new SelectorsHandler());
$this->page = new DocumentElement($driver, $this->elementFinder);

$driver->setSession($this);
$elementFinder = new ElementFinder($driver, $selectorsHandler ?? new SelectorsHandler());
$this->page = new DocumentElement($driver, $elementFinder);
}

/**
Expand Down Expand Up @@ -131,14 +125,6 @@ public function getPage()
return $this->page;
}

/**
* @internal
*/
public function getElementFinder(): ElementFinder
{
return $this->elementFinder;
}

/**
* Visit specified URL and automatically start session if not already running.
*
Expand Down
16 changes: 2 additions & 14 deletions tests/Driver/CoreDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace Behat\Mink\Tests\Driver;

use Behat\Mink\Element\ElementFinder;
use Behat\Mink\Element\NodeElement;
use PHPUnit\Framework\TestCase;

class CoreDriverTest extends TestCase
Expand All @@ -27,29 +25,19 @@ public function testCreateNodeElements()
->setMethods(array('findElementXpaths'))
->getMockForAbstractClass();

$session = $this->getMockBuilder('Behat\Mink\Session')
->disableOriginalConstructor()
->getMock();

$session->method('getElementFinder')->willReturn($this->createMock(ElementFinder::class));

$driver->setSession($session);

$driver->expects($this->once())
->method('findElementXpaths')
->with('xpath')
->willReturn(array('xpath1', 'xpath2'));

/** @var NodeElement[] $elements */
$elements = $driver->find('xpath');

$this->assertIsArray($elements);

$this->assertCount(2, $elements);
$this->assertContainsOnlyInstancesOf('Behat\Mink\Element\NodeElement', $elements);

$this->assertSame('xpath1', $elements[0]->getXpath());
$this->assertSame('xpath2', $elements[1]->getXpath());
$this->assertSame('xpath1', $elements[0]);
$this->assertSame('xpath2', $elements[1]);
}

/**
Expand Down
24 changes: 3 additions & 21 deletions tests/Element/ElementFinderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,6 @@ public function testNotFound()

public function testFound()
{
$element1 = $this->createStub(NodeElement::class);
$element1->method('getXpath')->willReturn('element1');

$element2 = $this->createStub(NodeElement::class);
$element2->method('getXpath')->willReturn('element2');

$this->selectorsHandler->expects($this->once())
->method('selectorToXpath')
->with('css', 'h3 > a')
Expand All @@ -82,7 +76,7 @@ public function testFound()
$this->driver->expects($this->once())
->method('find')
->with('full_xpath')
->will($this->returnValue(array($element1, $element2)));
->will($this->returnValue(array('element1', 'element2')));

$results = $this->finder->findAll('css', 'h3 > a', 'parent_xpath');

Expand All @@ -94,12 +88,6 @@ public function testFound()

public function testNamedFound()
{
$element1 = $this->createStub(NodeElement::class);
$element1->method('getXpath')->willReturn('element1');

$element2 = $this->createStub(NodeElement::class);
$element2->method('getXpath')->willReturn('element2');

$this->selectorsHandler->expects($this->once())
->method('selectorToXpath')
->with('named_exact', 'test')
Expand All @@ -113,7 +101,7 @@ public function testNamedFound()
$this->driver->expects($this->once())
->method('find')
->with('full_xpath')
->will($this->returnValue(array($element1, $element2)));
->will($this->returnValue(array('element1', 'element2')));

$results = $this->finder->findAll('named', 'test', 'parent_xpath');

Expand All @@ -125,12 +113,6 @@ public function testNamedFound()

public function testNamedPartialFallback()
{
$element1 = $this->createStub(NodeElement::class);
$element1->method('getXpath')->willReturn('element1');

$element2 = $this->createStub(NodeElement::class);
$element2->method('getXpath')->willReturn('element2');

$this->selectorsHandler->expects($this->exactly(2))
->method('selectorToXpath')
->will($this->returnValueMap(array(
Expand All @@ -149,7 +131,7 @@ public function testNamedPartialFallback()
->method('find')
->willReturnMap(array(
array('full_xpath', array()),
array('full_partial_xpath', array($element1, $element2)),
array('full_partial_xpath', array('element1', 'element2')),
));

$results = $this->finder->findAll('named', 'test', 'parent_xpath');
Expand Down
4 changes: 2 additions & 2 deletions tests/Element/NodeElementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function testElementIsValid()
->expects($this->once())
->method('find')
->with($elementXpath)
->willReturn(array($this->createStub(NodeElement::class)));
->willReturn(array($elementXpath));

$this->assertTrue($node->isValid());
}
Expand All @@ -78,7 +78,7 @@ public function testElementIsNotValidWithMultipleFound()
->expects($this->once())
->method('find')
->with('some xpath')
->willReturn(array($this->createStub(NodeElement::class), $this->createStub(NodeElement::class)));
->willReturn(array('some xpath', 'some other xpath'));

$this->assertFalse($node->isValid(), 'more then 1 element found is invalid element');
}
Expand Down
7 changes: 1 addition & 6 deletions tests/SessionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ class SessionTest extends TestCase
* @var DriverInterface&MockObject
*/
private $driver;
/**
* @var SelectorsHandler
*/
private $selectorsHandler;

/**
* Session.
Expand All @@ -32,8 +28,7 @@ class SessionTest extends TestCase
protected function prepareSession(): void
{
$this->driver = $this->getMockBuilder('Behat\Mink\Driver\DriverInterface')->getMock();
$this->selectorsHandler = $this->getMockBuilder('Behat\Mink\Selector\SelectorsHandler')->getMock();
$this->session = new Session($this->driver, $this->selectorsHandler);
$this->session = new Session($this->driver);
}

public function testGetDriver()
Expand Down

0 comments on commit c76a7e6

Please sign in to comment.