Move into nested docroot

This commit is contained in:
Rob Davies 2017-02-13 15:31:17 +00:00
parent 83a0d3a149
commit c8b70abde9
13405 changed files with 0 additions and 0 deletions

322
web/vendor/behat/mink/CHANGES.md vendored Normal file
View file

@ -0,0 +1,322 @@
1.7.1 / 2016-03-XX
==================
Bug fixes:
* Refactored the CssSelector to use the new API of the Symfony CssSelector component to be compatible with Symfony 3
Testsuite:
* Disallowed failures on PHP 7 on Travis (tests were passing since a long time)
Driver testsuite:
* Fixed the driver testsuite to account for driver inheritance when checking recommended practices
* Added a test for cookie values with semicolon, to ensure all drivers support it
* Improved the window resize test to consider headless browsers
* Fixed the compatibility of the testsuite with PHPUnit 5
* Added a test ensuring that `wait()` always return a boolean even when the JS expression does not cast the value
* Added HTML escaping of submitted values in the driver testsuite web-fixtures
Misc:
* Removed the Mink testsuite from archives generated by Github to make them smaller
1.7.0 / 2015-09-20
==================
New features:
* Added `Session::getResponseHeader` to access a response header easily
* Added support for header assertions
* Added a forward compatibility layer for drivers to allow them to prepare
for Mink 2.0 (they won't require any change if they use it). They should
now overwrite `CoreDriver::findElementXpaths` instead of implementing `find`
and `setSession` themselves.
* Added escaping of the locator in the NamedSelector rather than expecting
the caller to perform the escaping. Passing an escaped locator is still
supported but deprecated.
* Remove the dependency on the Session in expectation exceptions. Passing
the session in the exception constructor is now deprecated. The driver
should be passed instead.
Bug fixes:
* Fixed the URL assertions when comparing paths ending in ``.php``
* Silenced deprecation warnings (following the Symfony convention) to make
them less invasive. Use the `symfony/phpunit-bridge` to get them reported
when using Mink in your PHPUnit tests.
* Fixed `NodeElement::hasClass` in case the class attribute contains newlines
Testsuite:
* Made the testsuite compatible with PHPUnit strict timing mode (only the library testsuite, not the driver one)
* Added testing against PHP 7
* Added testing against lowest version of dependencies to ensure we got the lower bounds right
Driver testsuite:
* Added an extra test to ensure the right behavior when getting the HTML with empty elements
* Added a few more safeguards to ensure test failures rather than fatal errors for misbehaving drivers
* Added a test ensuring that drivers follow recommended practices
Misc:
* Added a few missing deprecation warnings for deprecated APIs or classes.
1.6.1 / 2015-02-04
==================
Bug fixes:
* Added a check for empty path in `WebAssert::cleanUrl()`
Driver testsuite:
* Added an extra test to ensure the right behavior for traversal
Misc:
* Changed the description in the composer.json
* Switched the repository structure to use PSR-4
* Updated URLs for the move to the new Github organization
1.6.0 / 2014-09-26
==================
* [BC break] Changed the named selector to prefer exact matches over partial matches
* [BC break] Changed `NodeElement::getValue` for checkboxes to return the value rather than the checked state (use `isChecked` for that)
* Fixed the XPath prefixing when searching inside an existing element
* Refactored the driver testsuite entirely and expand it to cover drivers entirely (covering many more cases for consistency)
* Changed `NodeElement::setValue` to support any fields rather than only input elements
* Removed the wrapping of any driver-level exception in a MinkException on invalid usage as it was making the code too complex
* Fixed the matching of the input type in the named selector to be case insensitive according to the HTML spec
* Introduced `Behat\Mink\Selector\Xpath\Escaper` to allow reusing the XPath escaping
* Deprecated `Element::getSession`. Code needing the session should get it from outside rather than the element
* Changed ElementNotFoundException to extend from ExpectationException
* Added `Element::getOuterHtml` to get the HTML code of the element including itself
* Fixed the name selectors to match on the `placeholder` only for textual inputs
* Enforced consistent behavior for drivers on 4xx and 5xx response to return the response rather than throwing an exception
* Added `Element::waitFor` to allow retrying some code until it succeeds or the timeout is reached
* Added `Element::isValid` to check whether an element still exists in the page
* Made `Session::executeScript` compatible across drivers by ensuring they all support the same syntaxes for the JS expression
* Made `Session::evaluateScript` compatible across drivers by ensuring they all support the same syntaxes for the JS expression
* Removed `hasClass` from `DocumentElement` (instead of triggering a fatal error)
* Added testing on HHVM to ensure consistency
* Fixed `NodeElement::getTagName` to ensure that the tag name is lowercase for all drivers
* Fixed `Element::hasAttribute` to ensure it supports attributes with an empty value
* Fixed the `field` selector to avoid matching inputs with the type `submit` or `reset`
* Changed the button XPath selection to accept `reset` buttons as well
* Changed `Session::wait` to return the condition value rather than nothing
* Added `Session::getWindowName` and `Session::getWindowNames` to get the name of the current and of all windows
* Added `Session::maximizeWindow` to maximize the window
* Added `NodeElement::isSelected` to check whether an `<option>` is selected
* Added `NodeElement::submitForm` to allow submitting a form without using a button
* Added assertions about the value of an attribute
* Added the anchor in the assertion on the URL in `WebAssert`
1.5.0 / 2013-04-14
==================
* Add `CoreDriver` to simplify future drivers improvements
* Add `Mink::isSessionStarted()` method
* Fix multibite string `preg_replace` bugs
* Fix handling of whitespaces in `WebAssert::pageText...()` methods
1.4.3 / 2013-03-02
==================
* Bump dependencies constraints
1.4.2 / 2013-02-13
==================
* Fix wrong test case to ensure that core drivers work as expected
1.4.1 / 2013-02-10
==================
* Update dependencies
* Add ElementException to element actions
* Rel attribute support for named selectors
* Add hasClass() helper to traversable elements
* Add getScreenshot() method to session
* Name attr support in named selector for button
* Fix for bunch of bugs
1.4.0 / 2012-05-40
==================
* New `Session::selectWindow()` and `Session::selectIFrame()` methods
* New built-in `WebAssert` class
* Fixed DocBlocks (autocompletion in any IDE now should just work)
* Moved Behat-related code into `Behat\MinkExtension`
* Removed PHPUnit test case class
* Updated composer dependencies to not require custom repository anymore
* All drivers moved into separate packages
1.3.3 / 2012-03-23
==================
* Prevent exceptions in `__toString()`
* Added couple of useful step definitions for Behat
* Fixed issues #168, #211, #212, #208
* Lot of small bug fixes and improvements
* Fixed dependencies and composer installation routine
1.3.2 / 2011-12-21
==================
* Fixed webdriver registration in MinkContext
1.3.1 / 2011-12-21
==================
* Fixed Composer package
1.3.0 / 2011-12-21
==================
* Brand new Selenium2Driver (webdriver session)
* Multiselect bugfixes
* ZombieDriver back in the business
* Composer now manages dependencies
* Some MinkContext steps got fixes
* Lots of bug fixes and cleanup
1.2.0 / 2011-11-04
==================
* Brand new SeleniumDriver (thanks @alexandresalome)
* Multiselect support (multiple options selection), including new Behat steps
* Ability to select option by it's text (in addition to value)
* ZombieDriver updates
* Use SuiteHooks to populate parameters (no need to call parent __construct anymore)
* Updated Goutte and all vendors
* Lot of bugfixes and new tests
1.1.1 / 2011-08-12
==================
* Fixed Zombie.js server termination on Linux
* Fixed base_url usage for external URLs
1.1.0 / 2011-08-08
==================
* Added Zombie.js driver (thanks @b00giZm)
* Added pt translation (thanks Daniel Gomes)
* Refactored MinkContext and MinkTestCase
1.0.3 / 2011-08-02
==================
* File uploads for empty fields fixed (GoutteDriver)
* Lazy sessions restart
* `show_tmp_dir` option in MinkContext
* Updated to stable Symfony2 components
* SahiClient connection limit bumped to 60 seconds
* Dutch language support
1.0.2 / 2011-07-22
==================
* ElementHtmlException fixed (thanks @Stof)
1.0.1 / 2011-07-21
==================
* Fixed buggy assertions in MinkContext
1.0.0 / 2011-07-20
==================
* Added missing tests for almost everything
* Hude speedup for SahiDriver
* Support for Behat 2.0 contexts
* Bundled PHPUnit TestCase
* Deep element traversing
* Correct behavior of getText() method
* New getHtml() method
* Basic HTTP auth support
* Soft and hard session resetting
* Cookies management
* Browser history interactions (reload(), back(), forward())
* Weaverryan'd exception messages
* Huge amount of bugfixes and small additions
0.3.2 / 2011-06-20
==================
* Fixed file uploads in Goutte driver
* Fixed setting of long texts into fields
* Added getPlainText() (returns text without tags and whitespaces) method to the element's API
* Start_url is now optional parameter
* Default session (if needed) name now need to be always specified by hands with setDefaultSessionName()
* default_driver => default_session
* Updated Symfony Components
0.3.1 / 2011-05-17
==================
* Small SahiClient update (it generates SID now if no provided)
* setActiveSessionName => setDefaultSessionName method rename
0.3.0 / 2011-05-17
==================
* Rewritten from scratch Mink drivers handler. Now it's sessions handler. And Mink now
sessions-centric tool. See examples in readme. Much cleaner API now.
0.2.4 / 2011-05-12
==================
* Fixed wrong url locator function
* Fixed wrong regex in `should see` step
* Fixed delimiters use in `should see` step
* Added url-match step for checking urls against regex
0.2.3 / 2011-05-01
==================
* Updated SahiClient with new version, which is faster and cleaner with it's exceptions
0.2.2 / 2011-05-01
==================
* Ability to use already started browser as SahiDriver aim
* Added japanese translation for bundled steps (thanks @hidenorigoto)
* 10 seconds limit for browser connection in SahiDriver
0.2.1 / 2011-04-21
==================
* Fixed some bundled step definitions
0.2.0 / 2011-04-21
==================
* Additional step definitions
* Support for extended drivers configuration through behat.yml environment parameters
* Lots of new named selectors
* Bug fixes
* Small improvements
0.1.2 / 2011-04-08
==================
* Fixed Sahi url escaping
0.1.1 / 2011-04-06
==================
* Fixed should/should_not steps
* Added spanish translation
* Fixed forms to use <base> element
* Fixed small UnsupportedByDriverException issue
0.1.0 / 2011-04-04
==================
* Initial release

22
web/vendor/behat/mink/LICENSE vendored Normal file
View file

@ -0,0 +1,22 @@
Copyright (c) 2011-2015 Konstantin Kudryashov <ever.zet@gmail.com>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

74
web/vendor/behat/mink/README.md vendored Normal file
View file

@ -0,0 +1,74 @@
Mink
====
[![Latest Stable Version](https://poser.pugx.org/behat/mink/v/stable.svg)](https://packagist.org/packages/behat/mink)
[![Latest Unstable Version](https://poser.pugx.org/behat/mink/v/unstable.svg)](https://packagist.org/packages/behat/mink)
[![Total Downloads](https://poser.pugx.org/behat/mink/downloads.svg)](https://packagist.org/packages/behat/mink)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/minkphp/Mink/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/minkphp/Mink/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/minkphp/Mink/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/minkphp/Mink/)
[![Build Status](https://travis-ci.org/minkphp/Mink.svg?branch=master)](https://travis-ci.org/minkphp/Mink)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/5bb8fab0-978f-428a-ae23-44ee4e129fbc/mini.png)](https://insight.sensiolabs.com/projects/5bb8fab0-978f-428a-ae23-44ee4e129fbc)
[![License](https://poser.pugx.org/behat/mink/license.svg)](https://packagist.org/packages/behat/mink)
Useful Links
------------
- The main website with documentation is at [http://mink.behat.org](http://mink.behat.org)
- Official Google Group is at [http://groups.google.com/group/behat](http://groups.google.com/group/behat)
- IRC channel on [#freenode](http://freenode.net/) is `#behat`
- [Note on Patches/Pull Requests](CONTRIBUTING.md)
Usage Example
-------------
``` php
<?php
use Behat\Mink\Mink,
Behat\Mink\Session,
Behat\Mink\Driver\GoutteDriver,
Behat\Mink\Driver\Goutte\Client as GoutteClient;
$startUrl = 'http://example.com';
// init Mink and register sessions
$mink = new Mink(array(
'goutte1' => new Session(new GoutteDriver(new GoutteClient())),
'goutte2' => new Session(new GoutteDriver(new GoutteClient())),
'custom' => new Session(new MyCustomDriver($startUrl))
));
// set the default session name
$mink->setDefaultSessionName('goutte2');
// visit a page
$mink->getSession()->visit($startUrl);
// call to getSession() without argument will always return a default session if has one (goutte2 here)
$mink->getSession()->getPage()->findLink('Downloads')->click();
echo $mink->getSession()->getPage()->getContent();
// call to getSession() with argument will return session by its name
$mink->getSession('custom')->getPage()->findLink('Downloads')->click();
echo $mink->getSession('custom')->getPage()->getContent();
// this all is done to make possible mixing sessions
$mink->getSession('goutte1')->getPage()->findLink('Chat')->click();
$mink->getSession('goutte2')->getPage()->findLink('Chat')->click();
```
Install Dependencies
--------------------
``` bash
$> curl -sS https://getcomposer.org/installer | php
$> php composer.phar install
```
Contributors
------------
* Konstantin Kudryashov [everzet](https://github.com/everzet) [lead developer]
* Christophe Coevoet [stof](https://github.com/stof) [lead developer]
* Alexander Obuhovich [aik099](https://github.com/aik099) [lead developer]
* Other [awesome developers](https://github.com/minkphp/Mink/graphs/contributors)

50
web/vendor/behat/mink/composer.json vendored Normal file
View file

@ -0,0 +1,50 @@
{
"name": "behat/mink",
"description": "Browser controller/emulator abstraction for PHP",
"keywords": ["web", "testing", "browser"],
"homepage": "http://mink.behat.org/",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
}
],
"require": {
"php": ">=5.3.1",
"symfony/css-selector": "~2.1|~3.0"
},
"require-dev": {
"symfony/phpunit-bridge": "~2.7|~3.0"
},
"suggest": {
"behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)",
"behat/mink-goutte-driver": "fast headless driver for any app without JS emulation",
"behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)",
"behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)"
},
"autoload": {
"psr-4": {
"Behat\\Mink\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Behat\\Mink\\Tests\\": "tests"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.7.x-dev"
}
}
}

View file

@ -0,0 +1,475 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Driver;
use Behat\Mink\Element\NodeElement;
use Behat\Mink\Exception\UnsupportedDriverActionException;
use Behat\Mink\Session;
/**
* Core driver.
* All other drivers should extend this class for future compatibility.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
abstract class CoreDriver implements DriverInterface
{
/**
* @var Session
*/
private $session;
/**
* {@inheritdoc}
*/
public function setSession(Session $session)
{
$this->session = $session;
}
/**
* {@inheritdoc}
*/
public function start()
{
throw new UnsupportedDriverActionException('Starting the driver is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function isStarted()
{
throw new UnsupportedDriverActionException('Checking the driver state is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function stop()
{
throw new UnsupportedDriverActionException('Stopping the driver is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function reset()
{
throw new UnsupportedDriverActionException('Resetting the driver is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function visit($url)
{
throw new UnsupportedDriverActionException('Visiting an url is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getCurrentUrl()
{
throw new UnsupportedDriverActionException('Getting the current url is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getContent()
{
throw new UnsupportedDriverActionException('Getting the page content is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function find($xpath)
{
$elements = array();
foreach ($this->findElementXpaths($xpath) as $xpath) {
$elements[] = new NodeElement($xpath, $this->session);
}
return $elements;
}
/**
* Finds elements with specified XPath query.
*
* @see find()
*
* @param string $xpath
*
* @return string[] The XPath of the matched elements
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
*/
protected function findElementXpaths($xpath)
{
throw new UnsupportedDriverActionException('Finding elements is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getTagName($xpath)
{
throw new UnsupportedDriverActionException('Getting the tag name is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getText($xpath)
{
throw new UnsupportedDriverActionException('Getting the element text is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getHtml($xpath)
{
throw new UnsupportedDriverActionException('Getting the element inner HTML is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getOuterHtml($xpath)
{
throw new UnsupportedDriverActionException('Getting the element outer HTML is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getAttribute($xpath, $name)
{
throw new UnsupportedDriverActionException('Getting the element attribute is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getValue($xpath)
{
throw new UnsupportedDriverActionException('Getting the field value is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function setValue($xpath, $value)
{
throw new UnsupportedDriverActionException('Setting the field value is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function check($xpath)
{
throw new UnsupportedDriverActionException('Checking a checkbox is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function uncheck($xpath)
{
throw new UnsupportedDriverActionException('Unchecking a checkbox is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function isChecked($xpath)
{
throw new UnsupportedDriverActionException('Getting the state of a checkbox is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function selectOption($xpath, $value, $multiple = false)
{
throw new UnsupportedDriverActionException('Selecting an option is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function click($xpath)
{
throw new UnsupportedDriverActionException('Clicking on an element is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function attachFile($xpath, $path)
{
throw new UnsupportedDriverActionException('Attaching a file in an input is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function reload()
{
throw new UnsupportedDriverActionException('Page reloading is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function forward()
{
throw new UnsupportedDriverActionException('Forward action is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function back()
{
throw new UnsupportedDriverActionException('Backward action is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function setBasicAuth($user, $password)
{
throw new UnsupportedDriverActionException('Basic auth setup is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function switchToWindow($name = null)
{
throw new UnsupportedDriverActionException('Windows management is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function switchToIFrame($name = null)
{
throw new UnsupportedDriverActionException('iFrames management is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function setRequestHeader($name, $value)
{
throw new UnsupportedDriverActionException('Request headers manipulation is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getResponseHeaders()
{
throw new UnsupportedDriverActionException('Response headers are not available from %s', $this);
}
/**
* {@inheritdoc}
*/
public function setCookie($name, $value = null)
{
throw new UnsupportedDriverActionException('Cookies manipulation is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getCookie($name)
{
throw new UnsupportedDriverActionException('Cookies are not available from %s', $this);
}
/**
* {@inheritdoc}
*/
public function getStatusCode()
{
throw new UnsupportedDriverActionException('Status code is not available from %s', $this);
}
/**
* {@inheritdoc}
*/
public function getScreenshot()
{
throw new UnsupportedDriverActionException('Screenshots are not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getWindowNames()
{
throw new UnsupportedDriverActionException('Listing all window names is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function getWindowName()
{
throw new UnsupportedDriverActionException('Listing this window name is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function doubleClick($xpath)
{
throw new UnsupportedDriverActionException('Double-clicking is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function rightClick($xpath)
{
throw new UnsupportedDriverActionException('Right-clicking is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function isVisible($xpath)
{
throw new UnsupportedDriverActionException('Element visibility check is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function isSelected($xpath)
{
throw new UnsupportedDriverActionException('Element selection check is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function mouseOver($xpath)
{
throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function focus($xpath)
{
throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function blur($xpath)
{
throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function keyPress($xpath, $char, $modifier = null)
{
throw new UnsupportedDriverActionException('Keyboard manipulations are not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function keyDown($xpath, $char, $modifier = null)
{
throw new UnsupportedDriverActionException('Keyboard manipulations are not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function keyUp($xpath, $char, $modifier = null)
{
throw new UnsupportedDriverActionException('Keyboard manipulations are not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function dragTo($sourceXpath, $destinationXpath)
{
throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function executeScript($script)
{
throw new UnsupportedDriverActionException('JS is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function evaluateScript($script)
{
throw new UnsupportedDriverActionException('JS is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function wait($timeout, $condition)
{
throw new UnsupportedDriverActionException('JS is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function resizeWindow($width, $height, $name = null)
{
throw new UnsupportedDriverActionException('Window resizing is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function maximizeWindow($name = null)
{
throw new UnsupportedDriverActionException('Window maximize is not supported by %s', $this);
}
/**
* {@inheritdoc}
*/
public function submitForm($xpath)
{
throw new UnsupportedDriverActionException('Form submission is not supported by %s', $this);
}
}

View file

@ -0,0 +1,637 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Driver;
use Behat\Mink\Element\NodeElement;
use Behat\Mink\Exception\DriverException;
use Behat\Mink\Exception\UnsupportedDriverActionException;
use Behat\Mink\Session;
/**
* Driver interface.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
interface DriverInterface
{
/**
* Sets driver's current session.
*
* @param Session $session
*/
public function setSession(Session $session);
/**
* Starts driver.
*
* Once started, the driver should be ready to visit a page.
*
* Calling any action before visiting a page is an undefined behavior.
* The only supported method calls on a fresh driver are
* - visit()
* - setRequestHeader()
* - setBasicAuth()
* - reset()
* - stop()
*
* Calling start on a started driver is an undefined behavior. Driver
* implementations are free to handle it silently or to fail with an
* exception.
*
* @throws DriverException When the driver cannot be started
*/
public function start();
/**
* Checks whether driver is started.
*
* @return Boolean
*/
public function isStarted();
/**
* Stops driver.
*
* Once stopped, the driver should be started again before using it again.
*
* Calling any action on a stopped driver is an undefined behavior.
* The only supported method call after stopping a driver is starting it again.
*
* Calling stop on a stopped driver is an undefined behavior. Driver
* implementations are free to handle it silently or to fail with an
* exception.
*
* @throws DriverException When the driver cannot be closed
*/
public function stop();
/**
* Resets driver state.
*
* This should reset cookies, request headers and basic authentication.
* When possible, the history should be reset as well, but this is not enforced
* as some implementations may not be able to reset it without restarting the
* driver entirely. Consumers requiring a clean history should restart the driver
* to enforce it.
*
* Once reset, the driver should be ready to visit a page.
* Calling any action before visiting a page is an undefined behavior.
* The only supported method calls on a fresh driver are
* - visit()
* - setRequestHeader()
* - setBasicAuth()
* - reset()
* - stop()
*
* Calling reset on a stopped driver is an undefined behavior.
*/
public function reset();
/**
* Visit specified URL.
*
* @param string $url url of the page
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function visit($url);
/**
* Returns current URL address.
*
* @return string
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getCurrentUrl();
/**
* Reloads current page.
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function reload();
/**
* Moves browser forward 1 page.
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function forward();
/**
* Moves browser backward 1 page.
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function back();
/**
* Sets HTTP Basic authentication parameters.
*
* @param string|Boolean $user user name or false to disable authentication
* @param string $password password
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function setBasicAuth($user, $password);
/**
* Switches to specific browser window.
*
* @param string $name window name (null for switching back to main window)
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function switchToWindow($name = null);
/**
* Switches to specific iFrame.
*
* @param string $name iframe name (null for switching back)
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function switchToIFrame($name = null);
/**
* Sets specific request header on client.
*
* @param string $name
* @param string $value
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function setRequestHeader($name, $value);
/**
* Returns last response headers.
*
* @return array
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getResponseHeaders();
/**
* Sets cookie.
*
* @param string $name
* @param string $value
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function setCookie($name, $value = null);
/**
* Returns cookie by name.
*
* @param string $name
*
* @return string|null
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getCookie($name);
/**
* Returns last response status code.
*
* @return int
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getStatusCode();
/**
* Returns last response content.
*
* @return string
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getContent();
/**
* Capture a screenshot of the current window.
*
* @return string screenshot of MIME type image/* depending
* on driver (e.g., image/png, image/jpeg)
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getScreenshot();
/**
* Return the names of all open windows.
*
* @return array array of all open windows
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getWindowNames();
/**
* Return the name of the currently active window.
*
* @return string the name of the current window
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getWindowName();
/**
* Finds elements with specified XPath query.
*
* @param string $xpath
*
* @return NodeElement[]
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function find($xpath);
/**
* Returns element's tag name by it's XPath query.
*
* @param string $xpath
*
* @return string
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getTagName($xpath);
/**
* Returns element's text by it's XPath query.
*
* @param string $xpath
*
* @return string
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getText($xpath);
/**
* Returns element's inner html by it's XPath query.
*
* @param string $xpath
*
* @return string
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getHtml($xpath);
/**
* Returns element's outer html by it's XPath query.
*
* @param string $xpath
*
* @return string
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getOuterHtml($xpath);
/**
* Returns element's attribute by it's XPath query.
*
* @param string $xpath
* @param string $name
*
* @return string|null
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function getAttribute($xpath, $name);
/**
* Returns element's value by it's XPath query.
*
* @param string $xpath
*
* @return string|bool|array
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*
* @see \Behat\Mink\Element\NodeElement::getValue
*/
public function getValue($xpath);
/**
* Sets element's value by it's XPath query.
*
* @param string $xpath
* @param string|bool|array $value
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*
* @see \Behat\Mink\Element\NodeElement::setValue
*/
public function setValue($xpath, $value);
/**
* Checks checkbox by it's XPath query.
*
* @param string $xpath
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*
* @see \Behat\Mink\Element\NodeElement::check
*/
public function check($xpath);
/**
* Unchecks checkbox by it's XPath query.
*
* @param string $xpath
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*
* @see \Behat\Mink\Element\NodeElement::uncheck
*/
public function uncheck($xpath);
/**
* Checks whether checkbox or radio button located by it's XPath query is checked.
*
* @param string $xpath
*
* @return Boolean
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*
* @see \Behat\Mink\Element\NodeElement::isChecked
*/
public function isChecked($xpath);
/**
* Selects option from select field or value in radio group located by it's XPath query.
*
* @param string $xpath
* @param string $value
* @param Boolean $multiple
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*
* @see \Behat\Mink\Element\NodeElement::selectOption
*/
public function selectOption($xpath, $value, $multiple = false);
/**
* Checks whether select option, located by it's XPath query, is selected.
*
* @param string $xpath
*
* @return Boolean
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*
* @see \Behat\Mink\Element\NodeElement::isSelected
*/
public function isSelected($xpath);
/**
* Clicks button or link located by it's XPath query.
*
* @param string $xpath
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function click($xpath);
/**
* Double-clicks button or link located by it's XPath query.
*
* @param string $xpath
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function doubleClick($xpath);
/**
* Right-clicks button or link located by it's XPath query.
*
* @param string $xpath
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function rightClick($xpath);
/**
* Attaches file path to file field located by it's XPath query.
*
* @param string $xpath
* @param string $path
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*
* @see \Behat\Mink\Element\NodeElement::attachFile
*/
public function attachFile($xpath, $path);
/**
* Checks whether element visible located by it's XPath query.
*
* @param string $xpath
*
* @return Boolean
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function isVisible($xpath);
/**
* Simulates a mouse over on the element.
*
* @param string $xpath
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function mouseOver($xpath);
/**
* Brings focus to element.
*
* @param string $xpath
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function focus($xpath);
/**
* Removes focus from element.
*
* @param string $xpath
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function blur($xpath);
/**
* Presses specific keyboard key.
*
* @param string $xpath
* @param string|int $char could be either char ('b') or char-code (98)
* @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function keyPress($xpath, $char, $modifier = null);
/**
* Pressed down specific keyboard key.
*
* @param string $xpath
* @param string|int $char could be either char ('b') or char-code (98)
* @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function keyDown($xpath, $char, $modifier = null);
/**
* Pressed up specific keyboard key.
*
* @param string $xpath
* @param string|int $char could be either char ('b') or char-code (98)
* @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function keyUp($xpath, $char, $modifier = null);
/**
* Drag one element onto another.
*
* @param string $sourceXpath
* @param string $destinationXpath
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function dragTo($sourceXpath, $destinationXpath);
/**
* Executes JS script.
*
* @param string $script
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function executeScript($script);
/**
* Evaluates JS script.
*
* The "return" keyword is optional in the script passed as argument. Driver implementations
* must accept the expression both with and without the keyword.
*
* @param string $script
*
* @return mixed
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function evaluateScript($script);
/**
* Waits some time or until JS condition turns true.
*
* @param int $timeout timeout in milliseconds
* @param string $condition JS condition
*
* @return bool
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function wait($timeout, $condition);
/**
* Set the dimensions of the window.
*
* @param int $width set the window width, measured in pixels
* @param int $height set the window height, measured in pixels
* @param string $name window name (null for the main window)
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function resizeWindow($width, $height, $name = null);
/**
* Maximizes the window if it is not maximized already.
*
* @param string $name window name (null for the main window)
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*/
public function maximizeWindow($name = null);
/**
* Submits the form.
*
* @param string $xpath Xpath.
*
* @throws UnsupportedDriverActionException When operation not supported by the driver
* @throws DriverException When the operation cannot be done
*
* @see \Behat\Mink\Element\NodeElement::submitForm
*/
public function submitForm($xpath);
}

View file

@ -0,0 +1,51 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Element;
/**
* Document element.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class DocumentElement extends TraversableElement
{
/**
* Returns XPath for handled element.
*
* @return string
*/
public function getXpath()
{
return '//html';
}
/**
* Returns document content.
*
* @return string
*/
public function getContent()
{
return trim($this->getDriver()->getContent());
}
/**
* Check whether document has specified content.
*
* @param string $content
*
* @return Boolean
*/
public function hasContent($content)
{
return $this->has('named', array('content', $content));
}
}

View file

@ -0,0 +1,214 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Element;
use Behat\Mink\Driver\DriverInterface;
use Behat\Mink\Exception\ElementNotFoundException;
use Behat\Mink\Selector\SelectorsHandler;
use Behat\Mink\Selector\Xpath\Manipulator;
use Behat\Mink\Session;
/**
* Base element.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
abstract class Element implements ElementInterface
{
/**
* @var Session
*/
private $session;
/**
* Driver.
*
* @var DriverInterface
*/
private $driver;
/**
* @var SelectorsHandler
*/
private $selectorsHandler;
/**
* @var Manipulator
*/
private $xpathManipulator;
/**
* Initialize element.
*
* @param Session $session
*/
public function __construct(Session $session)
{
$this->xpathManipulator = new Manipulator();
$this->session = $session;
$this->driver = $session->getDriver();
$this->selectorsHandler = $session->getSelectorsHandler();
}
/**
* Returns element session.
*
* @return Session
*
* @deprecated Accessing the session from the element is deprecated as of 1.6 and will be impossible in 2.0.
*/
public function getSession()
{
@trigger_error(sprintf('The method %s is deprecated as of 1.6 and will be removed in 2.0', __METHOD__), E_USER_DEPRECATED);
return $this->session;
}
/**
* Returns element's driver.
*
* @return DriverInterface
*/
protected function getDriver()
{
return $this->driver;
}
/**
* Returns selectors handler.
*
* @return SelectorsHandler
*
* @deprecated Accessing the selectors handler in the element is deprecated as of 1.7 and will be impossible in 2.0.
*/
protected function getSelectorsHandler()
{
@trigger_error(sprintf('The method %s is deprecated as of 1.7 and will be removed in 2.0', __METHOD__), E_USER_DEPRECATED);
return $this->selectorsHandler;
}
/**
* {@inheritdoc}
*/
public function has($selector, $locator)
{
return null !== $this->find($selector, $locator);
}
/**
* {@inheritdoc}
*/
public function isValid()
{
return 1 === count($this->getDriver()->find($this->getXpath()));
}
/**
* {@inheritdoc}
*/
public function waitFor($timeout, $callback)
{
if (!is_callable($callback)) {
throw new \InvalidArgumentException('Given callback is not a valid callable');
}
$start = microtime(true);
$end = $start + $timeout;
do {
$result = call_user_func($callback, $this);
if ($result) {
break;
}
usleep(100000);
} while (microtime(true) < $end);
return $result;
}
/**
* {@inheritdoc}
*/
public function find($selector, $locator)
{
$items = $this->findAll($selector, $locator);
return count($items) ? current($items) : null;
}
/**
* {@inheritdoc}
*/
public function findAll($selector, $locator)
{
if ('named' === $selector) {
$items = $this->findAll('named_exact', $locator);
if (empty($items)) {
$items = $this->findAll('named_partial', $locator);
}
return $items;
}
$xpath = $this->selectorsHandler->selectorToXpath($selector, $locator);
$xpath = $this->xpathManipulator->prepend($xpath, $this->getXpath());
return $this->getDriver()->find($xpath);
}
/**
* {@inheritdoc}
*/
public function getText()
{
return $this->getDriver()->getText($this->getXpath());
}
/**
* {@inheritdoc}
*/
public function getHtml()
{
return $this->getDriver()->getHtml($this->getXpath());
}
/**
* Returns element outer html.
*
* @return string
*/
public function getOuterHtml()
{
return $this->getDriver()->getOuterHtml($this->getXpath());
}
/**
* Builds an ElementNotFoundException.
*
* @param string $type
* @param string|null $selector
* @param string|null $locator
*
* @return ElementNotFoundException
*
* @deprecated as of 1.7, to be removed in 2.0
*/
protected function elementNotFound($type, $selector = null, $locator = null)
{
@trigger_error(sprintf('The method %s is deprecated as of 1.7 and will be removed in 2.0', __METHOD__), E_USER_DEPRECATED);
return new ElementNotFoundException($this->driver, $type, $selector, $locator);
}
}

View file

@ -0,0 +1,115 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Element;
use Behat\Mink\Session;
/**
* Element interface.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
interface ElementInterface
{
/**
* Returns XPath for handled element.
*
* @return string
*/
public function getXpath();
/**
* Returns element's session.
*
* @return Session
*
* @deprecated Accessing the session from the element is deprecated as of 1.6 and will be impossible in 2.0.
*/
public function getSession();
/**
* Checks whether element with specified selector exists inside the current element.
*
* @param string $selector selector engine name
* @param string|array $locator selector locator
*
* @return Boolean
*
* @see ElementInterface::findAll for the supported selectors
*/
public function has($selector, $locator);
/**
* Checks if an element still exists in the DOM.
*
* @return bool
*/
public function isValid();
/**
* Waits for an element(-s) to appear and returns it.
*
* @param int|float $timeout Maximal allowed waiting time in seconds.
* @param callable $callback Callback, which result is both used as waiting condition and returned.
* Will receive reference to `this element` as first argument.
*
* @return mixed
*
* @throws \InvalidArgumentException When invalid callback given.
*/
public function waitFor($timeout, $callback);
/**
* Finds first element with specified selector inside the current element.
*
* @param string $selector selector engine name
* @param string|array $locator selector locator
*
* @return NodeElement|null
*
* @see ElementInterface::findAll for the supported selectors
*/
public function find($selector, $locator);
/**
* Finds all elements with specified selector inside the current element.
*
* Valid selector engines are named, xpath, css, named_partial and named_exact.
*
* 'named' is a pseudo selector engine which prefers an exact match but
* will return a partial match if no exact match is found.
* 'xpath' is a pseudo selector engine supported by SelectorsHandler.
*
* More selector engines can be registered in the SelectorsHandler.
*
* @param string $selector selector engine name
* @param string|array $locator selector locator
*
* @return NodeElement[]
*
* @see NamedSelector for the locators supported by the named selectors
*/
public function findAll($selector, $locator);
/**
* Returns element text (inside tag).
*
* @return string
*/
public function getText();
/**
* Returns element inner html.
*
* @return string
*/
public function getHtml();
}

View file

@ -0,0 +1,350 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Element;
use Behat\Mink\Session;
use Behat\Mink\Exception\ElementNotFoundException;
/**
* Page element node.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class NodeElement extends TraversableElement
{
private $xpath;
/**
* Initializes node element.
*
* @param string $xpath element xpath
* @param Session $session session instance
*/
public function __construct($xpath, Session $session)
{
$this->xpath = $xpath;
parent::__construct($session);
}
/**
* Returns XPath for handled element.
*
* @return string
*/
public function getXpath()
{
return $this->xpath;
}
/**
* Returns parent element to the current one.
*
* @return NodeElement
*/
public function getParent()
{
return $this->find('xpath', '..');
}
/**
* Returns current node tag name.
*
* The value is always returned in lowercase to allow an easy comparison.
*
* @return string
*/
public function getTagName()
{
return strtolower($this->getDriver()->getTagName($this->getXpath()));
}
/**
* Returns the value of the form field or option element.
*
* For checkbox fields, the value is a boolean indicating whether the checkbox is checked.
* For radio buttons, the value is the value of the selected button in the radio group
* or null if no button is selected.
* For single select boxes, the value is the value of the selected option.
* For multiple select boxes, the value is an array of selected option values.
* for file inputs, the return value is undefined given that browsers don't allow accessing
* the value of file inputs for security reasons. Some drivers may allow accessing the
* path of the file set in the field, but this is not required if it cannot be implemented.
* For textarea elements and all textual fields, the value is the content of the field.
* Form option elements, the value is the value of the option (the value attribute or the text
* content if the attribute is not set).
*
* Calling this method on other elements than form fields or option elements is not allowed.
*
* @return string|bool|array
*/
public function getValue()
{
return $this->getDriver()->getValue($this->getXpath());
}
/**
* Sets the value of the form field.
*
* Calling this method on other elements than form fields is not allowed.
*
* @param string|bool|array $value
*
* @see NodeElement::getValue for the format of the value for each type of field
*/
public function setValue($value)
{
$this->getDriver()->setValue($this->getXpath(), $value);
}
/**
* Checks whether element has attribute with specified name.
*
* @param string $name
*
* @return Boolean
*/
public function hasAttribute($name)
{
return null !== $this->getDriver()->getAttribute($this->getXpath(), $name);
}
/**
* Returns specified attribute value.
*
* @param string $name
*
* @return string|null
*/
public function getAttribute($name)
{
return $this->getDriver()->getAttribute($this->getXpath(), $name);
}
/**
* Checks whether an element has a named CSS class.
*
* @param string $className Name of the class
*
* @return bool
*/
public function hasClass($className)
{
if ($this->hasAttribute('class')) {
return in_array($className, preg_split('/\s+/', $this->getAttribute('class')));
}
return false;
}
/**
* Clicks current node.
*/
public function click()
{
$this->getDriver()->click($this->getXpath());
}
/**
* Presses current button.
*/
public function press()
{
$this->click();
}
/**
* Double-clicks current node.
*/
public function doubleClick()
{
$this->getDriver()->doubleClick($this->getXpath());
}
/**
* Right-clicks current node.
*/
public function rightClick()
{
$this->getDriver()->rightClick($this->getXpath());
}
/**
* Checks current node if it's a checkbox field.
*/
public function check()
{
$this->getDriver()->check($this->getXpath());
}
/**
* Unchecks current node if it's a checkbox field.
*/
public function uncheck()
{
$this->getDriver()->uncheck($this->getXpath());
}
/**
* Checks whether current node is checked if it's a checkbox or radio field.
*
* Calling this method on any other elements is not allowed.
*
* @return Boolean
*/
public function isChecked()
{
return (Boolean) $this->getDriver()->isChecked($this->getXpath());
}
/**
* Selects specified option for select field or specified radio button in the group.
*
* If the current node is a select box, this selects the option found by its value or
* its text.
* If the current node is a radio button, this selects the radio button with the given
* value in the radio button group of the current node.
*
* Calling this method on any other elements is not allowed.
*
* @param string $option
* @param Boolean $multiple whether the option should be added to the selection for multiple selects
*
* @throws ElementNotFoundException when the option is not found in the select box
*/
public function selectOption($option, $multiple = false)
{
if ('select' !== $this->getTagName()) {
$this->getDriver()->selectOption($this->getXpath(), $option, $multiple);
return;
}
$opt = $this->find('named', array('option', $option));
if (null === $opt) {
throw new ElementNotFoundException($this->getDriver(), 'select option', 'value|text', $option);
}
$this->getDriver()->selectOption($this->getXpath(), $opt->getValue(), $multiple);
}
/**
* Checks whether current node is selected if it's a option field.
*
* Calling this method on any other elements is not allowed.
*
* @return Boolean
*/
public function isSelected()
{
return (Boolean) $this->getDriver()->isSelected($this->getXpath());
}
/**
* Attach file to current node if it's a file input.
*
* Calling this method on any other elements than file input is not allowed.
*
* @param string $path path to file (local)
*/
public function attachFile($path)
{
$this->getDriver()->attachFile($this->getXpath(), $path);
}
/**
* Checks whether current node is visible on page.
*
* @return Boolean
*/
public function isVisible()
{
return (Boolean) $this->getDriver()->isVisible($this->getXpath());
}
/**
* Simulates a mouse over on the element.
*/
public function mouseOver()
{
$this->getDriver()->mouseOver($this->getXpath());
}
/**
* Drags current node onto other node.
*
* @param ElementInterface $destination other node
*/
public function dragTo(ElementInterface $destination)
{
$this->getDriver()->dragTo($this->getXpath(), $destination->getXpath());
}
/**
* Brings focus to element.
*/
public function focus()
{
$this->getDriver()->focus($this->getXpath());
}
/**
* Removes focus from element.
*/
public function blur()
{
$this->getDriver()->blur($this->getXpath());
}
/**
* Presses specific keyboard key.
*
* @param string|int $char could be either char ('b') or char-code (98)
* @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
*/
public function keyPress($char, $modifier = null)
{
$this->getDriver()->keyPress($this->getXpath(), $char, $modifier);
}
/**
* Pressed down specific keyboard key.
*
* @param string|int $char could be either char ('b') or char-code (98)
* @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
*/
public function keyDown($char, $modifier = null)
{
$this->getDriver()->keyDown($this->getXpath(), $char, $modifier);
}
/**
* Pressed up specific keyboard key.
*
* @param string|int $char could be either char ('b') or char-code (98)
* @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
*/
public function keyUp($char, $modifier = null)
{
$this->getDriver()->keyUp($this->getXpath(), $char, $modifier);
}
/**
* Submits the form.
*
* Calling this method on anything else than form elements is not allowed.
*/
public function submit()
{
$this->getDriver()->submitForm($this->getXpath());
}
}

View file

@ -0,0 +1,297 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Element;
use Behat\Mink\Exception\ElementNotFoundException;
/**
* Traversable element.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
abstract class TraversableElement extends Element
{
/**
* Finds element by its id.
*
* @param string $id element id
*
* @return NodeElement|null
*/
public function findById($id)
{
return $this->find('named', array('id', $id));
}
/**
* Checks whether element has a link with specified locator.
*
* @param string $locator link id, title, text or image alt
*
* @return Boolean
*/
public function hasLink($locator)
{
return null !== $this->findLink($locator);
}
/**
* Finds link with specified locator.
*
* @param string $locator link id, title, text or image alt
*
* @return NodeElement|null
*/
public function findLink($locator)
{
return $this->find('named', array('link', $locator));
}
/**
* Clicks link with specified locator.
*
* @param string $locator link id, title, text or image alt
*
* @throws ElementNotFoundException
*/
public function clickLink($locator)
{
$link = $this->findLink($locator);
if (null === $link) {
throw new ElementNotFoundException($this->getDriver(), 'link', 'id|title|alt|text', $locator);
}
$link->click();
}
/**
* Checks whether element has a button (input[type=submit|image|button|reset], button) with specified locator.
*
* @param string $locator button id, value or alt
*
* @return Boolean
*/
public function hasButton($locator)
{
return null !== $this->findButton($locator);
}
/**
* Finds button (input[type=submit|image|button|reset], button) with specified locator.
*
* @param string $locator button id, value or alt
*
* @return NodeElement|null
*/
public function findButton($locator)
{
return $this->find('named', array('button', $locator));
}
/**
* Presses button (input[type=submit|image|button|reset], button) with specified locator.
*
* @param string $locator button id, value or alt
*
* @throws ElementNotFoundException
*/
public function pressButton($locator)
{
$button = $this->findButton($locator);
if (null === $button) {
throw new ElementNotFoundException($this->getDriver(), 'button', 'id|name|title|alt|value', $locator);
}
$button->press();
}
/**
* Checks whether element has a field (input, textarea, select) with specified locator.
*
* @param string $locator input id, name or label
*
* @return Boolean
*/
public function hasField($locator)
{
return null !== $this->findField($locator);
}
/**
* Finds field (input, textarea, select) with specified locator.
*
* @param string $locator input id, name or label
*
* @return NodeElement|null
*/
public function findField($locator)
{
return $this->find('named', array('field', $locator));
}
/**
* Fills in field (input, textarea, select) with specified locator.
*
* @param string $locator input id, name or label
* @param string $value value
*
* @throws ElementNotFoundException
*
* @see NodeElement::setValue
*/
public function fillField($locator, $value)
{
$field = $this->findField($locator);
if (null === $field) {
throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value|placeholder', $locator);
}
$field->setValue($value);
}
/**
* Checks whether element has a checkbox with specified locator, which is checked.
*
* @param string $locator input id, name or label
*
* @return Boolean
*
* @see NodeElement::isChecked
*/
public function hasCheckedField($locator)
{
$field = $this->findField($locator);
return null !== $field && $field->isChecked();
}
/**
* Checks whether element has a checkbox with specified locator, which is unchecked.
*
* @param string $locator input id, name or label
*
* @return Boolean
*
* @see NodeElement::isChecked
*/
public function hasUncheckedField($locator)
{
$field = $this->findField($locator);
return null !== $field && !$field->isChecked();
}
/**
* Checks checkbox with specified locator.
*
* @param string $locator input id, name or label
*
* @throws ElementNotFoundException
*/
public function checkField($locator)
{
$field = $this->findField($locator);
if (null === $field) {
throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value', $locator);
}
$field->check();
}
/**
* Unchecks checkbox with specified locator.
*
* @param string $locator input id, name or label
*
* @throws ElementNotFoundException
*/
public function uncheckField($locator)
{
$field = $this->findField($locator);
if (null === $field) {
throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value', $locator);
}
$field->uncheck();
}
/**
* Checks whether element has a select field with specified locator.
*
* @param string $locator select id, name or label
*
* @return Boolean
*/
public function hasSelect($locator)
{
return $this->has('named', array('select', $locator));
}
/**
* Selects option from select field with specified locator.
*
* @param string $locator input id, name or label
* @param string $value option value
* @param Boolean $multiple select multiple options
*
* @throws ElementNotFoundException
*
* @see NodeElement::selectOption
*/
public function selectFieldOption($locator, $value, $multiple = false)
{
$field = $this->findField($locator);
if (null === $field) {
throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value', $locator);
}
$field->selectOption($value, $multiple);
}
/**
* Checks whether element has a table with specified locator.
*
* @param string $locator table id or caption
*
* @return Boolean
*/
public function hasTable($locator)
{
return $this->has('named', array('table', $locator));
}
/**
* Attach file to file field with specified locator.
*
* @param string $locator input id, name or label
* @param string $path path to file
*
* @throws ElementNotFoundException
*
* @see NodeElement::attachFile
*/
public function attachFileToField($locator, $path)
{
$field = $this->findField($locator);
if (null === $field) {
throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value', $locator);
}
$field->attachFile($path);
}
}

View file

@ -0,0 +1,31 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Exception;
/**
* Exception thrown by drivers when they fail to perform an action.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class DriverException extends Exception
{
/**
* Initializes exception.
*
* @param string $message
* @param int $code
* @param \Exception|null $previous
*/
public function __construct($message, $code = 0, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

View file

@ -0,0 +1,60 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Exception;
@trigger_error('The class '.__NAMESPACE__.'\ElementException is deprecated as of Mink 1.6 and will be removed in 2.0', E_USER_DEPRECATED);
use Behat\Mink\Element\Element;
/**
* A standard way for elements to re-throw exceptions.
*
* @deprecated This exception class is not used anymore in Mink 1.6 and will be removed in 2.0
*
* @author Chris Worfolk <xmeltrut@gmail.com>
*/
class ElementException extends Exception
{
private $element;
/**
* Initialises exception.
*
* @param Element $element optional message
* @param \Exception $exception exception
*/
public function __construct(Element $element, \Exception $exception)
{
$this->element = $element;
parent::__construct(sprintf("Exception thrown by %s\n%s", $element->getXpath(), $exception->getMessage()));
}
/**
* Override default toString so we don't send a full backtrace in verbose mode.
*
* @return string
*/
public function __toString()
{
return $this->getMessage();
}
/**
* Get the element that caused the exception.
*
* @return Element
*/
public function getElement()
{
return $this->element;
}
}

View file

@ -0,0 +1,50 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Exception;
use Behat\Mink\Driver\DriverInterface;
use Behat\Mink\Element\Element;
use Behat\Mink\Session;
/**
* Exception thrown when an expectation on the HTML of an element fails.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class ElementHtmlException extends ExpectationException
{
/**
* Element instance.
*
* @var Element
*/
protected $element;
/**
* Initializes exception.
*
* @param string $message optional message
* @param DriverInterface|Session $driver driver instance
* @param Element $element element
* @param \Exception $exception expectation exception
*/
public function __construct($message, $driver, Element $element, \Exception $exception = null)
{
$this->element = $element;
parent::__construct($message, $driver, $exception);
}
protected function getContext()
{
return $this->element->getOuterHtml();
}
}

View file

@ -0,0 +1,54 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Exception;
use Behat\Mink\Driver\DriverInterface;
use Behat\Mink\Session;
/**
* Exception thrown when an expected element is not found.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class ElementNotFoundException extends ExpectationException
{
/**
* Initializes exception.
*
* @param DriverInterface|Session $driver driver instance
* @param string $type element type
* @param string $selector element selector type
* @param string $locator element locator
*/
public function __construct($driver, $type = null, $selector = null, $locator = null)
{
$message = '';
if (null !== $type) {
$message .= ucfirst($type);
} else {
$message .= 'Tag';
}
if (null !== $locator) {
if (null === $selector || in_array($selector, array('css', 'xpath'))) {
$selector = 'matching '.($selector ?: 'locator');
} else {
$selector = 'with '.$selector;
}
$message .= ' '.$selector.' "'.$locator.'"';
}
$message .= ' not found.';
parent::__construct($message, $driver);
}
}

View file

@ -0,0 +1,24 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Exception;
/**
* Exception thrown when an expectation on the text of an element fails.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class ElementTextException extends ElementHtmlException
{
protected function getContext()
{
return $this->element->getText();
}
}

View file

@ -0,0 +1,20 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Exception;
/**
* Mink base exception class.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
abstract class Exception extends \Exception
{
}

View file

@ -0,0 +1,175 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Exception;
use Behat\Mink\Driver\DriverInterface;
use Behat\Mink\Session;
/**
* Exception thrown for failed expectations.
*
* Some specialized child classes are available to customize the error rendering.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class ExpectationException extends Exception
{
private $session;
private $driver;
/**
* Initializes exception.
*
* @param string $message optional message
* @param DriverInterface|Session $driver driver instance (or session for BC)
* @param \Exception|null $exception expectation exception
*/
public function __construct($message, $driver, \Exception $exception = null)
{
if ($driver instanceof Session) {
@trigger_error('Passing a Session object to the ExpectationException constructor is deprecated as of Mink 1.7. Pass the driver instead.', E_USER_DEPRECATED);
$this->session = $driver;
$this->driver = $driver->getDriver();
} elseif (!$driver instanceof DriverInterface) {
// Trigger an exception as we cannot typehint a disjunction
throw new \InvalidArgumentException('The ExpectationException constructor expects a DriverInterface or a Session.');
} else {
$this->driver = $driver;
}
if (!$message && null !== $exception) {
$message = $exception->getMessage();
}
parent::__construct($message, 0, $exception);
}
/**
* Returns exception message with additional context info.
*
* @return string
*/
public function __toString()
{
try {
$pageText = $this->pipeString($this->trimString($this->getContext())."\n");
$string = sprintf("%s\n\n%s%s", $this->getMessage(), $this->getResponseInfo(), $pageText);
} catch (\Exception $e) {
return $this->getMessage();
}
return $string;
}
/**
* Gets the context rendered for this exception.
*
* @return string
*/
protected function getContext()
{
return $this->trimBody($this->driver->getContent());
}
/**
* Returns driver.
*
* @return DriverInterface
*/
protected function getDriver()
{
return $this->driver;
}
/**
* Returns exception session.
*
* @return Session
*
* @deprecated since 1.7, to be removed in 2.0. Use getDriver and the driver API instead.
*/
protected function getSession()
{
if (null === $this->session) {
throw new \LogicException(sprintf('The deprecated method %s cannot be used when passing a driver in the constructor', __METHOD__));
}
@trigger_error(sprintf('The method %s is deprecated as of Mink 1.7 and will be removed in 2.0. Use getDriver and the driver API instead.'));
return $this->session;
}
/**
* Prepends every line in a string with pipe (|).
*
* @param string $string
*
* @return string
*/
protected function pipeString($string)
{
return '| '.strtr($string, array("\n" => "\n| "));
}
/**
* Removes response header/footer, letting only <body /> content.
*
* @param string $string response content
*
* @return string
*/
protected function trimBody($string)
{
$string = preg_replace(array('/^.*<body>/s', '/<\/body>.*$/s'), array('<body>', '</body>'), $string);
return $string;
}
/**
* Trims string to specified number of chars.
*
* @param string $string response content
* @param int $count trim count
*
* @return string
*/
protected function trimString($string, $count = 1000)
{
$string = trim($string);
if ($count < mb_strlen($string)) {
return mb_substr($string, 0, $count - 3).'...';
}
return $string;
}
/**
* Returns response information string.
*
* @return string
*/
protected function getResponseInfo()
{
$driver = basename(str_replace('\\', '/', get_class($this->driver)));
$info = '+--[ ';
try {
$info .= 'HTTP/1.1 '.$this->driver->getStatusCode().' | ';
} catch (UnsupportedDriverActionException $e) {
// Ignore the status code when not supported
}
$info .= $this->driver->getCurrentUrl().' | '.$driver." ]\n|\n";
return $info;
}
}

View file

@ -0,0 +1,24 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Exception;
/**
* Exception thrown when an expectation on the response text fails.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class ResponseTextException extends ExpectationException
{
protected function getContext()
{
return $this->getDriver()->getText('//html');
}
}

View file

@ -0,0 +1,35 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Exception;
use Behat\Mink\Driver\DriverInterface;
/**
* Exception thrown by drivers when they don't support the requested action.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class UnsupportedDriverActionException extends DriverException
{
/**
* Initializes exception.
*
* @param string $template what is unsupported?
* @param DriverInterface $driver driver instance
* @param \Exception $previous previous exception
*/
public function __construct($template, DriverInterface $driver, \Exception $previous = null)
{
$message = sprintf($template, get_class($driver));
parent::__construct($message, 0, $previous);
}
}

216
web/vendor/behat/mink/src/Mink.php vendored Normal file
View file

@ -0,0 +1,216 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink;
/**
* Mink sessions manager.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class Mink
{
private $defaultSessionName;
/**
* Sessions.
*
* @var Session[]
*/
private $sessions = array();
/**
* Initializes manager.
*
* @param Session[] $sessions
*/
public function __construct(array $sessions = array())
{
foreach ($sessions as $name => $session) {
$this->registerSession($name, $session);
}
}
/**
* Stops all started sessions.
*/
public function __destruct()
{
$this->stopSessions();
}
/**
* Registers new session.
*
* @param string $name
* @param Session $session
*/
public function registerSession($name, Session $session)
{
$name = strtolower($name);
$this->sessions[$name] = $session;
}
/**
* Checks whether session with specified name is registered.
*
* @param string $name
*
* @return Boolean
*/
public function hasSession($name)
{
return isset($this->sessions[strtolower($name)]);
}
/**
* Sets default session name to use.
*
* @param string $name name of the registered session
*
* @throws \InvalidArgumentException
*/
public function setDefaultSessionName($name)
{
$name = strtolower($name);
if (!isset($this->sessions[$name])) {
throw new \InvalidArgumentException(sprintf('Session "%s" is not registered.', $name));
}
$this->defaultSessionName = $name;
}
/**
* Returns default session name or null if none.
*
* @return null|string
*/
public function getDefaultSessionName()
{
return $this->defaultSessionName;
}
/**
* Returns registered session by it's name or active one and automatically starts it if required.
*
* @param string $name session name
*
* @return Session
*
* @throws \InvalidArgumentException If the named session is not registered
*/
public function getSession($name = null)
{
$session = $this->locateSession($name);
// start session if needed
if (!$session->isStarted()) {
$session->start();
}
return $session;
}
/**
* Checks whether a named session (or the default session) has already been started.
*
* @param string $name session name - if null then the default session will be checked
*
* @return bool whether the session has been started
*
* @throws \InvalidArgumentException If the named session is not registered
*/
public function isSessionStarted($name = null)
{
$session = $this->locateSession($name);
return $session->isStarted();
}
/**
* Returns session asserter.
*
* @param Session|string $session session object or name
*
* @return WebAssert
*/
public function assertSession($session = null)
{
if (!($session instanceof Session)) {
$session = $this->getSession($session);
}
return new WebAssert($session);
}
/**
* Resets all started sessions.
*/
public function resetSessions()
{
foreach ($this->sessions as $session) {
if ($session->isStarted()) {
$session->reset();
}
}
}
/**
* Restarts all started sessions.
*/
public function restartSessions()
{
foreach ($this->sessions as $session) {
if ($session->isStarted()) {
$session->restart();
}
}
}
/**
* Stops all started sessions.
*/
public function stopSessions()
{
foreach ($this->sessions as $session) {
if ($session->isStarted()) {
$session->stop();
}
}
}
/**
* Returns the named or default session without starting it.
*
* @param string $name session name
*
* @return Session
*
* @throws \InvalidArgumentException If the named session is not registered
*/
protected function locateSession($name = null)
{
$name = strtolower($name) ?: $this->defaultSessionName;
if (null === $name) {
throw new \InvalidArgumentException('Specify session name to get');
}
if (!isset($this->sessions[$name])) {
throw new \InvalidArgumentException(sprintf('Session "%s" is not registered.', $name));
}
$session = $this->sessions[$name];
return $session;
}
}

View file

@ -0,0 +1,46 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Selector;
use Symfony\Component\CssSelector\CssSelector as CSS;
use Symfony\Component\CssSelector\CssSelectorConverter;
/**
* CSS selector engine. Transforms CSS to XPath.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class CssSelector implements SelectorInterface
{
/**
* Translates CSS into XPath.
*
* @param string|array $locator current selector locator
*
* @return string
*/
public function translateToXPath($locator)
{
if (!is_string($locator)) {
throw new \InvalidArgumentException('The CssSelector expects to get a string as locator');
}
// Symfony 2.8+ API
if (class_exists('Symfony\Component\CssSelector\CssSelectorConverter')) {
$converter = new CssSelectorConverter();
return $converter->toXPath($locator);
}
// old static API for Symfony 2.7 and older
return CSS::toXPath($locator);
}
}

View file

@ -0,0 +1,29 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Selector;
/**
* Exact match selector engine. Like the Named selector engine but ignores partial matches.
*/
class ExactNamedSelector extends NamedSelector
{
public function __construct()
{
$this->registerReplacement('%tagTextMatch%', 'normalize-space(string(.)) = %locator%');
$this->registerReplacement('%valueMatch%', './@value = %locator%');
$this->registerReplacement('%titleMatch%', './@title = %locator%');
$this->registerReplacement('%altMatch%', './@alt = %locator%');
$this->registerReplacement('%relMatch%', './@rel = %locator%');
$this->registerReplacement('%labelAttributeMatch%', './@label = %locator%');
parent::__construct();
}
}

View file

@ -0,0 +1,263 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Selector;
use Behat\Mink\Selector\Xpath\Escaper;
/**
* Named selectors engine. Uses registered XPath selectors to create new expressions.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class NamedSelector implements SelectorInterface
{
private $replacements = array(
// simple replacements
'%lowercaseType%' => "translate(./@type, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')",
'%lowercaseRole%' => "translate(./@role, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')",
'%tagTextMatch%' => 'contains(normalize-space(string(.)), %locator%)',
'%labelTextMatch%' => './@id = //label[%tagTextMatch%]/@for',
'%idMatch%' => './@id = %locator%',
'%valueMatch%' => 'contains(./@value, %locator%)',
'%idOrValueMatch%' => '(%idMatch% or %valueMatch%)',
'%idOrNameMatch%' => '(%idMatch% or ./@name = %locator%)',
'%placeholderMatch%' => './@placeholder = %locator%',
'%titleMatch%' => 'contains(./@title, %locator%)',
'%altMatch%' => 'contains(./@alt, %locator%)',
'%relMatch%' => 'contains(./@rel, %locator%)',
'%labelAttributeMatch%' => 'contains(./@label, %locator%)',
// complex replacements
'%inputTypeWithoutPlaceholderFilter%' => "%lowercaseType% = 'radio' or %lowercaseType% = 'checkbox' or %lowercaseType% = 'file'",
'%fieldFilterWithPlaceholder%' => 'self::input[not(%inputTypeWithoutPlaceholderFilter%)] | self::textarea',
'%fieldMatchWithPlaceholder%' => '(%idOrNameMatch% or %labelTextMatch% or %placeholderMatch%)',
'%fieldMatchWithoutPlaceholder%' => '(%idOrNameMatch% or %labelTextMatch%)',
'%fieldFilterWithoutPlaceholder%' => 'self::input[%inputTypeWithoutPlaceholderFilter%] | self::select',
'%buttonTypeFilter%' => "%lowercaseType% = 'submit' or %lowercaseType% = 'image' or %lowercaseType% = 'button' or %lowercaseType% = 'reset'",
'%notFieldTypeFilter%' => "not(%buttonTypeFilter% or %lowercaseType% = 'hidden')",
'%buttonMatch%' => '%idOrNameMatch% or %valueMatch% or %titleMatch%',
'%linkMatch%' => '(%idMatch% or %tagTextMatch% or %titleMatch% or %relMatch%)',
'%imgAltMatch%' => './/img[%altMatch%]',
);
private $selectors = array(
'fieldset' => <<<XPATH
.//fieldset
[(%idMatch% or .//legend[%tagTextMatch%])]
XPATH
,'field' => <<<XPATH
.//*
[%fieldFilterWithPlaceholder%][%notFieldTypeFilter%][%fieldMatchWithPlaceholder%]
|
.//label[%tagTextMatch%]//.//*[%fieldFilterWithPlaceholder%][%notFieldTypeFilter%]
|
.//*
[%fieldFilterWithoutPlaceholder%][%notFieldTypeFilter%][%fieldMatchWithoutPlaceholder%]
|
.//label[%tagTextMatch%]//.//*[%fieldFilterWithoutPlaceholder%][%notFieldTypeFilter%]
XPATH
,'link' => <<<XPATH
.//a
[./@href][(%linkMatch% or %imgAltMatch%)]
|
.//*
[%lowercaseRole% = 'link'][(%idOrValueMatch% or %titleMatch% or %tagTextMatch%)]
XPATH
,'button' => <<<XPATH
.//input
[%buttonTypeFilter%][(%buttonMatch%)]
|
.//input
[%lowercaseType% = 'image'][%altMatch%]
|
.//button
[(%buttonMatch% or %tagTextMatch%)]
|
.//*
[%lowercaseRole% = 'button'][(%buttonMatch% or %tagTextMatch%)]
XPATH
,'link_or_button' => <<<XPATH
.//a
[./@href][(%linkMatch% or %imgAltMatch%)]
|
.//input
[%buttonTypeFilter%][(%idOrValueMatch% or %titleMatch%)]
|
.//input
[%lowercaseType% = 'image'][%altMatch%]
|
.//button
[(%idOrValueMatch% or %titleMatch% or %tagTextMatch%)]
|
.//*
[(%lowercaseRole% = 'button' or %lowercaseRole% = 'link')][(%idOrValueMatch% or %titleMatch% or %tagTextMatch%)]
XPATH
,'content' => <<<XPATH
./descendant-or-self::*
[%tagTextMatch%]
XPATH
,'select' => <<<XPATH
.//select
[%fieldMatchWithoutPlaceholder%]
|
.//label[%tagTextMatch%]//.//select
XPATH
,'checkbox' => <<<XPATH
.//input
[%lowercaseType% = 'checkbox'][%fieldMatchWithoutPlaceholder%]
|
.//label[%tagTextMatch%]//.//input[%lowercaseType% = 'checkbox']
XPATH
,'radio' => <<<XPATH
.//input
[%lowercaseType% = 'radio'][%fieldMatchWithoutPlaceholder%]
|
.//label[%tagTextMatch%]//.//input[%lowercaseType% = 'radio']
XPATH
,'file' => <<<XPATH
.//input
[%lowercaseType% = 'file'][%fieldMatchWithoutPlaceholder%]
|
.//label[%tagTextMatch%]//.//input[%lowercaseType% = 'file']
XPATH
,'optgroup' => <<<XPATH
.//optgroup
[%labelAttributeMatch%]
XPATH
,'option' => <<<XPATH
.//option
[(./@value = %locator% or %tagTextMatch%)]
XPATH
,'table' => <<<XPATH
.//table
[(%idMatch% or .//caption[%tagTextMatch%])]
XPATH
,'id' => <<<XPATH
.//*[%idMatch%]
XPATH
,'id_or_name' => <<<XPATH
.//*[%idOrNameMatch%]
XPATH
);
private $xpathEscaper;
/**
* Creates selector instance.
*/
public function __construct()
{
$this->xpathEscaper = new Escaper();
foreach ($this->replacements as $from => $to) {
$this->replacements[$from] = strtr($to, $this->replacements);
}
foreach ($this->selectors as $alias => $selector) {
$this->selectors[$alias] = strtr($selector, $this->replacements);
}
}
/**
* Registers new XPath selector with specified name.
*
* @param string $name name for selector
* @param string $xpath xpath expression
*/
public function registerNamedXpath($name, $xpath)
{
$this->selectors[$name] = $xpath;
}
/**
* Translates provided locator into XPath.
*
* @param string|array $locator selector name or array of (selector_name, locator)
*
* @return string
*
* @throws \InvalidArgumentException
*/
public function translateToXPath($locator)
{
if (2 < count($locator)) {
throw new \InvalidArgumentException('NamedSelector expects array(name, locator) as argument');
}
if (2 == count($locator)) {
$selector = $locator[0];
$locator = $locator[1];
} else {
$selector = (string) $locator;
$locator = null;
}
if (!isset($this->selectors[$selector])) {
throw new \InvalidArgumentException(sprintf(
'Unknown named selector provided: "%s". Expected one of (%s)',
$selector,
implode(', ', array_keys($this->selectors))
));
}
$xpath = $this->selectors[$selector];
if (null !== $locator) {
$xpath = strtr($xpath, array('%locator%' => $this->escapeLocator($locator)));
}
return $xpath;
}
/**
* Registers a replacement in the list of replacements.
*
* This method must be called in the constructor before calling the parent constructor.
*
* @param string $from
* @param string $to
*/
protected function registerReplacement($from, $to)
{
$this->replacements[$from] = $to;
}
private function escapeLocator($locator)
{
// If the locator looks like an escaped one, don't escape it again for BC reasons.
if (
preg_match('/^\'[^\']*+\'$/', $locator)
|| (false !== strpos($locator, '\'') && preg_match('/^"[^"]*+"$/', $locator))
|| ((8 < $length = strlen($locator)) && 'concat(' === substr($locator, 0, 7) && ')' === $locator[$length - 1])
) {
@trigger_error(
'Passing an escaped locator to the named selector is deprecated as of 1.7 and will be removed in 2.0.'
.' Pass the raw value instead.',
E_USER_DEPRECATED
);
return $locator;
}
return $this->xpathEscaper->escapeLiteral($locator);
}
}

View file

@ -0,0 +1,31 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Selector;
/**
* Named selectors engine. Uses registered XPath selectors to create new expressions.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class PartialNamedSelector extends NamedSelector
{
public function __construct()
{
$this->registerReplacement('%tagTextMatch%', 'contains(normalize-space(string(.)), %locator%)');
$this->registerReplacement('%valueMatch%', 'contains(./@value, %locator%)');
$this->registerReplacement('%titleMatch%', 'contains(./@title, %locator%)');
$this->registerReplacement('%altMatch%', 'contains(./@alt, %locator%)');
$this->registerReplacement('%relMatch%', 'contains(./@rel, %locator%)');
$this->registerReplacement('%labelAttributeMatch%', 'contains(./@label, %locator%)');
parent::__construct();
}
}

View file

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Selector;
/**
* Mink selector engine interface.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
interface SelectorInterface
{
/**
* Translates provided locator into XPath.
*
* @param string|array $locator current selector locator
*
* @return string
*/
public function translateToXPath($locator);
}

View file

@ -0,0 +1,135 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Selector;
use Behat\Mink\Selector\Xpath\Escaper;
/**
* Selectors handler.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class SelectorsHandler
{
private $selectors;
private $escaper;
/**
* Initializes selectors handler.
*
* @param SelectorInterface[] $selectors default selectors to register
*/
public function __construct(array $selectors = array())
{
$this->escaper = new Escaper();
$this->registerSelector('named_partial', new PartialNamedSelector());
$this->registerSelector('named_exact', new ExactNamedSelector());
$this->registerSelector('css', new CssSelector());
foreach ($selectors as $name => $selector) {
$this->registerSelector($name, $selector);
}
}
/**
* Registers new selector engine with specified name.
*
* @param string $name selector engine name
* @param SelectorInterface $selector selector engine instance
*/
public function registerSelector($name, SelectorInterface $selector)
{
$this->selectors[$name] = $selector;
}
/**
* Checks whether selector with specified name is registered on handler.
*
* @param string $name selector engine name
*
* @return Boolean
*/
public function isSelectorRegistered($name)
{
return isset($this->selectors[$name]);
}
/**
* Returns selector engine with specified name.
*
* @param string $name selector engine name
*
* @return SelectorInterface
*
* @throws \InvalidArgumentException
*/
public function getSelector($name)
{
if ('named' === $name) {
@trigger_error(
'Using the "named" selector directly from the handler is deprecated as of 1.6 and will be removed in 2.0.'
.' Use the "named_partial" or use the "named" selector through the Element API instead.',
E_USER_DEPRECATED
);
$name = 'named_partial';
}
if (!$this->isSelectorRegistered($name)) {
throw new \InvalidArgumentException("Selector \"$name\" is not registered.");
}
return $this->selectors[$name];
}
/**
* Translates selector with specified name to XPath.
*
* @param string $selector selector engine name (registered)
* @param string|array $locator selector locator (an array or a string depending of the selector being used)
*
* @return string
*/
public function selectorToXpath($selector, $locator)
{
if ('xpath' === $selector) {
if (!is_string($locator)) {
throw new \InvalidArgumentException('The xpath selector expects to get a string as locator');
}
return $locator;
}
return $this->getSelector($selector)->translateToXPath($locator);
}
/**
* Translates string to XPath literal.
*
* @deprecated since Mink 1.7. Use \Behat\Mink\Selector\Xpath\Escaper::escapeLiteral when building Xpath
* or pass the unescaped value when using the named selector.
*
* @param string $s
*
* @return string
*/
public function xpathLiteral($s)
{
@trigger_error(
'The '.__METHOD__.' method is deprecated as of 1.7 and will be removed in 2.0.'
.' Use \Behat\Mink\Selector\Xpath\Escaper::escapeLiteral instead when building Xpath'
.' or pass the unescaped value when using the named selector.',
E_USER_DEPRECATED
);
return $this->escaper->escapeLiteral($s);
}
}

View file

@ -0,0 +1,52 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Selector\Xpath;
/**
* XPath escaper.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class Escaper
{
/**
* Escapes the string as a XPath literal.
*
* @param string $s
*
* @return string
*/
public function escapeLiteral($s)
{
if (false === strpos($s, "'")) {
return sprintf("'%s'", $s);
}
if (false === strpos($s, '"')) {
return sprintf('"%s"', $s);
}
$string = $s;
$parts = array();
while (true) {
if (false !== $pos = strpos($string, "'")) {
$parts[] = sprintf("'%s'", substr($string, 0, $pos));
$parts[] = "\"'\"";
$string = substr($string, $pos + 1);
} else {
$parts[] = "'$string'";
break;
}
}
return sprintf('concat(%s)', implode($parts, ','));
}
}

View file

@ -0,0 +1,69 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink\Selector\Xpath;
/**
* XPath manipulation utility.
*
* @author Graham Bates
* @author Christophe Coevoet <stof@notk.org>
*/
class Manipulator
{
/**
* Regex to find union operators not inside brackets.
*/
const UNION_PATTERN = '/\|(?![^\[]*\])/';
/**
* Prepends the XPath prefix to the given XPath.
*
* The returned XPath will match elements matching the XPath inside an element
* matching the prefix.
*
* @param string $xpath
* @param string $prefix
*
* @return string
*/
public function prepend($xpath, $prefix)
{
$expressions = array();
// If the xpath prefix contains a union we need to wrap it in parentheses.
if (preg_match(self::UNION_PATTERN, $prefix)) {
$prefix = '('.$prefix.')';
}
// Split any unions into individual expressions.
foreach (preg_split(self::UNION_PATTERN, $xpath) as $expression) {
$expression = trim($expression);
$parenthesis = '';
// If the union is inside some braces, we need to preserve the opening braces and apply
// the prefix only inside it.
if (preg_match('/^[\(\s*]+/', $expression, $matches)) {
$parenthesis = $matches[0];
$expression = substr($expression, strlen($parenthesis));
}
// add prefix before element selector
if (0 === strpos($expression, '/')) {
$expression = $prefix.$expression;
} else {
$expression = $prefix.'/'.$expression;
}
$expressions[] = $parenthesis.$expression;
}
return implode(' | ', $expressions);
}
}

373
web/vendor/behat/mink/src/Session.php vendored Normal file
View file

@ -0,0 +1,373 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink;
use Behat\Mink\Driver\DriverInterface;
use Behat\Mink\Selector\SelectorsHandler;
use Behat\Mink\Element\DocumentElement;
/**
* Mink session.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class Session
{
private $driver;
private $page;
private $selectorsHandler;
/**
* Initializes session.
*
* @param DriverInterface $driver
* @param SelectorsHandler $selectorsHandler
*/
public function __construct(DriverInterface $driver, SelectorsHandler $selectorsHandler = null)
{
$driver->setSession($this);
if (null === $selectorsHandler) {
$selectorsHandler = new SelectorsHandler();
}
$this->driver = $driver;
$this->selectorsHandler = $selectorsHandler;
$this->page = new DocumentElement($this);
}
/**
* Checks whether session (driver) was started.
*
* @return Boolean
*/
public function isStarted()
{
return $this->driver->isStarted();
}
/**
* Starts session driver.
*
* Calling any action before visiting a page is an undefined behavior.
* The only supported method calls on a fresh driver are
* - visit()
* - setRequestHeader()
* - setBasicAuth()
* - reset()
* - stop()
*/
public function start()
{
$this->driver->start();
}
/**
* Stops session driver.
*/
public function stop()
{
$this->driver->stop();
}
/**
* Restart session driver.
*/
public function restart()
{
$this->driver->stop();
$this->driver->start();
}
/**
* Reset session driver state.
*
* Calling any action before visiting a page is an undefined behavior.
* The only supported method calls on a fresh driver are
* - visit()
* - setRequestHeader()
* - setBasicAuth()
* - reset()
* - stop()
*/
public function reset()
{
$this->driver->reset();
}
/**
* Returns session driver.
*
* @return DriverInterface
*/
public function getDriver()
{
return $this->driver;
}
/**
* Returns page element.
*
* @return DocumentElement
*/
public function getPage()
{
return $this->page;
}
/**
* Returns selectors handler.
*
* @return SelectorsHandler
*/
public function getSelectorsHandler()
{
return $this->selectorsHandler;
}
/**
* Visit specified URL.
*
* @param string $url url of the page
*/
public function visit($url)
{
$this->driver->visit($url);
}
/**
* Sets HTTP Basic authentication parameters.
*
* @param string|Boolean $user user name or false to disable authentication
* @param string $password password
*/
public function setBasicAuth($user, $password = '')
{
$this->driver->setBasicAuth($user, $password);
}
/**
* Sets specific request header.
*
* @param string $name
* @param string $value
*/
public function setRequestHeader($name, $value)
{
$this->driver->setRequestHeader($name, $value);
}
/**
* Returns all response headers.
*
* @return array
*/
public function getResponseHeaders()
{
return $this->driver->getResponseHeaders();
}
/**
* Returns specific response header.
*
* @param string $name
*
* @return string|null
*/
public function getResponseHeader($name)
{
$headers = $this->driver->getResponseHeaders();
$name = strtolower($name);
$headers = array_change_key_case($headers, CASE_LOWER);
if (!isset($headers[$name])) {
return null;
}
return is_array($headers[$name]) ? $headers[$name][0] : $headers[$name];
}
/**
* Sets cookie.
*
* @param string $name
* @param string $value
*/
public function setCookie($name, $value = null)
{
$this->driver->setCookie($name, $value);
}
/**
* Returns cookie by name.
*
* @param string $name
*
* @return string|null
*/
public function getCookie($name)
{
return $this->driver->getCookie($name);
}
/**
* Returns response status code.
*
* @return int
*/
public function getStatusCode()
{
return $this->driver->getStatusCode();
}
/**
* Returns current URL address.
*
* @return string
*/
public function getCurrentUrl()
{
return $this->driver->getCurrentUrl();
}
/**
* Capture a screenshot of the current window.
*
* @return string screenshot of MIME type image/* depending
* on driver (e.g., image/png, image/jpeg)
*/
public function getScreenshot()
{
return $this->driver->getScreenshot();
}
/**
* Return the names of all open windows.
*
* @return array Array of all open window's names.
*/
public function getWindowNames()
{
return $this->driver->getWindowNames();
}
/**
* Return the name of the currently active window.
*
* @return string The name of the current window.
*/
public function getWindowName()
{
return $this->driver->getWindowName();
}
/**
* Reloads current session page.
*/
public function reload()
{
$this->driver->reload();
}
/**
* Moves backward 1 page in history.
*/
public function back()
{
$this->driver->back();
}
/**
* Moves forward 1 page in history.
*/
public function forward()
{
$this->driver->forward();
}
/**
* Switches to specific browser window.
*
* @param string $name window name (null for switching back to main window)
*/
public function switchToWindow($name = null)
{
$this->driver->switchToWindow($name);
}
/**
* Switches to specific iFrame.
*
* @param string $name iframe name (null for switching back)
*/
public function switchToIFrame($name = null)
{
$this->driver->switchToIFrame($name);
}
/**
* Execute JS in browser.
*
* @param string $script javascript
*/
public function executeScript($script)
{
$this->driver->executeScript($script);
}
/**
* Execute JS in browser and return it's response.
*
* @param string $script javascript
*
* @return string
*/
public function evaluateScript($script)
{
return $this->driver->evaluateScript($script);
}
/**
* Waits some time or until JS condition turns true.
*
* @param int $time time in milliseconds
* @param string $condition JS condition
*
* @return bool
*/
public function wait($time, $condition = 'false')
{
return $this->driver->wait($time, $condition);
}
/**
* Set the dimensions of the window.
*
* @param int $width set the window width, measured in pixels
* @param int $height set the window height, measured in pixels
* @param string $name window name (null for the main window)
*/
public function resizeWindow($width, $height, $name = null)
{
$this->driver->resizeWindow($width, $height, $name);
}
/**
* Maximize the window if it is not maximized already.
*
* @param string $name window name (null for the main window)
*/
public function maximizeWindow($name = null)
{
$this->driver->maximizeWindow($name);
}
}

849
web/vendor/behat/mink/src/WebAssert.php vendored Normal file
View file

@ -0,0 +1,849 @@
<?php
/*
* This file is part of the Mink package.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Behat\Mink;
use Behat\Mink\Element\Element;
use Behat\Mink\Element\ElementInterface;
use Behat\Mink\Element\NodeElement;
use Behat\Mink\Element\TraversableElement;
use Behat\Mink\Exception\ElementNotFoundException;
use Behat\Mink\Exception\ExpectationException;
use Behat\Mink\Exception\ResponseTextException;
use Behat\Mink\Exception\ElementHtmlException;
use Behat\Mink\Exception\ElementTextException;
/**
* Mink web assertions tool.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class WebAssert
{
protected $session;
/**
* Initializes assertion engine.
*
* @param Session $session
*/
public function __construct(Session $session)
{
$this->session = $session;
}
/**
* Checks that current session address is equals to provided one.
*
* @param string $page
*
* @throws ExpectationException
*/
public function addressEquals($page)
{
$expected = $this->cleanUrl($page);
$actual = $this->getCurrentUrlPath();
$this->assert($actual === $expected, sprintf('Current page is "%s", but "%s" expected.', $actual, $expected));
}
/**
* Checks that current session address is not equals to provided one.
*
* @param string $page
*
* @throws ExpectationException
*/
public function addressNotEquals($page)
{
$expected = $this->cleanUrl($page);
$actual = $this->getCurrentUrlPath();
$this->assert($actual !== $expected, sprintf('Current page is "%s", but should not be.', $actual));
}
/**
* Checks that current session address matches regex.
*
* @param string $regex
*
* @throws ExpectationException
*/
public function addressMatches($regex)
{
$actual = $this->getCurrentUrlPath();
$message = sprintf('Current page "%s" does not match the regex "%s".', $actual, $regex);
$this->assert((bool) preg_match($regex, $actual), $message);
}
/**
* Checks that specified cookie exists and its value equals to a given one.
*
* @param string $name cookie name
* @param string $value cookie value
*
* @throws ExpectationException
*/
public function cookieEquals($name, $value)
{
$this->cookieExists($name);
$actualValue = $this->session->getCookie($name);
$message = sprintf('Cookie "%s" value is "%s", but should be "%s".', $name, $actualValue, $value);
$this->assert($actualValue == $value, $message);
}
/**
* Checks that specified cookie exists.
*
* @param string $name cookie name
*
* @throws ExpectationException
*/
public function cookieExists($name)
{
$message = sprintf('Cookie "%s" is not set, but should be.', $name);
$this->assert($this->session->getCookie($name) !== null, $message);
}
/**
* Checks that current response code equals to provided one.
*
* @param int $code
*
* @throws ExpectationException
*/
public function statusCodeEquals($code)
{
$actual = $this->session->getStatusCode();
$message = sprintf('Current response status code is %d, but %d expected.', $actual, $code);
$this->assert(intval($code) === intval($actual), $message);
}
/**
* Checks that current response code not equals to provided one.
*
* @param int $code
*
* @throws ExpectationException
*/
public function statusCodeNotEquals($code)
{
$actual = $this->session->getStatusCode();
$message = sprintf('Current response status code is %d, but should not be.', $actual);
$this->assert(intval($code) !== intval($actual), $message);
}
/**
* Checks that current response header equals value.
*
* @param string $name
* @param string $value
*
* @throws ExpectationException
*/
public function responseHeaderEquals($name, $value)
{
$actual = $this->session->getResponseHeader($name);
$message = sprintf('Current response header "%s" is "%s", but "%s" expected.', $name, $actual, $value);
$this->assert($value === $actual, $message);
}
/**
* Checks that current response header does not equal value.
*
* @param string $name
* @param string $value
*
* @throws ExpectationException
*/
public function responseHeaderNotEquals($name, $value)
{
$actual = $this->session->getResponseHeader($name);
$message = sprintf('Current response header "%s" is "%s", but should not be.', $name, $actual, $value);
$this->assert($value !== $actual, $message);
}
/**
* Checks that current response header contains value.
*
* @param string $name
* @param string $value
*
* @throws ExpectationException
*/
public function responseHeaderContains($name, $value)
{
$actual = $this->session->getResponseHeader($name);
$message = sprintf('The text "%s" was not found anywhere in the "%s" response header.', $value, $name);
$this->assert(false !== stripos($actual, $value), $message);
}
/**
* Checks that current response header does not contain value.
*
* @param string $name
* @param string $value
*
* @throws ExpectationException
*/
public function responseHeaderNotContains($name, $value)
{
$actual = $this->session->getResponseHeader($name);
$message = sprintf('The text "%s" was found in the "%s" response header, but it should not.', $value, $name);
$this->assert(false === stripos($actual, $value), $message);
}
/**
* Checks that current response header matches regex.
*
* @param string $name
* @param string $regex
*
* @throws ExpectationException
*/
public function responseHeaderMatches($name, $regex)
{
$actual = $this->session->getResponseHeader($name);
$message = sprintf('The pattern "%s" was not found anywhere in the "%s" response header.', $regex, $name);
$this->assert((bool) preg_match($regex, $actual), $message);
}
/**
* Checks that current response header does not match regex.
*
* @param string $name
* @param string $regex
*
* @throws ExpectationException
*/
public function responseHeaderNotMatches($name, $regex)
{
$actual = $this->session->getResponseHeader($name);
$message = sprintf(
'The pattern "%s" was found in the text of the "%s" response header, but it should not.',
$regex,
$name
);
$this->assert(!preg_match($regex, $actual), $message);
}
/**
* Checks that current page contains text.
*
* @param string $text
*
* @throws ResponseTextException
*/
public function pageTextContains($text)
{
$actual = $this->session->getPage()->getText();
$actual = preg_replace('/\s+/u', ' ', $actual);
$regex = '/'.preg_quote($text, '/').'/ui';
$message = sprintf('The text "%s" was not found anywhere in the text of the current page.', $text);
$this->assertResponseText((bool) preg_match($regex, $actual), $message);
}
/**
* Checks that current page does not contains text.
*
* @param string $text
*
* @throws ResponseTextException
*/
public function pageTextNotContains($text)
{
$actual = $this->session->getPage()->getText();
$actual = preg_replace('/\s+/u', ' ', $actual);
$regex = '/'.preg_quote($text, '/').'/ui';
$message = sprintf('The text "%s" appears in the text of this page, but it should not.', $text);
$this->assertResponseText(!preg_match($regex, $actual), $message);
}
/**
* Checks that current page text matches regex.
*
* @param string $regex
*
* @throws ResponseTextException
*/
public function pageTextMatches($regex)
{
$actual = $this->session->getPage()->getText();
$message = sprintf('The pattern %s was not found anywhere in the text of the current page.', $regex);
$this->assertResponseText((bool) preg_match($regex, $actual), $message);
}
/**
* Checks that current page text does not matches regex.
*
* @param string $regex
*
* @throws ResponseTextException
*/
public function pageTextNotMatches($regex)
{
$actual = $this->session->getPage()->getText();
$message = sprintf('The pattern %s was found in the text of the current page, but it should not.', $regex);
$this->assertResponseText(!preg_match($regex, $actual), $message);
}
/**
* Checks that page HTML (response content) contains text.
*
* @param string $text
*
* @throws ExpectationException
*/
public function responseContains($text)
{
$actual = $this->session->getPage()->getContent();
$regex = '/'.preg_quote($text, '/').'/ui';
$message = sprintf('The string "%s" was not found anywhere in the HTML response of the current page.', $text);
$this->assert((bool) preg_match($regex, $actual), $message);
}
/**
* Checks that page HTML (response content) does not contains text.
*
* @param string $text
*
* @throws ExpectationException
*/
public function responseNotContains($text)
{
$actual = $this->session->getPage()->getContent();
$regex = '/'.preg_quote($text, '/').'/ui';
$message = sprintf('The string "%s" appears in the HTML response of this page, but it should not.', $text);
$this->assert(!preg_match($regex, $actual), $message);
}
/**
* Checks that page HTML (response content) matches regex.
*
* @param string $regex
*
* @throws ExpectationException
*/
public function responseMatches($regex)
{
$actual = $this->session->getPage()->getContent();
$message = sprintf('The pattern %s was not found anywhere in the HTML response of the page.', $regex);
$this->assert((bool) preg_match($regex, $actual), $message);
}
/**
* Checks that page HTML (response content) does not matches regex.
*
* @param $regex
*
* @throws ExpectationException
*/
public function responseNotMatches($regex)
{
$actual = $this->session->getPage()->getContent();
$message = sprintf('The pattern %s was found in the HTML response of the page, but it should not.', $regex);
$this->assert(!preg_match($regex, $actual), $message);
}
/**
* Checks that there is specified number of specific elements on the page.
*
* @param string $selectorType element selector type (css, xpath)
* @param string|array $selector element selector
* @param int $count expected count
* @param ElementInterface $container document to check against
*
* @throws ExpectationException
*/
public function elementsCount($selectorType, $selector, $count, ElementInterface $container = null)
{
$container = $container ?: $this->session->getPage();
$nodes = $container->findAll($selectorType, $selector);
$message = sprintf(
'%d %s found on the page, but should be %d.',
count($nodes),
$this->getMatchingElementRepresentation($selectorType, $selector, count($nodes) !== 1),
$count
);
$this->assert(intval($count) === count($nodes), $message);
}
/**
* Checks that specific element exists on the current page.
*
* @param string $selectorType element selector type (css, xpath)
* @param string|array $selector element selector
* @param ElementInterface $container document to check against
*
* @return NodeElement
*
* @throws ElementNotFoundException
*/
public function elementExists($selectorType, $selector, ElementInterface $container = null)
{
$container = $container ?: $this->session->getPage();
$node = $container->find($selectorType, $selector);
if (null === $node) {
if (is_array($selector)) {
$selector = implode(' ', $selector);
}
throw new ElementNotFoundException($this->session->getDriver(), 'element', $selectorType, $selector);
}
return $node;
}
/**
* Checks that specific element does not exists on the current page.
*
* @param string $selectorType element selector type (css, xpath)
* @param string|array $selector element selector
* @param ElementInterface $container document to check against
*
* @throws ExpectationException
*/
public function elementNotExists($selectorType, $selector, ElementInterface $container = null)
{
$container = $container ?: $this->session->getPage();
$node = $container->find($selectorType, $selector);
$message = sprintf(
'An %s appears on this page, but it should not.',
$this->getMatchingElementRepresentation($selectorType, $selector)
);
$this->assert(null === $node, $message);
}
/**
* Checks that specific element contains text.
*
* @param string $selectorType element selector type (css, xpath)
* @param string|array $selector element selector
* @param string $text expected text
*
* @throws ElementTextException
*/
public function elementTextContains($selectorType, $selector, $text)
{
$element = $this->elementExists($selectorType, $selector);
$actual = $element->getText();
$regex = '/'.preg_quote($text, '/').'/ui';
$message = sprintf(
'The text "%s" was not found in the text of the %s.',
$text,
$this->getMatchingElementRepresentation($selectorType, $selector)
);
$this->assertElementText((bool) preg_match($regex, $actual), $message, $element);
}
/**
* Checks that specific element does not contains text.
*
* @param string $selectorType element selector type (css, xpath)
* @param string|array $selector element selector
* @param string $text expected text
*
* @throws ElementTextException
*/
public function elementTextNotContains($selectorType, $selector, $text)
{
$element = $this->elementExists($selectorType, $selector);
$actual = $element->getText();
$regex = '/'.preg_quote($text, '/').'/ui';
$message = sprintf(
'The text "%s" appears in the text of the %s, but it should not.',
$text,
$this->getMatchingElementRepresentation($selectorType, $selector)
);
$this->assertElementText(!preg_match($regex, $actual), $message, $element);
}
/**
* Checks that specific element contains HTML.
*
* @param string $selectorType element selector type (css, xpath)
* @param string|array $selector element selector
* @param string $html expected text
*
* @throws ElementHtmlException
*/
public function elementContains($selectorType, $selector, $html)
{
$element = $this->elementExists($selectorType, $selector);
$actual = $element->getHtml();
$regex = '/'.preg_quote($html, '/').'/ui';
$message = sprintf(
'The string "%s" was not found in the HTML of the %s.',
$html,
$this->getMatchingElementRepresentation($selectorType, $selector)
);
$this->assertElement((bool) preg_match($regex, $actual), $message, $element);
}
/**
* Checks that specific element does not contains HTML.
*
* @param string $selectorType element selector type (css, xpath)
* @param string|array $selector element selector
* @param string $html expected text
*
* @throws ElementHtmlException
*/
public function elementNotContains($selectorType, $selector, $html)
{
$element = $this->elementExists($selectorType, $selector);
$actual = $element->getHtml();
$regex = '/'.preg_quote($html, '/').'/ui';
$message = sprintf(
'The string "%s" appears in the HTML of the %s, but it should not.',
$html,
$this->getMatchingElementRepresentation($selectorType, $selector)
);
$this->assertElement(!preg_match($regex, $actual), $message, $element);
}
/**
* Checks that an attribute exists in an element.
*
* @param string $selectorType
* @param string|array $selector
* @param string $attribute
*
* @return NodeElement
*
* @throws ElementHtmlException
*/
public function elementAttributeExists($selectorType, $selector, $attribute)
{
$element = $this->elementExists($selectorType, $selector);
$message = sprintf(
'The attribute "%s" was not found in the %s.',
$attribute,
$this->getMatchingElementRepresentation($selectorType, $selector)
);
$this->assertElement($element->hasAttribute($attribute), $message, $element);
return $element;
}
/**
* Checks that an attribute of a specific elements contains text.
*
* @param string $selectorType
* @param string|array $selector
* @param string $attribute
* @param string $text
*
* @throws ElementHtmlException
*/
public function elementAttributeContains($selectorType, $selector, $attribute, $text)
{
$element = $this->elementAttributeExists($selectorType, $selector, $attribute);
$actual = $element->getAttribute($attribute);
$regex = '/'.preg_quote($text, '/').'/ui';
$message = sprintf(
'The text "%s" was not found in the attribute "%s" of the %s.',
$text,
$attribute,
$this->getMatchingElementRepresentation($selectorType, $selector)
);
$this->assertElement((bool) preg_match($regex, $actual), $message, $element);
}
/**
* Checks that an attribute of a specific elements does not contain text.
*
* @param string $selectorType
* @param string|array $selector
* @param string $attribute
* @param string $text
*
* @throws ElementHtmlException
*/
public function elementAttributeNotContains($selectorType, $selector, $attribute, $text)
{
$element = $this->elementAttributeExists($selectorType, $selector, $attribute);
$actual = $element->getAttribute($attribute);
$regex = '/'.preg_quote($text, '/').'/ui';
$message = sprintf(
'The text "%s" was found in the attribute "%s" of the %s.',
$text,
$attribute,
$this->getMatchingElementRepresentation($selectorType, $selector)
);
$this->assertElement(!preg_match($regex, $actual), $message, $element);
}
/**
* Checks that specific field exists on the current page.
*
* @param string $field field id|name|label|value
* @param TraversableElement $container document to check against
*
* @return NodeElement
*
* @throws ElementNotFoundException
*/
public function fieldExists($field, TraversableElement $container = null)
{
$container = $container ?: $this->session->getPage();
$node = $container->findField($field);
if (null === $node) {
throw new ElementNotFoundException($this->session->getDriver(), 'form field', 'id|name|label|value', $field);
}
return $node;
}
/**
* Checks that specific field does not exists on the current page.
*
* @param string $field field id|name|label|value
* @param TraversableElement $container document to check against
*
* @throws ExpectationException
*/
public function fieldNotExists($field, TraversableElement $container = null)
{
$container = $container ?: $this->session->getPage();
$node = $container->findField($field);
$this->assert(null === $node, sprintf('A field "%s" appears on this page, but it should not.', $field));
}
/**
* Checks that specific field have provided value.
*
* @param string $field field id|name|label|value
* @param string $value field value
* @param TraversableElement $container document to check against
*
* @throws ExpectationException
*/
public function fieldValueEquals($field, $value, TraversableElement $container = null)
{
$node = $this->fieldExists($field, $container);
$actual = $node->getValue();
$regex = '/^'.preg_quote($value, '/').'$/ui';
$message = sprintf('The field "%s" value is "%s", but "%s" expected.', $field, $actual, $value);
$this->assert((bool) preg_match($regex, $actual), $message);
}
/**
* Checks that specific field have provided value.
*
* @param string $field field id|name|label|value
* @param string $value field value
* @param TraversableElement $container document to check against
*
* @throws ExpectationException
*/
public function fieldValueNotEquals($field, $value, TraversableElement $container = null)
{
$node = $this->fieldExists($field, $container);
$actual = $node->getValue();
$regex = '/^'.preg_quote($value, '/').'$/ui';
$message = sprintf('The field "%s" value is "%s", but it should not be.', $field, $actual);
$this->assert(!preg_match($regex, $actual), $message);
}
/**
* Checks that specific checkbox is checked.
*
* @param string $field field id|name|label|value
* @param TraversableElement $container document to check against
*
* @throws ExpectationException
*/
public function checkboxChecked($field, TraversableElement $container = null)
{
$node = $this->fieldExists($field, $container);
$this->assert($node->isChecked(), sprintf('Checkbox "%s" is not checked, but it should be.', $field));
}
/**
* Checks that specific checkbox is unchecked.
*
* @param string $field field id|name|label|value
* @param TraversableElement $container document to check against
*
* @throws ExpectationException
*/
public function checkboxNotChecked($field, TraversableElement $container = null)
{
$node = $this->fieldExists($field, $container);
$this->assert(!$node->isChecked(), sprintf('Checkbox "%s" is checked, but it should not be.', $field));
}
/**
* Gets current url of the page.
*
* @return string
*/
protected function getCurrentUrlPath()
{
return $this->cleanUrl($this->session->getCurrentUrl());
}
/**
* Trims scriptname from the URL.
*
* @param string $url
*
* @return string
*/
protected function cleanUrl($url)
{
$parts = parse_url($url);
$fragment = empty($parts['fragment']) ? '' : '#'.$parts['fragment'];
$path = empty($parts['path']) ? '/' : $parts['path'];
return preg_replace('/^\/[^\.\/]+\.php\//', '/', $path).$fragment;
}
/**
* Asserts a condition.
*
* @param bool $condition
* @param string $message Failure message
*
* @throws ExpectationException when the condition is not fulfilled
*/
private function assert($condition, $message)
{
if ($condition) {
return;
}
throw new ExpectationException($message, $this->session->getDriver());
}
/**
* Asserts a condition involving the response text.
*
* @param bool $condition
* @param string $message Failure message
*
* @throws ResponseTextException when the condition is not fulfilled
*/
private function assertResponseText($condition, $message)
{
if ($condition) {
return;
}
throw new ResponseTextException($message, $this->session->getDriver());
}
/**
* Asserts a condition on an element.
*
* @param bool $condition
* @param string $message Failure message
* @param Element $element
*
* @throws ElementHtmlException when the condition is not fulfilled
*/
private function assertElement($condition, $message, Element $element)
{
if ($condition) {
return;
}
throw new ElementHtmlException($message, $this->session->getDriver(), $element);
}
/**
* Asserts a condition involving the text of an element.
*
* @param bool $condition
* @param string $message Failure message
* @param Element $element
*
* @throws ElementTextException when the condition is not fulfilled
*/
private function assertElementText($condition, $message, Element $element)
{
if ($condition) {
return;
}
throw new ElementTextException($message, $this->session->getDriver(), $element);
}
/**
* @param string $selectorType
* @param string|array $selector
* @param bool $plural
*
* @return string
*/
private function getMatchingElementRepresentation($selectorType, $selector, $plural = false)
{
$pluralization = $plural ? 's' : '';
if (in_array($selectorType, array('named', 'named_exact', 'named_partial'))
&& is_array($selector) && 2 === count($selector)
) {
return sprintf('%s%s matching locator "%s"', $selector[0], $pluralization, $selector[1]);
}
if (is_array($selector)) {
$selector = implode(' ', $selector);
}
return sprintf('element%s matching %s "%s"', $pluralization, $selectorType, $selector);
}
}