aboutsummaryrefslogtreecommitdiffstats
path: root/tests/acceptance/features/core
diff options
context:
space:
mode:
Diffstat (limited to 'tests/acceptance/features/core')
-rw-r--r--tests/acceptance/features/core/Actor.php214
-rw-r--r--tests/acceptance/features/core/ActorAware.php36
-rw-r--r--tests/acceptance/features/core/ActorAwareInterface.php29
-rw-r--r--tests/acceptance/features/core/ActorContext.php194
-rw-r--r--tests/acceptance/features/core/ElementFinder.php203
-rw-r--r--tests/acceptance/features/core/ElementWrapper.php358
-rw-r--r--tests/acceptance/features/core/Locator.php313
-rw-r--r--tests/acceptance/features/core/NextcloudTestServerContext.php126
-rw-r--r--tests/acceptance/features/core/NextcloudTestServerHelper.php71
-rw-r--r--tests/acceptance/features/core/NextcloudTestServerLocalApacheHelper.php128
-rw-r--r--tests/acceptance/features/core/NextcloudTestServerLocalBuiltInHelper.php142
-rw-r--r--tests/acceptance/features/core/NoSuchElementException.php35
-rw-r--r--tests/acceptance/features/core/Utils.php88
13 files changed, 0 insertions, 1937 deletions
diff --git a/tests/acceptance/features/core/Actor.php b/tests/acceptance/features/core/Actor.php
deleted file mode 100644
index abe9a390920..00000000000
--- a/tests/acceptance/features/core/Actor.php
+++ /dev/null
@@ -1,214 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/**
- * An actor in a test scenario.
- *
- * Every Actor object is intended to be used only in a single test scenario.
- * An Actor can control its web browser thanks to the Mink Session received when
- * it was created, so in each scenario each Actor must have its own Mink
- * Session; the same Mink Session can be used by different Actors in different
- * scenarios, but never by different Actors in the same scenario.
- *
- * The test servers used in an scenario can change between different test runs,
- * so an Actor stores the base URL for the current test server being used; in
- * most cases the tests are specified using relative paths that can be converted
- * to the appropriate absolute URL using locatePath() in the step
- * implementation.
- *
- * An Actor can find elements in its Mink Session using its find() method; it is
- * a wrapper over the find() method provided by Mink that extends it with
- * several features: the element can be looked for based on a Locator object, an
- * exception is thrown if the element is not found, and, optionally, it is
- * possible to try again to find the element several times before giving up.
- *
- * The returned object is also a wrapper over the element itself that
- * automatically handles common causes of failed commands, like clicking on a
- * hidden element; in this case, the wrapper would wait for the element to be
- * visible up to the timeout set to find the element.
- *
- * The amount of time to wait before giving up is specified in each call to
- * find(). However, a general multiplier to be applied to every timeout can be
- * set using setFindTimeoutMultiplier(); this makes possible to retry longer
- * before giving up without modifying the tests themselves. Note that the
- * multiplier affects the timeout, but not the timeout step; the rate at which
- * find() will try again to find the element does not change.
- *
- * All actors share a notebook in which data can be annotated. This makes
- * possible to share data between different test steps, no matter which Actor
- * performs them.
- */
-class Actor {
- /**
- * @var string
- */
- private $name;
-
- /**
- * @var \Behat\Mink\Session
- */
- private $session;
-
- /**
- * @var string
- */
- private $baseUrl;
-
- /**
- * @var float
- */
- private $findTimeoutMultiplier;
-
- /**
- * @var array
- */
- private $sharedNotebook;
-
- /**
- * Creates a new Actor.
- *
- * @param string $name the name of the actor.
- * @param \Behat\Mink\Session $session the Mink Session used to control its
- * web browser.
- * @param string $baseUrl the base URL used when solving relative URLs.
- * @param array $sharedNotebook the notebook shared between all actors.
- */
- public function __construct($name, \Behat\Mink\Session $session, $baseUrl, &$sharedNotebook) {
- $this->name = $name;
- $this->session = $session;
- $this->baseUrl = $baseUrl;
- $this->sharedNotebook = &$sharedNotebook;
- $this->findTimeoutMultiplier = 1;
- }
-
- /**
- * Returns the name of this Actor.
- *
- * @return string the name of this Actor.
- */
- public function getName() {
- return $this->name;
- }
-
- /**
- * Sets the base URL.
- *
- * @param string $baseUrl the base URL used when solving relative URLs.
- */
- public function setBaseUrl($baseUrl) {
- $this->baseUrl = $baseUrl;
- }
-
- /**
- * Returns the multiplier for find timeouts.
- *
- * @return float the multiplier to apply to find timeouts.
- */
- public function getFindTimeoutMultiplier() {
- return $this->findTimeoutMultiplier;
- }
-
- /**
- * Sets the multiplier for find timeouts.
- *
- * @param float $findTimeoutMultiplier the multiplier to apply to find
- * timeouts.
- */
- public function setFindTimeoutMultiplier($findTimeoutMultiplier) {
- $this->findTimeoutMultiplier = $findTimeoutMultiplier;
- }
-
- /**
- * Returns the Mink Session used to control its web browser.
- *
- * @return \Behat\Mink\Session the Mink Session used to control its web
- * browser.
- */
- public function getSession() {
- return $this->session;
- }
-
- /**
- * Returns the full path for the given relative path based on the base URL.
- *
- * @param string relativePath the relative path.
- * @return string the full path.
- */
- public function locatePath($relativePath) {
- return $this->baseUrl . $relativePath;
- }
-
- /**
- * Finds an element in the Mink Session of this Actor.
- *
- * The given element locator is relative to its ancestor (either another
- * locator or an actual element); if it has no ancestor then the base
- * document element is used.
- *
- * Sometimes an element may not be found simply because it has not appeared
- * yet; for those cases this method supports trying again to find the
- * element several times before giving up. The timeout parameter controls
- * how much time to wait, at most, to find the element; the timeoutStep
- * parameter controls how much time to wait before trying again to find the
- * element. If ancestor locators need to be found the timeout is applied
- * individually to each one, that is, if the timeout is 10 seconds the
- * method will wait up to 10 seconds to find the ancestor of the ancestor
- * and, then, up to 10 seconds to find the ancestor and, then, up to 10
- * seconds to find the element. By default the timeout is 0, so the element
- * and its ancestor will be looked for just once; the default time to wait
- * before retrying is half a second. If the timeout is not 0 it will be
- * affected by the multiplier set using setFindTimeoutMultiplier(), if any.
- *
- * When found, the element is returned wrapped in an ElementWrapper; the
- * ElementWrapper handles common causes of failures when executing commands
- * in an element, like clicking on a hidden element.
- *
- * In any case, if the element, or its ancestors, can not be found a
- * NoSuchElementException is thrown.
- *
- * @param Locator $elementLocator the locator for the element.
- * @param float $timeout the number of seconds (decimals allowed) to wait at
- * most for the element to appear.
- * @param float $timeoutStep the number of seconds (decimals allowed) to
- * wait before trying to find the element again.
- * @return ElementWrapper an ElementWrapper object for the element.
- * @throws NoSuchElementException if the element, or its ancestor, can not
- * be found.
- */
- public function find(Locator $elementLocator, $timeout = 0, $timeoutStep = 0.5) {
- $timeout = $timeout * $this->findTimeoutMultiplier;
-
- $elementFinder = new ElementFinder($this->session, $elementLocator, $timeout, $timeoutStep);
-
- return new ElementWrapper($elementFinder);
- }
-
- /**
- * Returns the shared notebook of the Actors.
- *
- * @return array the shared notebook of the Actors.
- */
- public function &getSharedNotebook() {
- return $this->sharedNotebook;
- }
-}
diff --git a/tests/acceptance/features/core/ActorAware.php b/tests/acceptance/features/core/ActorAware.php
deleted file mode 100644
index c734d7e1906..00000000000
--- a/tests/acceptance/features/core/ActorAware.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-trait ActorAware {
- /**
- * @var Actor
- */
- protected $actor;
-
- /**
- * @param Actor $actor
- */
- public function setCurrentActor(Actor $actor) {
- $this->actor = $actor;
- }
-}
diff --git a/tests/acceptance/features/core/ActorAwareInterface.php b/tests/acceptance/features/core/ActorAwareInterface.php
deleted file mode 100644
index 7b855aed4d3..00000000000
--- a/tests/acceptance/features/core/ActorAwareInterface.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-interface ActorAwareInterface {
- /**
- * @param Actor $actor
- */
- public function setCurrentActor(Actor $actor);
-}
diff --git a/tests/acceptance/features/core/ActorContext.php b/tests/acceptance/features/core/ActorContext.php
deleted file mode 100644
index 7f152a1f3eb..00000000000
--- a/tests/acceptance/features/core/ActorContext.php
+++ /dev/null
@@ -1,194 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-use Behat\Behat\Hook\Scope\BeforeStepScope;
-use Behat\MinkExtension\Context\RawMinkContext;
-
-/**
- * Behat context to set the actor used in sibling contexts.
- *
- * This helper context provides a step definition ("I act as XXX") to change the
- * current actor of the scenario, which makes possible to use different browser
- * sessions in the same scenario.
- *
- * Sibling contexts that want to have access to the current actor of the
- * scenario must implement the ActorAwareInterface; this can be done just by
- * using the ActorAware trait.
- *
- * Besides updating the current actor in sibling contexts the ActorContext also
- * propagates its inherited "base_url" Mink parameter to the Actors as needed.
- *
- * By default no multiplier for the find timeout is set in the Actors. However,
- * it can be customized using the "actorTimeoutMultiplier" parameter of the
- * ActorContext in "behat.yml". This parameter also affects the overall timeout
- * to start a session for an Actor before giving up.
- *
- * Every actor used in the scenarios must have a corresponding Mink session
- * declared in "behat.yml" with the same name as the actor. All used sessions
- * are stopped after each scenario is run.
- */
-class ActorContext extends RawMinkContext {
- /**
- * @var array
- */
- private $actors;
-
- /**
- * @var array
- */
- private $sharedNotebook;
-
- /**
- * @var Actor
- */
- private $currentActor;
-
- /**
- * @var float
- */
- private $actorTimeoutMultiplier;
-
- /**
- * Creates a new ActorContext.
- *
- * @param float $actorTimeoutMultiplier the timeout multiplier for Actor
- * related timeouts.
- */
- public function __construct($actorTimeoutMultiplier = 1) {
- $this->actorTimeoutMultiplier = $actorTimeoutMultiplier;
- }
-
- /**
- * Sets a Mink parameter.
- *
- * When the "base_url" parameter is set its value is propagated to all the
- * Actors.
- *
- * @param string $name the name of the parameter.
- * @param string $value the value of the parameter.
- */
- public function setMinkParameter($name, $value) {
- parent::setMinkParameter($name, $value);
-
- if ($name === "base_url") {
- foreach ($this->actors as $actor) {
- $actor->setBaseUrl($value);
- }
- }
- }
-
- /**
- * Returns the session with the given name.
- *
- * If the session is not started it is started before returning it; if the
- * session fails to start (typically due to a timeout connecting with the
- * web browser) it will be tried again up to $actorTimeoutMultiplier times
- * in total (rounded up to the next integer) before giving up.
- *
- * @param string|null $sname the name of the session to get, or null for the
- * default session.
- * @return \Behat\Mink\Session the session.
- */
- public function getSession($name = null) {
- for ($i = 0; $i < ($this->actorTimeoutMultiplier - 1); $i++) {
- try {
- return parent::getSession($name);
- } catch (\Behat\Mink\Exception\DriverException $exception) {
- echo "Exception when getting " . ($name == null? "default session": "session '$name'") . ": " . $exception->getMessage() . "\n";
- echo "Trying again\n";
- }
- }
-
- return parent::getSession($name);
- }
-
- /**
- * @BeforeScenario
- *
- * Initializes the Actors for the new Scenario with the default Actor.
- *
- * Other Actors are added (and their Mink Sessions started) only when they
- * are used in an "I act as XXX" step.
- */
- public function initializeActors() {
- $this->actors = [];
- $this->sharedNotebook = [];
-
- $this->getSession()->start();
-
- $this->getSession()->maximizeWindow();
-
- $this->actors["default"] = new Actor("default", $this->getSession(), $this->getMinkParameter("base_url"), $this->sharedNotebook);
- $this->actors["default"]->setFindTimeoutMultiplier($this->actorTimeoutMultiplier);
-
- $this->currentActor = $this->actors["default"];
- }
-
- /**
- * @BeforeStep
- */
- public function setCurrentActorInSiblingActorAwareContexts(BeforeStepScope $scope) {
- $environment = $scope->getEnvironment();
-
- foreach ($environment->getContexts() as $context) {
- if ($context instanceof ActorAwareInterface) {
- $context->setCurrentActor($this->currentActor);
- }
- }
- }
-
- /**
- * @Given I act as :actorName
- */
- public function iActAs($actorName) {
- if (!array_key_exists($actorName, $this->actors)) {
- $this->getSession($actorName)->start();
-
- $this->getSession($actorName)->maximizeWindow();
-
- $this->actors[$actorName] = new Actor($actorName, $this->getSession($actorName), $this->getMinkParameter("base_url"), $this->sharedNotebook);
- $this->actors[$actorName]->setFindTimeoutMultiplier($this->actorTimeoutMultiplier);
- }
-
- $this->currentActor = $this->actors[$actorName];
-
- // Ensure that the browser window of the actor is the one in the
- // foreground; this works around a bug in the Firefox driver of Selenium
- // and/or maybe in Firefox itself when interacting with a window in the
- // background, but also reflects better how the user would interact with
- // the browser in real life.
- $session = $this->actors[$actorName]->getSession();
- $session->switchToWindow($session->getWindowName());
- }
-
- /**
- * @AfterScenario
- *
- * Stops all the Mink Sessions used in the last Scenario.
- */
- public function cleanUpSessions() {
- foreach ($this->actors as $actor) {
- $actor->getSession()->stop();
- }
- }
-}
diff --git a/tests/acceptance/features/core/ElementFinder.php b/tests/acceptance/features/core/ElementFinder.php
deleted file mode 100644
index 714b100bfa2..00000000000
--- a/tests/acceptance/features/core/ElementFinder.php
+++ /dev/null
@@ -1,203 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/**
- * Command object to find Mink elements.
- *
- * The element locator is relative to its ancestor (either another locator or an
- * actual element); if it has no ancestor then the base document element is
- * used.
- *
- * Sometimes an element may not be found simply because it has not appeared yet;
- * for those cases ElementFinder supports trying again to find the element
- * several times before giving up. The timeout parameter controls how much time
- * to wait, at most, to find the element; the timeoutStep parameter controls how
- * much time to wait before trying again to find the element. If ancestor
- * locators need to be found the timeout is applied individually to each one,
- * that is, if the timeout is 10 seconds the method will wait up to 10 seconds
- * to find the ancestor of the ancestor and, then, up to 10 seconds to find the
- * ancestor and, then, up to 10 seconds to find the element. By default the
- * timeout is 0, so the element and its ancestor will be looked for just once;
- * the default time to wait before retrying is half a second.
- *
- * In any case, if the element, or its ancestors, can not be found a
- * NoSuchElementException is thrown.
- */
-class ElementFinder {
- /**
- * Finds an element in the given Mink Session.
- *
- * @see ElementFinder
- */
- private static function findInternal(\Behat\Mink\Session $session, Locator $elementLocator, $timeout, $timeoutStep) {
- $element = null;
- $selector = $elementLocator->getSelector();
- $locator = $elementLocator->getLocator();
- $ancestorElement = self::findAncestorElement($session, $elementLocator, $timeout, $timeoutStep);
-
- $findCallback = function () use (&$element, $selector, $locator, $ancestorElement) {
- $element = $ancestorElement->find($selector, $locator);
-
- return $element !== null;
- };
- if (!Utils::waitFor($findCallback, $timeout, $timeoutStep)) {
- $message = $elementLocator->getDescription() . " could not be found";
- if ($timeout > 0) {
- $message = $message . " after $timeout seconds";
- }
- throw new NoSuchElementException($message);
- }
-
- return $element;
- }
-
- /**
- * Returns the ancestor element from which the given locator will be looked
- * for.
- *
- * If the ancestor of the given locator is another locator the element for
- * the ancestor locator is found and returned. If the ancestor of the given
- * locator is already an element that element is the one returned. If the
- * given locator has no ancestor then the base document element is returned.
- *
- * The timeout is used only when finding the element for the ancestor
- * locator; if the timeout expires a NoSuchElementException is thrown.
- *
- * @param \Behat\Mink\Session $session the Mink Session to get the ancestor
- * element from.
- * @param Locator $elementLocator the locator for the element to get its
- * ancestor.
- * @param float $timeout the number of seconds (decimals allowed) to wait at
- * most for the ancestor element to appear.
- * @param float $timeoutStep the number of seconds (decimals allowed) to
- * wait before trying to find the ancestor element again.
- * @return \Behat\Mink\Element\Element the ancestor element found.
- * @throws NoSuchElementException if the ancestor element can not be found.
- */
- private static function findAncestorElement(\Behat\Mink\Session $session, Locator $elementLocator, $timeout, $timeoutStep) {
- $ancestorElement = $elementLocator->getAncestor();
- if ($ancestorElement instanceof Locator) {
- try {
- $ancestorElement = self::findInternal($session, $ancestorElement, $timeout, $timeoutStep);
- } catch (NoSuchElementException $exception) {
- // Little hack to show the stack of ancestor elements that could
- // not be found, as Behat only shows the message of the last
- // exception in the chain.
- $message = $exception->getMessage() . "\n" .
- $elementLocator->getDescription() . " could not be found";
- if ($timeout > 0) {
- $message = $message . " after $timeout seconds";
- }
- throw new NoSuchElementException($message, $exception);
- }
- }
-
- if ($ancestorElement === null) {
- $ancestorElement = $session->getPage();
- }
-
- return $ancestorElement;
- }
-
- /**
- * @var \Behat\Mink\Session
- */
- private $session;
-
- /**
- * @param Locator
- */
- private $elementLocator;
-
- /**
- * @var float
- */
- private $timeout;
-
- /**
- * @var float
- */
- private $timeoutStep;
-
- /**
- * Creates a new ElementFinder.
- *
- * @param \Behat\Mink\Session $session the Mink Session to get the element
- * from.
- * @param Locator $elementLocator the locator for the element.
- * @param float $timeout the number of seconds (decimals allowed) to wait at
- * most for the element to appear.
- * @param float $timeoutStep the number of seconds (decimals allowed) to
- * wait before trying to find the element again.
- */
- public function __construct(\Behat\Mink\Session $session, Locator $elementLocator, $timeout, $timeoutStep) {
- $this->session = $session;
- $this->elementLocator = $elementLocator;
- $this->timeout = $timeout;
- $this->timeoutStep = $timeoutStep;
- }
-
- /**
- * Returns the description of the element to find.
- *
- * @return string the description of the element to find.
- */
- public function getDescription() {
- return $this->elementLocator->getDescription();
- }
-
- /**
- * Returns the timeout.
- *
- * @return float the number of seconds (decimals allowed) to wait at most
- * for the element to appear.
- */
- public function getTimeout() {
- return $this->timeout;
- }
-
- /**
- * Returns the timeout step.
- *
- * @return float the number of seconds (decimals allowed) to wait before
- * trying to find the element again.
- */
- public function getTimeoutStep() {
- return $this->timeoutStep;
- }
-
- /**
- * Finds an element using the parameters set in the constructor of this
- * ElementFinder.
- *
- * If the element, or its ancestors, can not be found a
- * NoSuchElementException is thrown.
- *
- * @return \Behat\Mink\Element\Element the element found.
- * @throws NoSuchElementException if the element, or its ancestor, can not
- * be found.
- */
- public function find() {
- return self::findInternal($this->session, $this->elementLocator, $this->timeout, $this->timeoutStep);
- }
-}
diff --git a/tests/acceptance/features/core/ElementWrapper.php b/tests/acceptance/features/core/ElementWrapper.php
deleted file mode 100644
index 6ac9a6b8e8f..00000000000
--- a/tests/acceptance/features/core/ElementWrapper.php
+++ /dev/null
@@ -1,358 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/**
- * Wrapper to automatically handle failed commands on Mink elements.
- *
- * Commands executed on Mink elements may fail for several reasons. The
- * ElementWrapper frees the caller of the commands from handling the most common
- * reasons of failure.
- *
- * StaleElementReference exceptions are thrown when the command is executed on
- * an element that is no longer attached to the DOM. This can happen even in
- * a chained call like "$actor->find($locator)->click()"; in the milliseconds
- * between finding the element and clicking it the element could have been
- * removed from the page (for example, if a previous interaction with the page
- * started an asynchronous update of the DOM). Every command executed through
- * the ElementWrapper is guarded against StaleElementReference exceptions; if
- * the element is stale it is found again using the same parameters to find it
- * in the first place.
- *
- * NoSuchElement exceptions are sometimes thrown instead of
- * StaleElementReference exceptions. This can happen when the Selenium2 driver
- * for Mink performs an action on an element through the WebDriver session
- * instead of directly through the WebDriver element. In that case, if the
- * element with the given ID does not exist, a NoSuchElement exception would be
- * thrown instead of a StaleElementReference exception, so those cases are
- * handled like StaleElementReference exceptions.
- *
- * ElementNotVisible exceptions are thrown when the command requires the element
- * to be visible but the element is not. Finding an element only guarantees that
- * (at that time) the element is attached to the DOM, but it does not provide
- * any guarantee regarding its visibility. Due to that, a call like
- * "$actor->find($locator)->click()" can fail if the element was hidden and
- * meant to be made visible by a previous interaction with the page, but that
- * interaction triggered an asynchronous update that was not finished when the
- * click command is executed. All commands executed through the ElementWrapper
- * that require the element to be visible are guarded against ElementNotVisible
- * exceptions; if the element is not visible it is waited for it to be visible
- * up to the timeout set to find it.
- *
- * MoveTargetOutOfBounds exceptions are sometimes thrown instead of
- * ElementNotVisible exceptions. This can happen when the Selenium2 driver for
- * Mink moves the cursor on an element using the "moveto" method of the
- * WebDriver session, for example, before clicking on an element. In that case,
- * if the element is not visible, "moveto" would throw a MoveTargetOutOfBounds
- * exception instead of an ElementNotVisible exception, so those cases are
- * handled like ElementNotVisible exceptions.
- *
- * ElementNotInteractable exceptions are thrown in Selenium 3 when the command
- * needs to interact with an element but that is not possible. This could be a
- * transitive situation (for example, due to an animation), so the command is
- * executed again after a small timeout.
- *
- * Despite the automatic handling it is possible for the commands to throw those
- * exceptions when they are executed again; this class does not handle cases
- * like an element becoming stale several times in a row (uncommon) or an
- * element not becoming visible before the timeout expires (which would mean
- * that the timeout is too short or that the test has to, indeed, fail). In a
- * similar way, MoveTargetOutOfBounds exceptions would be thrown again if
- * originally they were thrown because the element was visible but "out of
- * reach". ElementNotInteractable exceptions would be thrown again if it is not
- * possible to interact yet with the element after the wait (which could mean
- * that the test has to, indeed, fail, although it could mean too that the
- * automatic handling needs to be improved).
- *
- * If needed, automatically handling failed commands can be disabled calling
- * "doNotHandleFailedCommands()"; as it returns the ElementWrapper it can be
- * chained with the command to execute (but note that automatically handling
- * failed commands will still be disabled if further commands are executed on
- * the ElementWrapper).
- */
-class ElementWrapper {
- /**
- * @var ElementFinder
- */
- private $elementFinder;
-
- /**
- * @var \Behat\Mink\Element\Element
- */
- private $element;
-
- /**
- * @param boolean
- */
- private $handleFailedCommands;
-
- /**
- * Creates a new ElementWrapper.
- *
- * The wrapped element is found in the constructor itself using the
- * ElementFinder.
- *
- * @param ElementFinder $elementFinder the command object to find the
- * wrapped element.
- * @throws NoSuchElementException if the element, or its ancestor, can not
- * be found.
- */
- public function __construct(ElementFinder $elementFinder) {
- $this->elementFinder = $elementFinder;
- $this->element = $elementFinder->find();
- $this->handleFailedCommands = true;
- }
-
- /**
- * Returns the raw Mink element.
- *
- * @return \Behat\Mink\Element\Element the wrapped element.
- */
- public function getWrappedElement() {
- return $this->element;
- }
-
- /**
- * Prevents the automatic handling of failed commands.
- *
- * @return ElementWrapper this ElementWrapper.
- */
- public function doNotHandleFailedCommands() {
- $this->handleFailedCommands = false;
-
- return $this;
- }
-
- /**
- * Returns whether the wrapped element is visible or not.
- *
- * @return bool true if the wrapped element is visible, false otherwise.
- */
- public function isVisible() {
- $commandCallback = function () {
- return $this->element->isVisible();
- };
- return $this->executeCommand($commandCallback, "visibility could not be got");
- }
-
- /**
- * Returns whether the wrapped element is checked or not.
- *
- * @return bool true if the wrapped element is checked, false otherwise.
- */
- public function isChecked() {
- $commandCallback = function () {
- return $this->element->isChecked();
- };
- return $this->executeCommand($commandCallback, "check state could not be got");
- }
-
- /**
- * Returns the text of the wrapped element.
- *
- * If the wrapped element is not visible the returned text is an empty
- * string.
- *
- * @return string the text of the wrapped element, or an empty string if it
- * is not visible.
- */
- public function getText() {
- $commandCallback = function () {
- return $this->element->getText();
- };
- return $this->executeCommand($commandCallback, "text could not be got");
- }
-
- /**
- * Returns the value of the wrapped element.
- *
- * The value can be got even if the wrapped element is not visible.
- *
- * @return string the value of the wrapped element.
- */
- public function getValue() {
- $commandCallback = function () {
- return $this->element->getValue();
- };
- return $this->executeCommand($commandCallback, "value could not be got");
- }
-
- /**
- * Sets the given value on the wrapped element.
- *
- * If automatically waits for the wrapped element to be visible (up to the
- * timeout set when finding it).
- *
- * @param string $value the value to set.
- */
- public function setValue($value) {
- $commandCallback = function () use ($value) {
- $this->element->setValue($value);
- };
- $this->executeCommandOnVisibleElement($commandCallback, "value could not be set");
- }
-
- /**
- * Clicks on the wrapped element.
- *
- * If automatically waits for the wrapped element to be visible (up to the
- * timeout set when finding it).
- */
- public function click() {
- $commandCallback = function () {
- $this->element->click();
- };
- $this->executeCommandOnVisibleElement($commandCallback, "could not be clicked");
- }
-
- /**
- * Check the wrapped element.
- *
- * If automatically waits for the wrapped element to be visible (up to the
- * timeout set when finding it).
- */
- public function check() {
- $commandCallback = function () {
- $this->element->check();
- };
- $this->executeCommand($commandCallback, "could not be checked");
- }
-
- /**
- * uncheck the wrapped element.
- *
- * If automatically waits for the wrapped element to be visible (up to the
- * timeout set when finding it).
- */
- public function uncheck() {
- $commandCallback = function () {
- $this->element->uncheck();
- };
- $this->executeCommand($commandCallback, "could not be unchecked");
- }
-
- /**
- * Executes the given command.
- *
- * If a StaleElementReference or a NoSuchElement exception is thrown the
- * wrapped element is found again and, then, the command is executed again.
- *
- * @param \Closure $commandCallback the command to execute.
- * @param string $errorMessage an error message that describes the failed
- * command (appended to the description of the element).
- */
- private function executeCommand(\Closure $commandCallback, $errorMessage) {
- if (!$this->handleFailedCommands) {
- return $commandCallback();
- }
-
- try {
- return $commandCallback();
- } catch (\WebDriver\Exception\StaleElementReference $exception) {
- $this->printFailedCommandMessage($exception, $errorMessage);
- } catch (\WebDriver\Exception\NoSuchElement $exception) {
- $this->printFailedCommandMessage($exception, $errorMessage);
- }
-
- $this->element = $this->elementFinder->find();
-
- return $commandCallback();
- }
-
- /**
- * Executes the given command on a visible element.
- *
- * If a StaleElementReference or a NoSuchElement exception is thrown the
- * wrapped element is found again and, then, the command is executed again.
- * If an ElementNotVisible or a MoveTargetOutOfBounds exception is thrown it
- * is waited for the wrapped element to be visible and, then, the command is
- * executed again.
- * If an ElementNotInteractable exception is thrown it is also waited for
- * the wrapped element to be visible. It is very likely that the element was
- * visible already, but it is not possible to easily check if the element
- * can be interacted with, retrying will be only useful if it was a
- * transitive situation that resolves itself with a wait (for example, due
- * to an animation) and waiting for the element to be visible will always
- * start with a wait.
- *
- * @param \Closure $commandCallback the command to execute.
- * @param string $errorMessage an error message that describes the failed
- * command (appended to the description of the element).
- */
- private function executeCommandOnVisibleElement(\Closure $commandCallback, $errorMessage) {
- if (!$this->handleFailedCommands) {
- return $commandCallback();
- }
-
- try {
- return $this->executeCommand($commandCallback, $errorMessage);
- } catch (\WebDriver\Exception\ElementNotVisible $exception) {
- $this->printFailedCommandMessage($exception, $errorMessage);
- } catch (\WebDriver\Exception\MoveTargetOutOfBounds $exception) {
- $this->printFailedCommandMessage($exception, $errorMessage);
- } catch (\Exception $exception) {
- // The "ElementNotInteractable" exception is not available yet in
- // the current "instaclick/php-webdriver" version, so it is thrown
- // as a generic exception with a specific message.
- if (stripos($exception->getMessage(), "element not interactable") === false) {
- throw $exception;
- }
- $this->printFailedCommandMessage($exception, $errorMessage);
- }
-
- $this->waitForElementToBeVisible();
-
- return $commandCallback();
- }
-
- /**
- * Prints information about the failed command.
- *
- * @param \Exception exception the exception thrown by the command.
- * @param string $errorMessage an error message that describes the failed
- * command (appended to the description of the locator of the element).
- */
- private function printFailedCommandMessage(\Exception $exception, $errorMessage) {
- echo $this->elementFinder->getDescription() . " " . $errorMessage . "\n";
- echo "Exception message: " . $exception->getMessage() . "\n";
- echo "Trying again\n";
- }
-
- /**
- * Waits for the wrapped element to be visible.
- *
- * This method waits up to the timeout used when finding the wrapped
- * element; therefore, it may return when the element is still not visible.
- *
- * @return boolean true if the element is visible after the wait, false
- * otherwise.
- */
- private function waitForElementToBeVisible() {
- $isVisibleCallback = function () {
- return $this->isVisible();
- };
- $timeout = $this->elementFinder->getTimeout();
- $timeoutStep = $this->elementFinder->getTimeoutStep();
-
- return Utils::waitFor($isVisibleCallback, $timeout, $timeoutStep);
- }
-}
diff --git a/tests/acceptance/features/core/Locator.php b/tests/acceptance/features/core/Locator.php
deleted file mode 100644
index 1b933399e6b..00000000000
--- a/tests/acceptance/features/core/Locator.php
+++ /dev/null
@@ -1,313 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/**
- * Data object for the information needed to locate an element in a web page
- * using Mink.
- *
- * Locators can be created directly using the constructor, or through a more
- * fluent interface with Locator::forThe().
- */
-class Locator {
- /**
- * @var string
- */
- private $description;
-
- /**
- * @var string
- */
- private $selector;
-
- /**
- * @var string|array
- */
- private $locator;
-
- /**
- * @var null|Locator|\Behat\Mink\Element\ElementInterface
- */
- private $ancestor;
-
- /**
- * Starting point for the fluent interface to create Locators.
- *
- * @return LocatorBuilder
- */
- public static function forThe() {
- return new LocatorBuilder();
- }
-
- /**
- * @param string $description
- * @param string $selector
- * @param string|array $locator
- * @param null|Locator|\Behat\Mink\Element\ElementInterface $ancestor
- */
- public function __construct($description, $selector, $locator, $ancestor = null) {
- $this->description = $description;
- $this->selector = $selector;
- $this->locator = $locator;
- $this->ancestor = $ancestor;
- }
-
- /**
- * @return string
- */
- public function getDescription() {
- return $this->description;
- }
-
- /**
- * @return string
- */
- public function getSelector() {
- return $this->selector;
- }
-
- /**
- * @return string|array
- */
- public function getLocator() {
- return $this->locator;
- }
-
- /**
- * @return null|Locator|\Behat\Mink\Element\ElementInterface
- */
- public function getAncestor() {
- return $this->ancestor;
- }
-}
-
-class LocatorBuilder {
- /**
- * @param string $selector
- * @param string|array $locator
- * @return LocatorBuilderSecondStep
- */
- public function customSelector($selector, $locator) {
- return new LocatorBuilderSecondStep($selector, $locator);
- }
-
- /**
- * @param string $cssExpression
- * @return LocatorBuilderSecondStep
- */
- public function css($cssExpression) {
- return $this->customSelector("css", $cssExpression);
- }
-
- /**
- * @param string $xpathExpression
- * @return LocatorBuilderSecondStep
- */
- public function xpath($xpathExpression) {
- return $this->customSelector("xpath", $xpathExpression);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function id($value) {
- return $this->customSelector("named_exact", ["id", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function idOrName($value) {
- return $this->customSelector("named_exact", ["id_or_name", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function link($value) {
- return $this->customSelector("named_exact", ["link", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function button($value) {
- return $this->customSelector("named_exact", ["button", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function linkOrButton($value) {
- return $this->customSelector("named_exact", ["link_or_button", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function field($value) {
- return $this->customSelector("named_exact", ["field", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function selectField($value) {
- return $this->customSelector("named_exact", ["select", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function checkbox($value) {
- return $this->customSelector("named_exact", ["checkbox", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function radioButton($value) {
- return $this->customSelector("named_exact", ["radio", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function fileInput($value) {
- return $this->customSelector("named_exact", ["file", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function optionGroup($value) {
- return $this->customSelector("named_exact", ["optgroup", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function option($value) {
- return $this->customSelector("named_exact", ["option", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function fieldSet($value) {
- return $this->customSelector("named_exact", ["fieldset", $value]);
- }
-
- /**
- * @param string $value
- * @return LocatorBuilderSecondStep
- */
- public function table($value) {
- return $this->customSelector("named_exact", ["table", $value]);
- }
-}
-
-class LocatorBuilderSecondStep {
- /**
- * @var string
- */
- private $selector;
-
- /**
- * @var string|array
- */
- private $locator;
-
- /**
- * @param string $selector
- * @param string|array $locator
- */
- public function __construct($selector, $locator) {
- $this->selector = $selector;
- $this->locator = $locator;
- }
-
- /**
- * @param Locator|\Behat\Mink\Element\ElementInterface $ancestor
- * @return LocatorBuilderThirdStep
- */
- public function descendantOf($ancestor) {
- return new LocatorBuilderThirdStep($this->selector, $this->locator, $ancestor);
- }
-
- /**
- * @param string $description
- * @return Locator
- */
- public function describedAs($description) {
- return new Locator($description, $this->selector, $this->locator);
- }
-}
-
-class LocatorBuilderThirdStep {
- /**
- * @var string
- */
- private $selector;
-
- /**
- * @var string|array
- */
- private $locator;
-
- /**
- * @var Locator|\Behat\Mink\Element\ElementInterface
- */
- private $ancestor;
-
- /**
- * @param string $selector
- * @param string|array $locator
- * @param Locator|\Behat\Mink\Element\ElementInterface $ancestor
- */
- public function __construct($selector, $locator, $ancestor) {
- $this->selector = $selector;
- $this->locator = $locator;
- $this->ancestor = $ancestor;
- }
-
- /**
- * @param string $description
- * @return Locator
- */
- public function describedAs($description) {
- return new Locator($description, $this->selector, $this->locator, $this->ancestor);
- }
-}
diff --git a/tests/acceptance/features/core/NextcloudTestServerContext.php b/tests/acceptance/features/core/NextcloudTestServerContext.php
deleted file mode 100644
index d0dc0c32181..00000000000
--- a/tests/acceptance/features/core/NextcloudTestServerContext.php
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-use Behat\Behat\Context\Context;
-use Behat\Behat\Hook\Scope\BeforeScenarioScope;
-
-/**
- * Behat context to run each scenario against a clean Nextcloud server.
- *
- * Before each scenario is run, this context sets up a fresh Nextcloud server
- * with predefined data and configuration. Thanks to this every scenario is
- * independent from the others and they all know the initial state of the
- * server.
- *
- * This context is expected to be used along with RawMinkContext contexts (or
- * subclasses). As the server address can be different for each scenario, this
- * context automatically sets the "base_url" parameter of all its sibling
- * RawMinkContexts; just add NextcloudTestServerContext to the context list of a
- * suite in "behat.yml".
- *
- * The Nextcloud server is provided by an instance of NextcloudTestServerHelper;
- * its class must be specified when this context is created. By default,
- * "NextcloudTestServerLocalBuiltInHelper" is used, although that can be
- * customized using the "nextcloudTestServerHelper" parameter in "behat.yml". In
- * the same way, the parameters to be passed to the helper when it is created
- * can be customized using the "nextcloudTestServerHelperParameters" parameter,
- * which is an array (without keys) with the value of the parameters in the same
- * order as in the constructor of the helper class (by default, [ ]).
- *
- * Example of custom parameters in "behat.yml":
- * default:
- * suites:
- * default:
- * contexts:
- * - NextcloudTestServerContext:
- * nextcloudTestServerHelper: NextcloudTestServerCustomHelper
- * nextcloudTestServerHelperParameters:
- * - first-parameter-value
- * - second-parameter-value
- */
-class NextcloudTestServerContext implements Context {
- /**
- * @var NextcloudTestServerHelper
- */
- private $nextcloudTestServerHelper;
-
- /**
- * Creates a new NextcloudTestServerContext.
- *
- * @param string $nextcloudTestServerHelper the name of the
- * NextcloudTestServerHelper implementing class to use.
- * @param array $nextcloudTestServerHelperParameters the parameters for the
- * constructor of the $nextcloudTestServerHelper class.
- */
- public function __construct($nextcloudTestServerHelper = "NextcloudTestServerLocalBuiltInHelper",
- $nextcloudTestServerHelperParameters = [ ]) {
- $nextcloudTestServerHelperClass = new ReflectionClass($nextcloudTestServerHelper);
-
- if ($nextcloudTestServerHelperParameters === null) {
- $nextcloudTestServerHelperParameters = [];
- }
-
- $this->nextcloudTestServerHelper = $nextcloudTestServerHelperClass->newInstanceArgs($nextcloudTestServerHelperParameters);
- }
-
- /**
- * @BeforeScenario
- *
- * Sets up the Nextcloud test server before each scenario.
- *
- * Once the Nextcloud test server is set up, the "base_url" parameter of the
- * sibling RawMinkContexts is set to the base URL of the Nextcloud test
- * server.
- *
- * @param \Behat\Behat\Hook\Scope\BeforeScenarioScope $scope the
- * BeforeScenario hook scope.
- * @throws \Exception if the Nextcloud test server can not be set up or its
- * base URL got.
- */
- public function setUpNextcloudTestServer(BeforeScenarioScope $scope) {
- $this->nextcloudTestServerHelper->setUp();
-
- $this->setBaseUrlInSiblingRawMinkContexts($scope, $this->nextcloudTestServerHelper->getBaseUrl());
- }
-
- /**
- * @AfterScenario
- *
- * Cleans up the Nextcloud test server after each scenario.
- *
- * @throws \Exception if the Nextcloud test server can not be cleaned up.
- */
- public function cleanUpNextcloudTestServer() {
- $this->nextcloudTestServerHelper->cleanUp();
- }
-
- private function setBaseUrlInSiblingRawMinkContexts(BeforeScenarioScope $scope, $baseUrl) {
- $environment = $scope->getEnvironment();
-
- foreach ($environment->getContexts() as $context) {
- if ($context instanceof Behat\MinkExtension\Context\RawMinkContext) {
- $context->setMinkParameter("base_url", $baseUrl);
- }
- }
- }
-}
diff --git a/tests/acceptance/features/core/NextcloudTestServerHelper.php b/tests/acceptance/features/core/NextcloudTestServerHelper.php
deleted file mode 100644
index 69b8ce70505..00000000000
--- a/tests/acceptance/features/core/NextcloudTestServerHelper.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/**
- * Interface for classes that manage a Nextcloud server during acceptance tests.
- *
- * A NextcloudTestServerHelper takes care of setting up a Nextcloud server to be
- * used in acceptance tests through its "setUp" method. It does not matter
- * wheter the server is a fresh new server just started or an already running
- * server; in any case, the state of the server must comply with the initial
- * state expected by the tests (like having performed the Nextcloud installation
- * or having an admin user with certain password).
- *
- * As the IP address and thus its the base URL of the server is not known
- * beforehand, the NextcloudTestServerHelper must provide it through its
- * "getBaseUrl" method. Note that this must be the base URL from the point of
- * view of the Selenium server, which may be a different value than the base URL
- * from the point of view of the acceptance tests themselves.
- *
- * Once the Nextcloud test server is no longer needed the "cleanUp" method will
- * be called; depending on how the Nextcloud test server was set up it may not
- * need to do anything.
- *
- * All the methods throw an exception if they fail to execute; as, due to the
- * current use of this interface, it is just a warning for the test runner and
- * nothing to be explicitly catched a plain base Exception is used.
- */
-interface NextcloudTestServerHelper {
- /**
- * Sets up the Nextcloud test server.
- *
- * @throws \Exception if the Nextcloud test server can not be set up.
- */
- public function setUp();
-
- /**
- * Cleans up the Nextcloud test server.
- *
- * @throws \Exception if the Nextcloud test server can not be cleaned up.
- */
- public function cleanUp();
-
- /**
- * Returns the base URL of the Nextcloud test server (from the point of view
- * of the Selenium server).
- *
- * @return string the base URL of the Nextcloud test server.
- * @throws \Exception if the base URL can not be determined.
- */
- public function getBaseUrl();
-}
diff --git a/tests/acceptance/features/core/NextcloudTestServerLocalApacheHelper.php b/tests/acceptance/features/core/NextcloudTestServerLocalApacheHelper.php
deleted file mode 100644
index 367e950931d..00000000000
--- a/tests/acceptance/features/core/NextcloudTestServerLocalApacheHelper.php
+++ /dev/null
@@ -1,128 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2018, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/**
- * Helper to manage a Nextcloud test server started directly by the acceptance
- * tests themselves using the Apache web server.
- *
- * The Nextcloud test server is executed using the Apache web server; the
- * default Apache directory is expected to have been set to the root directory
- * of the Nextcloud server (for example, by linking "var/www/html" to it); in
- * any case, note that the acceptance tests must be run from the acceptance
- * tests directory. The "setUp" method resets the Nextcloud server to its
- * initial state and starts it, while the "cleanUp" method stops it. To be able
- * to reset the Nextcloud server to its initial state a Git repository must be
- * provided in the root directory of the Nextcloud server; the last commit in
- * that Git repository must provide the initial state for the Nextcloud server
- * expected by the acceptance tests. When the Nextcloud server is reset the
- * owner of "apps", "config" and "data" must be set to the user that Apache
- * server is run as; it is assumed that Apache is run as "www-data".
- *
- * The Nextcloud server is available at "$nextcloudServerDomain", which can be
- * optionally specified when the NextcloudTestServerLocalApacheHelper is
- * created; if no value is given "127.0.0.1" is used by default. In any case,
- * the value of "$nextcloudServerDomain" must be seen as a trusted domain by the
- * Nextcloud server (which would be the case for "127.0.0.1" if it was installed
- * by running "occ maintenance:install"). The base URL to access the Nextcloud
- * server can be got from "getBaseUrl".
- */
-class NextcloudTestServerLocalApacheHelper implements NextcloudTestServerHelper {
- /**
- * @var string
- */
- private $nextcloudServerDomain;
-
- /**
- * Creates a new NextcloudTestServerLocalApacheHelper.
- */
- public function __construct($nextcloudServerDomain = "127.0.0.1") {
- $this->nextcloudServerDomain = $nextcloudServerDomain;
- }
-
- /**
- * Sets up the Nextcloud test server.
- *
- * It resets the Nextcloud test server restoring its last saved Git state
- * and then waits for the Nextcloud test server to start again; if the
- * server can not be reset or if it does not start again after some time an
- * exception is thrown (as it is just a warning for the test runner and
- * nothing to be explicitly catched a plain base Exception is used).
- *
- * @throws \Exception if the Nextcloud test server can not be reset or
- * started again.
- */
- public function setUp(): void {
- // Ensure that previous Apache server is not running (as cleanUp may not
- // have been called).
- $this->stopApacheServer();
-
- $this->execOrException("cd ../../ && git reset --hard HEAD");
- $this->execOrException("cd ../../ && git clean -d --force");
- $this->execOrException("cd ../../ && chown -R www-data:www-data apps config data");
-
- $this->execOrException("service apache2 start");
-
- $timeout = 60;
- if (!Utils::waitForServer($this->getBaseUrl(), $timeout)) {
- throw new Exception("Nextcloud test server could not be started");
- }
- }
-
- /**
- * Cleans up the Nextcloud test server.
- *
- * It stops the running Nextcloud test server, if any.
- */
- public function cleanUp() {
- $this->stopApacheServer();
- }
-
- /**
- * Returns the base URL of the Nextcloud test server.
- *
- * @return string the base URL of the Nextcloud test server.
- */
- public function getBaseUrl() {
- return "http://" . $this->nextcloudServerDomain . "/index.php";
- }
-
- /**
- * Executes the given command, throwing an Exception if it fails.
- *
- * @param string $command the command to execute.
- * @throws \Exception if the command fails to execute.
- */
- private function execOrException($command) {
- exec($command . " 2>&1", $output, $returnValue);
- if ($returnValue != 0) {
- throw new Exception("'$command' could not be executed: " . implode("\n", $output));
- }
- }
-
- /**
- * Stops the Apache server started in setUp, if any.
- */
- private function stopApacheServer() {
- $this->execOrException("service apache2 stop");
- }
-}
diff --git a/tests/acceptance/features/core/NextcloudTestServerLocalBuiltInHelper.php b/tests/acceptance/features/core/NextcloudTestServerLocalBuiltInHelper.php
deleted file mode 100644
index a1ab1f8720a..00000000000
--- a/tests/acceptance/features/core/NextcloudTestServerLocalBuiltInHelper.php
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/**
- * Helper to manage a Nextcloud test server started directly by the acceptance
- * tests themselves using the PHP built-in web server.
- *
- * The Nextcloud test server is executed using the PHP built-in web server
- * directly from the grandparent directory of the acceptance tests directory
- * (that is, the root directory of the Nextcloud server); note that the
- * acceptance tests must be run from the acceptance tests directory. The "setUp"
- * method resets the Nextcloud server to its initial state and starts it, while
- * the "cleanUp" method stops it. To be able to reset the Nextcloud server to
- * its initial state a Git repository must be provided in the root directory of
- * the Nextcloud server; the last commit in that Git repository must provide the
- * initial state for the Nextcloud server expected by the acceptance tests.
- *
- * The Nextcloud server is available at "$nextcloudServerDomain", which can be
- * optionally specified when the NextcloudTestServerLocalBuiltInHelper is
- * created; if no value is given "127.0.0.1" is used by default. In any case,
- * the value of "$nextcloudServerDomain" must be seen as a trusted domain by the
- * Nextcloud server (which would be the case for "127.0.0.1" if it was installed
- * by running "occ maintenance:install"). The base URL to access the Nextcloud
- * server can be got from "getBaseUrl".
- */
-class NextcloudTestServerLocalBuiltInHelper implements NextcloudTestServerHelper {
- /**
- * @var string
- */
- private $nextcloudServerDomain;
-
- /**
- * @var string
- */
- private $phpServerPid;
-
- /**
- * Creates a new NextcloudTestServerLocalBuiltInHelper.
- */
- public function __construct($nextcloudServerDomain = "127.0.0.1") {
- $this->nextcloudServerDomain = $nextcloudServerDomain;
-
- $this->phpServerPid = "";
- }
-
- /**
- * Sets up the Nextcloud test server.
- *
- * It resets the Nextcloud test server restoring its last saved Git state
- * and then waits for the Nextcloud test server to start again; if the
- * server can not be reset or if it does not start again after some time an
- * exception is thrown (as it is just a warning for the test runner and
- * nothing to be explicitly catched a plain base Exception is used).
- *
- * @throws \Exception if the Nextcloud test server can not be reset or
- * started again.
- */
- public function setUp(): void {
- // Ensure that previous PHP server is not running (as cleanUp may not
- // have been called).
- $this->killPhpServer();
-
- $this->execOrException("cd ../../ && git reset --hard HEAD");
- $this->execOrException("cd ../../ && git clean -d --force");
-
- // execOrException is not used because the server is started in the
- // background, so the command will always succeed even if the server
- // itself fails.
- $this->phpServerPid = exec("php -S " . $this->nextcloudServerDomain . ":80 -t ../../ >/dev/null 2>&1 & echo $!");
-
- $timeout = 60;
- if (!Utils::waitForServer($this->getBaseUrl(), $timeout)) {
- throw new Exception("Nextcloud test server could not be started");
- }
- }
-
- /**
- * Cleans up the Nextcloud test server.
- *
- * It kills the running Nextcloud test server, if any.
- */
- public function cleanUp() {
- $this->killPhpServer();
- }
-
- /**
- * Returns the base URL of the Nextcloud test server.
- *
- * @return string the base URL of the Nextcloud test server.
- */
- public function getBaseUrl() {
- return "http://" . $this->nextcloudServerDomain . "/index.php";
- }
-
- /**
- * Executes the given command, throwing an Exception if it fails.
- *
- * @param string $command the command to execute.
- * @throws \Exception if the command fails to execute.
- */
- private function execOrException($command) {
- exec($command . " 2>&1", $output, $returnValue);
- if ($returnValue != 0) {
- throw new Exception("'$command' could not be executed: " . implode("\n", $output));
- }
- }
-
- /**
- * Kills the PHP built-in web server started in setUp, if any.
- */
- private function killPhpServer() {
- if ($this->phpServerPid == "") {
- return;
- }
-
- // execOrException is not used because the PID may no longer exist when
- // trying to kill it.
- exec("kill " . $this->phpServerPid);
-
- $this->phpServerPid = "";
- }
-}
diff --git a/tests/acceptance/features/core/NoSuchElementException.php b/tests/acceptance/features/core/NoSuchElementException.php
deleted file mode 100644
index 35583c7e63f..00000000000
--- a/tests/acceptance/features/core/NoSuchElementException.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/**
- * Exception to signal that the element looked for could not be found.
- */
-class NoSuchElementException extends \Exception {
- /**
- * @param string $message
- * @param null|\Exception $previous
- */
- public function __construct($message, \Exception $previous = null) {
- parent::__construct($message, 0, $previous);
- }
-}
diff --git a/tests/acceptance/features/core/Utils.php b/tests/acceptance/features/core/Utils.php
deleted file mode 100644
index eb7c65e993a..00000000000
--- a/tests/acceptance/features/core/Utils.php
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-class Utils {
- /**
- * Waits at most $timeout seconds for the given condition to be true,
- * checking it again every $timeoutStep seconds.
- *
- * Note that the timeout is no longer taken into account when a condition is
- * met; that is, true will be returned if the condition is met before the
- * timeout expires, but also if it is met exactly when the timeout expires.
- * For example, even if the timeout is set to 0, the condition will be
- * checked at least once, and true will be returned in that case if the
- * condition was met.
- *
- * @param \Closure $conditionCallback the condition to wait for, as a
- * function that returns a boolean.
- * @param float $timeout the number of seconds (decimals allowed) to wait at
- * most for the condition to be true.
- * @param float $timeoutStep the number of seconds (decimals allowed) to
- * wait before checking the condition again.
- * @return boolean true if the condition is met before (or exactly when) the
- * timeout expires, false otherwise.
- */
- public static function waitFor($conditionCallback, $timeout, $timeoutStep) {
- $elapsedTime = 0;
- $conditionMet = false;
-
- while (!($conditionMet = $conditionCallback()) && $elapsedTime < $timeout) {
- usleep($timeoutStep * 1000000);
-
- $elapsedTime += $timeoutStep;
- }
-
- return $conditionMet;
- }
-
- /**
- * Waits at most $timeout seconds for the server at the given URL to be up,
- * checking it again every $timeoutStep seconds.
- *
- * Note that it does not verify whether the URL returns a valid HTTP status
- * or not; it simply checks that the server at the given URL is accessible.
- *
- * @param string $url the URL for the server to check.
- * @param float $timeout the number of seconds (decimals allowed) to wait at
- * most for the server.
- * @param float $timeoutStep the number of seconds (decimals allowed) to
- * wait before checking the server again; by default, 0.5 seconds.
- * @return boolean true if the server was found, false otherwise.
- */
- public static function waitForServer($url, $timeout, $timeoutStep = 0.5) {
- $isServerUpCallback = function () use ($url) {
- $curlHandle = curl_init($url);
-
- // Returning the transfer as the result of curl_exec prevents the
- // transfer from being written to the output.
- curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
-
- $transfer = curl_exec($curlHandle);
-
- curl_close($curlHandle);
-
- return $transfer !== false;
- };
- return self::waitFor($isServerUpCallback, $timeout, $timeoutStep);
- }
-}