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
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ cache:
- $HOME/.composer/cache

before_install:
- wget https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v2.11.1/php-cs-fixer.phar
- wget https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v2.12.1/php-cs-fixer.phar
- wget https://github.com/phpstan/phpstan/releases/download/0.10.1/phpstan.phar

before_script:
- phpenv config-rm xdebug.ini
Expand All @@ -19,3 +20,4 @@ before_script:
script:
- phpunit
- php php-cs-fixer.phar fix --dry-run --diff --no-ansi
- php phpstan.phar analyse src tests --level=6
6 changes: 6 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
parameters:
ignoreErrors:
# https://github.com/symfony/symfony/pull/27849
- '/Parameter #1 \$value of method Symfony\\Component\\DomCrawler\\Field\\ChoiceFormField::select\(\) expects string, array<int, string> given\./'
# Require a redesign of the underlying Symfony components
- '#Panthere\\[a-zA-Z\\]+::__construct\(\) does not call parent constructor from Symfony\\Component\\(BrowserKit|DomCrawler)\\[a-zA-Z]+\.#'
2 changes: 1 addition & 1 deletion src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ final class Client extends BaseClient implements WebDriver
use ExceptionThrower;

/**
* @var WebDriver
* @var WebDriver|null
*/
private $webDriver;
private $browserManager;
Expand Down
3 changes: 3 additions & 0 deletions src/DomCrawler/Crawler.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
use Facebook\WebDriver\WebDriver;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverElement;
use Panthere\ExceptionThrower;
use Symfony\Component\DomCrawler\Crawler as BaseCrawler;

/**
* @author Kévin Dunglas <dunglas@gmail.com>
*/
final class Crawler extends BaseCrawler implements WebDriverElement
{
use ExceptionThrower;

private $elements;
private $webDriver;

Expand Down
8 changes: 6 additions & 2 deletions src/DomCrawler/Field/ChoiceFormField.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,17 @@ public function untick()
/**
* Sets the value of the field.
*
* @param string $value The value of the field
* @param string|array|bool $value The value of the field
*
* @throws \InvalidArgumentException When value type provided is not correct
*/
public function setValue($value)
{
if ('checkbox' === $this->type && \is_bool($value)) {
if (\is_bool($value)) {
if ('checkbox' !== $this->type) {
throw new \InvalidArgumentException(\sprintf('Invalid argument of type "%s"', \gettype($value)));
}

if ($value) {
if (!$this->element->isSelected()) {
$this->element->click();
Expand Down
10 changes: 6 additions & 4 deletions src/DomCrawler/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public function getValues()
}

// Flatten non array-checkboxes
if (!$isArrayElement && 1 === \count($value)) {
if (\is_array($value) && !$isArrayElement && 1 === \count($value)) {
$value = $value[0];
}
}
Expand Down Expand Up @@ -300,10 +300,12 @@ private function setValue(string $name, $value): void
try {
$element = $this->element->findElement(WebDriverBy::name($name));
} catch (NoSuchElementException $e) {
// Compatibility with the DomCrawler API
if (\is_array($value)) {
$element = $this->element->findElement(WebDriverBy::name($name.'[]'));
if (!\is_array($value)) {
throw $e;
}

// Compatibility with the DomCrawler API
$element = $this->element->findElement(WebDriverBy::name($name.'[]'));
}

if (null === $webDriverSelect = $this->getWebDriverSelect($element)) {
Expand Down
110 changes: 4 additions & 106 deletions src/PanthereTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,119 +13,17 @@

namespace Panthere;

use Goutte\Client as GoutteClient;
use GuzzleHttp\Client as GuzzleClient;
use Panthere\Client as PanthereClient;
use Panthere\ProcessManager\WebServerManager;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

if (\class_exists(WebTestCase::class)) {
/**
* @internal
*/
abstract class InternalTestCase extends WebTestCase
abstract class PanthereTestCase extends WebTestCase
{
use PanthereTestCaseTrait;
}
} else {
/**
* @internal
*/
abstract class InternalTestCase extends TestCase
abstract class PanthereTestCase extends TestCase
{
}
}

/**
* @author Kévin Dunglas <dunglas@gmail.com>
*/
abstract class PanthereTestCase extends InternalTestCase
{
/**
* @var string|null
*/
protected static $webServerDir;

/**
* @var WebServerManager|null
*/
protected static $webServerManager;

/**
* @var string|null
*/
protected static $baseUri;

/**
* @var GoutteClient|null
*/
protected static $goutteClient;

/**
* @var PanthereClient|null
*/
protected static $panthereClient;

public static function tearDownAfterClass()
{
if (null !== self::$webServerManager) {
self::$webServerManager->quit();
self::$webServerManager = null;
}

if (null !== self::$panthereClient) {
self::$panthereClient->quit();
self::$panthereClient = null;
}

if (null !== self::$goutteClient) {
self::$goutteClient = null;
}

self::$baseUri = null;
}

protected static function startWebServer(?string $webServerDir = null, string $hostname = '127.0.0.1', int $port = 9000): void
{
if (null !== static::$webServerManager) {
return;
}

if (null === $webServerDir) {
// Try the local $webServerDir property, or the PANTHERE_WEB_SERVER_DIR env var or default to the Flex directory structure
$webServerDir = static::$webServerDir ?? $_ENV['PANTHERE_WEB_SERVER_DIR'] ?? __DIR__.'/../../../../public';
}

self::$webServerManager = new WebServerManager($webServerDir, $hostname, $port);
self::$webServerManager->start();

self::$baseUri = "http://$hostname:$port";
}

protected static function createPanthereClient(string $hostname = '127.0.0.1', int $port = 9000): PanthereClient
{
self::startWebServer(null, $hostname, $port);
if (null === self::$panthereClient) {
self::$panthereClient = Client::createChromeClient(null, null, [], self::$baseUri);
}

return self::$panthereClient;
}

protected static function createGoutteClient(): GoutteClient
{
if (!\class_exists(GoutteClient::class)) {
throw new \RuntimeException('Goutte is not installed. Run "composer req fabpot/goutte".');
}

self::startWebServer();
if (null === self::$goutteClient) {
$goutteClient = new GoutteClient();
$goutteClient->setClient(new GuzzleClient(['base_uri' => self::$baseUri]));

self::$goutteClient = $goutteClient;
}

return self::$goutteClient;
use PanthereTestCaseTrait;
}
}
117 changes: 117 additions & 0 deletions src/PanthereTestCaseTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php

/*
* This file is part of the Panthère project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Panthere;

use Goutte\Client as GoutteClient;
use GuzzleHttp\Client as GuzzleClient;
use Panthere\Client as PanthereClient;
use Panthere\ProcessManager\WebServerManager;

/**
* Eases conditional class definition.
*
* @internal
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
trait PanthereTestCaseTrait
{
/**
* @var string|null
*/
protected static $webServerDir;

/**
* @var WebServerManager|null
*/
protected static $webServerManager;

/**
* @var string|null
*/
protected static $baseUri;

/**
* @var GoutteClient|null
*/
protected static $goutteClient;

/**
* @var PanthereClient|null
*/
protected static $panthereClient;

public static function tearDownAfterClass()
{
if (null !== self::$webServerManager) {
self::$webServerManager->quit();
self::$webServerManager = null;
}

if (null !== self::$panthereClient) {
self::$panthereClient->quit();
self::$panthereClient = null;
}

if (null !== self::$goutteClient) {
self::$goutteClient = null;
}

self::$baseUri = null;
}

protected static function startWebServer(?string $webServerDir = null, string $hostname = '127.0.0.1', int $port = 9000): void
{
if (null !== static::$webServerManager) {
return;
}

if (null === $webServerDir) {
// Try the local $webServerDir property, or the PANTHERE_WEB_SERVER_DIR env var or default to the Flex directory structure
$webServerDir = static::$webServerDir ?? $_ENV['PANTHERE_WEB_SERVER_DIR'] ?? __DIR__.'/../../../../public';
}

self::$webServerManager = new WebServerManager($webServerDir, $hostname, $port);
self::$webServerManager->start();

self::$baseUri = "http://$hostname:$port";
}

protected static function createPanthereClient(string $hostname = '127.0.0.1', int $port = 9000): PanthereClient
{
self::startWebServer(null, $hostname, $port);
if (null === self::$panthereClient) {
self::$panthereClient = Client::createChromeClient(null, null, [], self::$baseUri);
}

return self::$panthereClient;
}

protected static function createGoutteClient(): GoutteClient
{
if (!\class_exists(GoutteClient::class)) {
throw new \RuntimeException('Goutte is not installed. Run "composer req fabpot/goutte".');
}

self::startWebServer();
if (null === self::$goutteClient) {
$goutteClient = new GoutteClient();
$goutteClient->setClient(new GuzzleClient(['base_uri' => self::$baseUri]));

self::$goutteClient = $goutteClient;
}

return self::$goutteClient;
}
}
2 changes: 0 additions & 2 deletions src/ProcessManager/ChromeManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ public function __construct(?string $chromeDriverBinary = null, ?array $argument
}

/**
* @param string[]|null $arguments
*
* @throws \RuntimeException
*/
public function start(): WebDriver
Expand Down
Loading