Update to drupal 8.0.0-rc1. For more information, see https://www.drupal.org/node/2582663

This commit is contained in:
Greg Anderson 2015-10-08 11:40:12 -07:00
parent eb34d130a8
commit f32e58e4b1
8476 changed files with 211648 additions and 170042 deletions

5
vendor/behat/mink/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
*.tgz
*.phar
phpunit.xml
composer.lock
vendor

28
vendor/behat/mink/.travis.yml vendored Normal file
View file

@ -0,0 +1,28 @@
language: php
sudo: false
php: [5.3, 5.4, 5.5, 5.6, 7.0, hhvm]
matrix:
fast_finish: true
include:
- php: 5.3
env: COMPOSER_FLAGS='--prefer-lowest --prefer-stable' SYMFONY_DEPRECATIONS_HELPER=weak
allow_failures:
- php: 7.0
cache:
directories:
- $HOME/.composer/cache/files
before_install:
- composer self-update
install:
- composer update $COMPOSER_FLAGS
script: phpunit -v --coverage-clover=coverage.clover
after_script:
- if [[ "7.0" != "$TRAVIS_PHP_VERSION" && "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi

297
vendor/behat/mink/CHANGES.md vendored Normal file
View file

@ -0,0 +1,297 @@
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
vendor/behat/mink/CONTRIBUTING.md vendored Normal file
View file

@ -0,0 +1,22 @@
# Contributing
Mink is an open source, community-driven project. If you'd like to contribute, feel free to do this, but remember to follow these few simple rules:
## Submitting an issues
- __Driver-related__ issues must be reported in the corresponding driver repository
- A reproducible example is required for every bug report, otherwise it will most probably be __closed without warning__
- If you are going to make a big, substantial change, let's discuss it first
## Working with Pull Requests
1. Create your feature addition or a bug fix branch based on `master` branch in your repository's fork.
2. Make necessary changes, but __don't mix__ code reformatting with code changes on topic.
3. Add tests for those changes (please look into `tests/` folder for some examples). This is important so we don't break it in a future version unintentionally.
4. Commit your code, but do not mess with `CHANGES.md`.
5. Squash your commits by topic to preserve a clean and readable log.
6. Create Pull Request.
# Running tests
Make sure that you don't break anything with your changes by running:
```bash
$> phpunit
```

22
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
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
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"
},
"require-dev": {
"symfony/phpunit-bridge": "~2.7"
},
"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,96 @@
Mink Driver testsuite
=====================
This is the common testsuite for Mink drivers to ensure consistency among implementations.
Usage
-----
The testsuite of a driver should be based as follow:
```json
{
"require": {
"behat/mink": "~1.6@dev"
},
"autoload-dev": {
"psr-4": {
"Acme\\MyDriver\\Tests\\": "tests"
}
}
}
```
```xml
<!-- phpunit.xml.dist -->
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="vendor/behat/mink/driver-testsuite/bootstrap.php">
<php>
<var name="driver_config_factory" value="Acme\MyDriver\Tests\Config::getInstance" />
<server name="WEB_FIXTURES_HOST" value="http://test.mink.dev" />
</php>
<testsuites>
<testsuite name="Functional tests">
<directory>vendor/behat/mink/driver-testsuite/tests</directory>
</testsuite>
<!-- if needed to add more tests -->
<testsuite name="Driver tests">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src</directory>
</whitelist>
</filter>
</phpunit>
```
Then create the driver config for the testsuite:
```php
// tests/Config.php
namespace Acme\MyDriver\Tests;
use Behat\Mink\Tests\Driver\AbstractConfig;
class Config extends AbstractConfig
{
/**
* Creates an instance of the config.
*
* This is the callable registered as a php variable in the phpunit.xml config file.
* It could be outside the class but this is convenient.
*/
public static function getInstance()
{
return new self();
}
/**
* Creates driver instance.
*
* @return \Behat\Mink\Driver\DriverInterface
*/
public function createDriver()
{
return new \Acme\MyDriver\MyDriver();
}
}
```
Some other methods are available in the AbstractConfig which can be overwritten to adapt the testsuite to
the needs of the driver (skipping some tests for instance).
Adding Driver-specific Tests
----------------------------
When adding extra test cases specific to the driver, either use your own namespace or put them in the
``Behat\Mink\Tests\Driver\Custom`` subnamespace to ensure that you will not create conflicts with test cases
added in the driver testsuite in the future.

View file

@ -0,0 +1,28 @@
<?php
$file = __DIR__.'/../../../autoload.php';
if (!file_exists($file)) {
echo PHP_EOL.'The Mink driver testsuite expects Mink to be installed as a composer dependency of your project'.PHP_EOL;
exit(1);
}
/** @var \Composer\Autoload\ClassLoader $loader */
$loader = require $file;
$loader->addPsr4('Behat\Mink\Tests\Driver\\', __DIR__.'/tests');
// Clean the global variables
unset($file);
unset($loader);
// Check the definition of the driverLoaderFactory
if (!isset($GLOBALS['driver_config_factory'])) {
echo PHP_EOL.'The "driver_config_factory" global variable must be set.'.PHP_EOL;
exit(1);
}
if (!is_callable($GLOBALS['driver_config_factory'])) {
echo PHP_EOL.'The "driver_config_factory" global variable must be a callable.'.PHP_EOL;
exit(1);
}

View file

@ -0,0 +1,83 @@
<?php
namespace Behat\Mink\Tests\Driver;
use Behat\Mink\Driver\DriverInterface;
abstract class AbstractConfig
{
/**
* Creates driver instance.
*
* @return DriverInterface
*/
abstract public function createDriver();
/**
* Map remote file path.
*
* @param string $file File path.
*
* @return string
*/
public function mapRemoteFilePath($file)
{
if (!isset($_SERVER['TEST_MACHINE_BASE_PATH']) || !isset($_SERVER['DRIVER_MACHINE_BASE_PATH'])) {
return $file;
}
$pattern = '/^'.preg_quote($_SERVER['TEST_MACHINE_BASE_PATH'], '/').'/';
$basePath = $_SERVER['DRIVER_MACHINE_BASE_PATH'];
return preg_replace($pattern, $basePath, $file, 1);
}
/**
* Gets the base url to the fixture folder.
*
* @return string
*/
public function getWebFixturesUrl()
{
return $_SERVER['WEB_FIXTURES_HOST'];
}
/**
* @param string $testCase The name of the TestCase class
* @param string $test The name of the test method
*
* @return string|null A message explaining why the test should be skipped, or null to run the test.
*/
public function skipMessage($testCase, $test)
{
if (!$this->supportsCss() && 0 === strpos($testCase, 'Behat\Mink\Tests\Driver\Css\\')) {
return 'This driver does not support CSS.';
}
if (!$this->supportsJs() && 0 === strpos($testCase, 'Behat\Mink\Tests\Driver\Js\\')) {
return 'This driver does not support JavaScript.';
}
return null;
}
/**
* Whether the JS tests should run or no.
*
* @return bool
*/
protected function supportsJs()
{
return true;
}
/**
* Whether the CSS tests should run or no.
*
* @return bool
*/
protected function supportsCss()
{
return false;
}
}

View file

@ -0,0 +1,64 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
class BasicAuthTest extends TestCase
{
/**
* @dataProvider setBasicAuthDataProvider
*/
public function testSetBasicAuth($user, $pass, $pageText)
{
$session = $this->getSession();
$session->setBasicAuth($user, $pass);
$session->visit($this->pathTo('/basic_auth.php'));
$this->assertContains($pageText, $session->getPage()->getContent());
}
public function setBasicAuthDataProvider()
{
return array(
array('mink-user', 'mink-password', 'is authenticated'),
array('', '', 'is not authenticated'),
);
}
public function testResetBasicAuth()
{
$session = $this->getSession();
$session->setBasicAuth('mink-user', 'mink-password');
$session->visit($this->pathTo('/basic_auth.php'));
$this->assertContains('is authenticated', $session->getPage()->getContent());
$session->setBasicAuth(false);
$session->visit($this->pathTo('/headers.php'));
$this->assertNotContains('PHP_AUTH_USER', $session->getPage()->getContent());
}
public function testResetWithBasicAuth()
{
$session = $this->getSession();
$session->setBasicAuth('mink-user', 'mink-password');
$session->visit($this->pathTo('/basic_auth.php'));
$this->assertContains('is authenticated', $session->getPage()->getContent());
$session->reset();
$session->visit($this->pathTo('/headers.php'));
$this->assertNotContains('PHP_AUTH_USER', $session->getPage()->getContent());
}
}

View file

@ -0,0 +1,84 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
/**
* This testcase ensures that the driver implementation follows recommended practices for drivers.
*/
class BestPracticesTest extends TestCase
{
public function testExtendsCoreDriver()
{
$driver = $this->createDriver();
$this->assertInstanceOf('Behat\Mink\Driver\CoreDriver', $driver);
return $driver;
}
/**
* @depends testExtendsCoreDriver
*/
public function testImplementFindXpath()
{
$driver = $this->createDriver();
$this->assertNotImplementMethod('find', $driver, 'The driver should overwrite `findElementXpaths` rather than `find` for forward compatibility with Mink 2.');
$this->assertImplementMethod('findElementXpaths', $driver, 'The driver must be able to find elements.');
$this->assertNotImplementMethod('setSession', $driver, 'The driver should not deal with the Session directly for forward compatibility with Mink 2.');
}
/**
* @dataProvider provideRequiredMethods
*/
public function testImplementBasicApi($method)
{
$driver = $this->createDriver();
$this->assertImplementMethod($method, $driver, 'The driver is unusable when this method is not implemented.');
}
public function provideRequiredMethods()
{
return array(
array('start'),
array('isStarted'),
array('stop'),
array('reset'),
array('visit'),
array('getCurrentUrl'),
array('getContent'),
array('click'),
);
}
private function assertImplementMethod($method, $object, $reason = '')
{
$ref = new \ReflectionClass(get_class($object));
$refMethod = $ref->getMethod($method);
$message = sprintf('The driver should implement the `%s` method.', $method);
if ('' !== $reason) {
$message .= ' '.$reason;
}
$this->assertSame($ref->name, $refMethod->getDeclaringClass()->name, $message);
}
private function assertNotImplementMethod($method, $object, $reason = '')
{
$ref = new \ReflectionClass(get_class($object));
$refMethod = $ref->getMethod($method);
$message = sprintf('The driver should not implement the `%s` method.', $method);
if ('' !== $reason) {
$message .= ' '.$reason;
}
$this->assertNotSame($ref->name, $refMethod->getDeclaringClass()->name, $message);
}
}

View file

@ -0,0 +1,86 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
class ContentTest extends TestCase
{
public function testOuterHtml()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$element = $this->getAssertSession()->elementExists('css', '.travers');
$this->assertEquals(
"<div class=\"travers\">\n <div class=\"sub\">el1</div>\n".
" <div class=\"sub\">el2</div>\n <div class=\"sub\">\n".
" <a href=\"some_url\">some <strong>deep</strong> url</a>\n".
" </div>\n </div>",
$element->getOuterHtml()
);
}
public function testDumpingEmptyElements()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$element = $this->getAssertSession()->elementExists('css', '#empty');
$this->assertEquals(
'An empty <em></em> tag should be rendered with both open and close tags.',
trim($element->getHtml())
);
}
/**
* @dataProvider getAttributeDataProvider
*/
public function testGetAttribute($attributeName, $attributeValue)
{
$this->getSession()->visit($this->pathTo('/index.html'));
$element = $this->getSession()->getPage()->findById('attr-elem['.$attributeName.']');
$this->assertNotNull($element);
$this->assertSame($attributeValue, $element->getAttribute($attributeName));
}
public function getAttributeDataProvider()
{
return array(
array('with-value', 'some-value'),
array('without-value', ''),
array('with-empty-value', ''),
array('with-missing', null),
);
}
public function testJson()
{
$this->getSession()->visit($this->pathTo('/json.php'));
$this->assertContains(
'{"key1":"val1","key2":234,"key3":[1,2,3]}',
$this->getSession()->getPage()->getContent()
);
}
public function testHtmlDecodingNotPerformed()
{
$session = $this->getSession();
$webAssert = $this->getAssertSession();
$session->visit($this->pathTo('/html_decoding.html'));
$page = $session->getPage();
$span = $webAssert->elementExists('css', 'span');
$input = $webAssert->elementExists('css', 'input');
$expectedHtml = '<span custom-attr="&amp;">some text</span>';
$this->assertContains($expectedHtml, $page->getHtml(), '.innerHTML is returned as-is');
$this->assertContains($expectedHtml, $page->getContent(), '.outerHTML is returned as-is');
$this->assertEquals('&', $span->getAttribute('custom-attr'), '.getAttribute value is decoded');
$this->assertEquals('&', $input->getAttribute('value'), '.getAttribute value is decoded');
$this->assertEquals('&', $input->getValue(), 'node value is decoded');
}
}

View file

@ -0,0 +1,168 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
class CookieTest extends TestCase
{
/**
* test cookie decoding.
*
* @group issue140
*/
public function testIssue140()
{
$this->getSession()->visit($this->pathTo('/issue140.php'));
$this->getSession()->getPage()->fillField('cookie_value', 'some:value;');
$this->getSession()->getPage()->pressButton('Set cookie');
$this->getSession()->visit($this->pathTo('/issue140.php?show_value'));
$this->assertEquals('some:value;', $this->getSession()->getCookie('tc'));
$this->assertEquals('some:value;', $this->getSession()->getPage()->getText());
}
public function testCookie()
{
$this->getSession()->visit($this->pathTo('/cookie_page2.php'));
$this->assertContains('Previous cookie: NO', $this->getSession()->getPage()->getText());
$this->assertNull($this->getSession()->getCookie('srvr_cookie'));
$this->getSession()->setCookie('srvr_cookie', 'client cookie set');
$this->getSession()->reload();
$this->assertContains('Previous cookie: client cookie set', $this->getSession()->getPage()->getText());
$this->assertEquals('client cookie set', $this->getSession()->getCookie('srvr_cookie'));
$this->getSession()->setCookie('srvr_cookie', null);
$this->getSession()->reload();
$this->assertContains('Previous cookie: NO', $this->getSession()->getPage()->getText());
$this->getSession()->visit($this->pathTo('/cookie_page1.php'));
$this->getSession()->visit($this->pathTo('/cookie_page2.php'));
$this->assertContains('Previous cookie: srv_var_is_set', $this->getSession()->getPage()->getText());
$this->getSession()->setCookie('srvr_cookie', null);
$this->getSession()->reload();
$this->assertContains('Previous cookie: NO', $this->getSession()->getPage()->getText());
}
/**
* @dataProvider cookieWithPathsDataProvider
*/
public function testCookieWithPaths($cookieRemovalMode)
{
// start clean
$session = $this->getSession();
$session->visit($this->pathTo('/sub-folder/cookie_page2.php'));
$this->assertContains('Previous cookie: NO', $session->getPage()->getText());
// cookie from root path is accessible in sub-folder
$session->visit($this->pathTo('/cookie_page1.php'));
$session->visit($this->pathTo('/sub-folder/cookie_page2.php'));
$this->assertContains('Previous cookie: srv_var_is_set', $session->getPage()->getText());
// cookie from sub-folder overrides cookie from root path
$session->visit($this->pathTo('/sub-folder/cookie_page1.php'));
$session->visit($this->pathTo('/sub-folder/cookie_page2.php'));
$this->assertContains('Previous cookie: srv_var_is_set_sub_folder', $session->getPage()->getText());
if ($cookieRemovalMode == 'session_reset') {
$session->reset();
} elseif ($cookieRemovalMode == 'cookie_delete') {
$session->setCookie('srvr_cookie', null);
}
// cookie is removed from all paths
$session->visit($this->pathTo('/sub-folder/cookie_page2.php'));
$this->assertContains('Previous cookie: NO', $session->getPage()->getText());
}
public function cookieWithPathsDataProvider()
{
return array(
array('session_reset'),
array('cookie_delete'),
);
}
public function testReset()
{
$this->getSession()->visit($this->pathTo('/cookie_page1.php'));
$this->getSession()->visit($this->pathTo('/cookie_page2.php'));
$this->assertContains('Previous cookie: srv_var_is_set', $this->getSession()->getPage()->getText());
$this->getSession()->reset();
$this->getSession()->visit($this->pathTo('/cookie_page2.php'));
$this->assertContains('Previous cookie: NO', $this->getSession()->getPage()->getText());
$this->getSession()->setCookie('srvr_cookie', 'test_cookie');
$this->getSession()->visit($this->pathTo('/cookie_page2.php'));
$this->assertContains('Previous cookie: test_cookie', $this->getSession()->getPage()->getText());
$this->getSession()->reset();
$this->getSession()->visit($this->pathTo('/cookie_page2.php'));
$this->assertContains('Previous cookie: NO', $this->getSession()->getPage()->getText());
$this->getSession()->setCookie('client_cookie1', 'some_val');
$this->getSession()->setCookie('client_cookie2', 123);
$this->getSession()->visit($this->pathTo('/session_test.php'));
$this->getSession()->visit($this->pathTo('/cookie_page1.php'));
$this->getSession()->visit($this->pathTo('/print_cookies.php'));
$this->assertContains(
"'client_cookie1' = 'some_val'",
$this->getSession()->getPage()->getText()
);
$this->assertContains(
"'client_cookie2' = '123'",
$this->getSession()->getPage()->getText()
);
$this->assertContains(
"_SESS' = ",
$this->getSession()->getPage()->getText()
);
$this->assertContains(
" 'srvr_cookie' = 'srv_var_is_set'",
$this->getSession()->getPage()->getText()
);
$this->getSession()->reset();
$this->getSession()->visit($this->pathTo('/print_cookies.php'));
$this->assertContains('array ( )', $this->getSession()->getPage()->getText());
}
public function testHttpOnlyCookieIsDeleted()
{
$this->getSession()->restart();
$this->getSession()->visit($this->pathTo('/cookie_page3.php'));
$this->assertEquals('Has Cookie: false', $this->findById('cookie-status')->getText());
$this->getSession()->reload();
$this->assertEquals('Has Cookie: true', $this->findById('cookie-status')->getText());
$this->getSession()->restart();
$this->getSession()->visit($this->pathTo('/cookie_page3.php'));
$this->assertEquals('Has Cookie: false', $this->findById('cookie-status')->getText());
}
public function testSessionPersistsBetweenRequests()
{
$this->getSession()->visit($this->pathTo('/session_test.php'));
$webAssert = $this->getAssertSession();
$node = $webAssert->elementExists('css', '#session-id');
$sessionId = $node->getText();
$this->getSession()->visit($this->pathTo('/session_test.php'));
$node = $webAssert->elementExists('css', '#session-id');
$this->assertEquals($sessionId, $node->getText());
$this->getSession()->visit($this->pathTo('/session_test.php?login'));
$node = $webAssert->elementExists('css', '#session-id');
$this->assertNotEquals($sessionId, $newSessionId = $node->getText());
$this->getSession()->visit($this->pathTo('/session_test.php'));
$node = $webAssert->elementExists('css', '#session-id');
$this->assertEquals($newSessionId, $node->getText());
}
}

View file

@ -0,0 +1,265 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
/**
* @group slow
*/
class ErrorHandlingTest extends TestCase
{
const NOT_FOUND_XPATH = '//html/./invalid';
const NOT_FOUND_EXCEPTION = 'Exception';
const INVALID_EXCEPTION = 'Exception';
public function testVisitErrorPage()
{
$this->getSession()->visit($this->pathTo('/500.php'));
$this->assertContains(
'Sorry, a server error happened',
$this->getSession()->getPage()->getContent(),
'Drivers allow loading pages with a 500 status code'
);
}
public function testCheckInvalidElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$element = $this->findById('user-name');
$this->setExpectedException(self::INVALID_EXCEPTION);
$this->getSession()->getDriver()->check($element->getXpath());
}
public function testCheckNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->check(self::NOT_FOUND_XPATH);
}
public function testUncheckInvalidElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$element = $this->findById('user-name');
$this->setExpectedException(self::INVALID_EXCEPTION);
$this->getSession()->getDriver()->uncheck($element->getXpath());
}
public function testUncheckNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->uncheck(self::NOT_FOUND_XPATH);
}
public function testSelectOptionInvalidElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$element = $this->findById('user-name');
$this->setExpectedException(self::INVALID_EXCEPTION);
$this->getSession()->getDriver()->selectOption($element->getXpath(), 'test');
}
public function testSelectOptionNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->selectOption(self::NOT_FOUND_XPATH, 'test');
}
public function testAttachFileInvalidElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$element = $this->findById('user-name');
$this->setExpectedException(self::INVALID_EXCEPTION);
$this->getSession()->getDriver()->attachFile($element->getXpath(), __FILE__);
}
public function testAttachFileNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->attachFile(self::NOT_FOUND_XPATH, __FILE__);
}
public function testSubmitFormInvalidElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$element = $this->findById('core');
$this->setExpectedException(self::INVALID_EXCEPTION);
$this->getSession()->getDriver()->submitForm($element->getXpath());
}
public function testSubmitFormNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->submitForm(self::NOT_FOUND_XPATH);
}
public function testGetTagNameNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->getTagName(self::NOT_FOUND_XPATH);
}
public function testGetTextNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->getText(self::NOT_FOUND_XPATH);
}
public function testGetHtmlNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->getHtml(self::NOT_FOUND_XPATH);
}
public function testGetOuterHtmlNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->getOuterHtml(self::NOT_FOUND_XPATH);
}
public function testGetValueNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->getValue(self::NOT_FOUND_XPATH);
}
public function testSetValueNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->setValue(self::NOT_FOUND_XPATH, 'test');
}
public function testIsSelectedNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->isSelected(self::NOT_FOUND_XPATH);
}
public function testIsCheckedNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->isChecked(self::NOT_FOUND_XPATH);
}
public function testIsVisibleNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->isVisible(self::NOT_FOUND_XPATH);
}
public function testClickNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->click(self::NOT_FOUND_XPATH);
}
public function testDoubleClickNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->doubleClick(self::NOT_FOUND_XPATH);
}
public function testRightClickNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->rightClick(self::NOT_FOUND_XPATH);
}
public function testGetAttributeNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->getAttribute(self::NOT_FOUND_XPATH, 'id');
}
public function testMouseOverNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->mouseOver(self::NOT_FOUND_XPATH);
}
public function testFocusNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->focus(self::NOT_FOUND_XPATH);
}
public function testBlurNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->blur(self::NOT_FOUND_XPATH);
}
public function testKeyPressNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->keyPress(self::NOT_FOUND_XPATH, 'a');
}
public function testKeyDownNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->keyDown(self::NOT_FOUND_XPATH, 'a');
}
public function testKeyUpNotFoundElement()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->setExpectedException(self::NOT_FOUND_EXCEPTION);
$this->getSession()->getDriver()->keyUp(self::NOT_FOUND_XPATH, 'a');
}
}

View file

@ -0,0 +1,78 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
class HeaderTest extends TestCase
{
/**
* test referrer.
*
* @group issue130
*/
public function testIssue130()
{
$this->getSession()->visit($this->pathTo('/issue130.php?p=1'));
$page = $this->getSession()->getPage();
$page->clickLink('Go to 2');
$this->assertEquals($this->pathTo('/issue130.php?p=1'), $page->getText());
}
public function testHeaders()
{
$this->getSession()->setRequestHeader('Accept-Language', 'fr');
$this->getSession()->visit($this->pathTo('/headers.php'));
$this->assertContains('[HTTP_ACCEPT_LANGUAGE] => fr', $this->getSession()->getPage()->getContent());
}
public function testSetUserAgent()
{
$session = $this->getSession();
$session->setRequestHeader('user-agent', 'foo bar');
$session->visit($this->pathTo('/headers.php'));
$this->assertContains('[HTTP_USER_AGENT] => foo bar', $session->getPage()->getContent());
}
public function testResetHeaders()
{
$session = $this->getSession();
$session->setRequestHeader('X-Mink-Test', 'test');
$session->visit($this->pathTo('/headers.php'));
$this->assertContains(
'[HTTP_X_MINK_TEST] => test',
$session->getPage()->getContent(),
'The custom header should be sent',
true
);
$session->reset();
$session->visit($this->pathTo('/headers.php'));
$this->assertNotContains(
'[HTTP_X_MINK_TEST] => test',
$session->getPage()->getContent(),
'The custom header should not be sent after resetting',
true
);
}
public function testResponseHeaders()
{
$this->getSession()->visit($this->pathTo('/response_headers.php'));
$headers = $this->getSession()->getResponseHeaders();
$lowercasedHeaders = array();
foreach ($headers as $name => $value) {
$lowercasedHeaders[str_replace('_', '-', strtolower($name))] = $value;
}
$this->assertArrayHasKey('x-mink-test', $lowercasedHeaders);
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
class IFrameTest extends TestCase
{
public function testIFrame()
{
$this->getSession()->visit($this->pathTo('/iframe.html'));
$webAssert = $this->getAssertSession();
$el = $webAssert->elementExists('css', '#text');
$this->assertSame('Main window div text', $el->getText());
$this->getSession()->switchToIFrame('subframe');
$el = $webAssert->elementExists('css', '#text');
$this->assertSame('iFrame div text', $el->getText());
$this->getSession()->switchToIFrame();
$el = $webAssert->elementExists('css', '#text');
$this->assertSame('Main window div text', $el->getText());
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
class NavigationTest extends TestCase
{
public function testRedirect()
{
$this->getSession()->visit($this->pathTo('/redirector.php'));
$this->assertEquals($this->pathTo('/redirect_destination.html'), $this->getSession()->getCurrentUrl());
}
public function testPageControls()
{
$this->getSession()->visit($this->pathTo('/randomizer.php'));
$number1 = $this->getAssertSession()->elementExists('css', '#number')->getText();
$this->getSession()->reload();
$number2 = $this->getAssertSession()->elementExists('css', '#number')->getText();
$this->assertNotEquals($number1, $number2);
$this->getSession()->visit($this->pathTo('/links.html'));
$this->getSession()->getPage()->clickLink('Random number page');
$this->assertEquals($this->pathTo('/randomizer.php'), $this->getSession()->getCurrentUrl());
$this->getSession()->back();
$this->assertEquals($this->pathTo('/links.html'), $this->getSession()->getCurrentUrl());
$this->getSession()->forward();
$this->assertEquals($this->pathTo('/randomizer.php'), $this->getSession()->getCurrentUrl());
}
public function testLinks()
{
$this->getSession()->visit($this->pathTo('/links.html'));
$page = $this->getSession()->getPage();
$link = $page->findLink('Redirect me to');
$this->assertNotNull($link);
$this->assertRegExp('/redirector\.php$/', $link->getAttribute('href'));
$link->click();
$this->assertEquals($this->pathTo('/redirect_destination.html'), $this->getSession()->getCurrentUrl());
$this->getSession()->visit($this->pathTo('/links.html'));
$page = $this->getSession()->getPage();
$link = $page->findLink('basic form image');
$this->assertNotNull($link);
$this->assertRegExp('/basic_form\.html$/', $link->getAttribute('href'));
$link->click();
$this->assertEquals($this->pathTo('/basic_form.html'), $this->getSession()->getCurrentUrl());
$this->getSession()->visit($this->pathTo('/links.html'));
$page = $this->getSession()->getPage();
$link = $page->findLink('Link with a ');
$this->assertNotNull($link);
$this->assertRegExp('/links\.html\?quoted$/', $link->getAttribute('href'));
$link->click();
$this->assertEquals($this->pathTo('/links.html?quoted'), $this->getSession()->getCurrentUrl());
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
class ScreenshotTest extends TestCase
{
public function testScreenshot()
{
if (!extension_loaded('gd')) {
$this->markTestSkipped('Testing screenshots requires the GD extension');
}
$this->getSession()->visit($this->pathTo('/index.html'));
$screenShot = $this->getSession()->getScreenshot();
$this->assertInternalType('string', $screenShot);
$this->assertFalse(base64_decode($screenShot, true), 'The returned screenshot should not be base64-encoded');
$img = imagecreatefromstring($screenShot);
if (false === $img) {
$this->fail('The screenshot should be a valid image');
}
imagedestroy($img);
}
}

View file

@ -0,0 +1,22 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
class StatusCodeTest extends TestCase
{
public function testStatuses()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->assertEquals(200, $this->getSession()->getStatusCode());
$this->assertEquals($this->pathTo('/index.html'), $this->getSession()->getCurrentUrl());
$this->getSession()->visit($this->pathTo('/404.php'));
$this->assertEquals($this->pathTo('/404.php'), $this->getSession()->getCurrentUrl());
$this->assertEquals(404, $this->getSession()->getStatusCode());
$this->assertEquals('Sorry, page not found', $this->getSession()->getPage()->getContent());
}
}

View file

@ -0,0 +1,143 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
class TraversingTest extends TestCase
{
/**
* find by label.
*
* @group issue211
*/
public function testIssue211()
{
$this->getSession()->visit($this->pathTo('/issue211.html'));
$field = $this->getSession()->getPage()->findField('Téléphone');
$this->assertNotNull($field);
}
public function testElementsTraversing()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$page = $this->getSession()->getPage();
$title = $page->find('css', 'h1');
$this->assertNotNull($title);
$this->assertEquals('Extremely useless page', $title->getText());
$this->assertEquals('h1', $title->getTagName());
$strong = $page->find('xpath', '//div/strong[3]');
$this->assertNotNull($strong);
$this->assertEquals('pariatur', $strong->getText());
$this->assertEquals('super-duper', $strong->getAttribute('class'));
$this->assertTrue($strong->hasAttribute('class'));
$strong2 = $page->find('xpath', '//div/strong[2]');
$this->assertNotNull($strong2);
$this->assertEquals('veniam', $strong2->getText());
$this->assertEquals('strong', $strong2->getTagName());
$this->assertNull($strong2->getAttribute('class'));
$this->assertFalse($strong2->hasAttribute('class'));
$strongs = $page->findAll('css', 'div#core > strong');
$this->assertCount(3, $strongs);
$this->assertEquals('Lorem', $strongs[0]->getText());
$this->assertEquals('pariatur', $strongs[2]->getText());
$element = $page->find('css', '#some-element');
$this->assertNotNull($element);
$this->assertEquals('some very interesting text', $element->getText());
$this->assertEquals(
"\n some <div>very\n </div>\n".
"<em>interesting</em> text\n ",
$element->getHtml()
);
$this->assertTrue($element->hasAttribute('data-href'));
$this->assertFalse($element->hasAttribute('data-url'));
$this->assertEquals('http://mink.behat.org', $element->getAttribute('data-href'));
$this->assertNull($element->getAttribute('data-url'));
$this->assertEquals('div', $element->getTagName());
}
public function testVeryDeepElementsTraversing()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$page = $this->getSession()->getPage();
$footer = $page->find('css', 'footer');
$this->assertNotNull($footer);
$searchForm = $footer->find('css', 'form#search-form');
$this->assertNotNull($searchForm);
$this->assertEquals('search-form', $searchForm->getAttribute('id'));
$searchInput = $searchForm->findField('Search site...');
$this->assertNotNull($searchInput);
$this->assertEquals('text', $searchInput->getAttribute('type'));
$searchInput = $searchForm->findField('Search site...');
$this->assertNotNull($searchInput);
$this->assertEquals('text', $searchInput->getAttribute('type'));
$profileForm = $footer->find('css', '#profile');
$this->assertNotNull($profileForm);
$profileFormDiv = $profileForm->find('css', 'div');
$this->assertNotNull($profileFormDiv);
$profileFormDivLabel = $profileFormDiv->find('css', 'label');
$this->assertNotNull($profileFormDivLabel);
$profileFormDivParent = $profileFormDivLabel->getParent();
$this->assertNotNull($profileFormDivParent);
$profileFormDivParent = $profileFormDivLabel->getParent();
$this->assertEquals('something', $profileFormDivParent->getAttribute('data-custom'));
$profileFormInput = $profileFormDivLabel->findField('user-name');
$this->assertNotNull($profileFormInput);
$this->assertEquals('username', $profileFormInput->getAttribute('name'));
}
public function testDeepTraversing()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$traversDivs = $this->getSession()->getPage()->findAll('css', 'div.travers');
$this->assertCount(1, $traversDivs);
$subDivs = $traversDivs[0]->findAll('css', 'div.sub');
$this->assertCount(3, $subDivs);
$this->assertTrue($subDivs[2]->hasLink('some deep url'));
$this->assertFalse($subDivs[2]->hasLink('come deep url'));
$subUrl = $subDivs[2]->findLink('some deep url');
$this->assertNotNull($subUrl);
$this->assertRegExp('/some_url$/', $subUrl->getAttribute('href'));
$this->assertEquals('some deep url', $subUrl->getText());
$this->assertEquals('some <strong>deep</strong> url', $subUrl->getHtml());
$this->assertTrue($subUrl->has('css', 'strong'));
$this->assertFalse($subUrl->has('css', 'em'));
$this->assertEquals('deep', $subUrl->find('css', 'strong')->getText());
}
public function testFindingChild()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$form = $this->getSession()->getPage()->find('css', 'footer form');
$this->assertNotNull($form);
$this->assertCount(1, $form->findAll('css', 'input'), 'Elements are searched only in the element, not in all previous matches');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace Behat\Mink\Tests\Driver\Basic;
use Behat\Mink\Tests\Driver\TestCase;
class VisibilityTest extends TestCase
{
public function testVisibility()
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$webAssert = $this->getAssertSession();
$clicker = $webAssert->elementExists('css', '.elements div#clicker');
$invisible = $webAssert->elementExists('css', '#invisible');
$this->assertFalse($invisible->isVisible());
$this->assertTrue($clicker->isVisible());
}
}

View file

@ -0,0 +1,76 @@
<?php
namespace Behat\Mink\Tests\Driver\Css;
use Behat\Mink\Tests\Driver\TestCase;
class HoverTest extends TestCase
{
/**
* @group mouse-events
*/
public function testMouseOverHover()
{
$this->getSession()->visit($this->pathTo('/css_mouse_events.html'));
$this->findById('reset-square')->mouseOver();
$this->assertActionSquareHeight(100);
$this->findById('action-square')->mouseOver();
$this->assertActionSquareHeight(200);
}
/**
* @group mouse-events
* @depends testMouseOverHover
*/
public function testClickHover()
{
$this->getSession()->visit($this->pathTo('/css_mouse_events.html'));
$this->findById('reset-square')->mouseOver();
$this->assertActionSquareHeight(100);
$this->findById('action-square')->click();
$this->assertActionSquareHeight(200);
}
/**
* @group mouse-events
* @depends testMouseOverHover
*/
public function testDoubleClickHover()
{
$this->getSession()->visit($this->pathTo('/css_mouse_events.html'));
$this->findById('reset-square')->mouseOver();
$this->assertActionSquareHeight(100);
$this->findById('action-square')->doubleClick();
$this->assertActionSquareHeight(200);
}
/**
* @group mouse-events
* @depends testMouseOverHover
*/
public function testRightClickHover()
{
$this->getSession()->visit($this->pathTo('/css_mouse_events.html'));
$this->findById('reset-square')->mouseOver();
$this->assertActionSquareHeight(100);
$this->findById('action-square')->rightClick();
$this->assertActionSquareHeight(200);
}
private function assertActionSquareHeight($expected)
{
$this->assertEquals(
$expected,
$this->getSession()->evaluateScript("return window.$('#action-square').height();"),
'Mouse is located over the object when mouse-related action is performed'
);
}
}

View file

@ -0,0 +1,73 @@
<?php
namespace Behat\Mink\Tests\Driver\Form;
use Behat\Mink\Tests\Driver\TestCase;
class CheckboxTest extends TestCase
{
public function testManipulate()
{
$this->getSession()->visit($this->pathTo('advanced_form.html'));
$checkbox = $this->getAssertSession()->fieldExists('agreement');
$this->assertNull($checkbox->getValue());
$this->assertFalse($checkbox->isChecked());
$checkbox->check();
$this->assertEquals('yes', $checkbox->getValue());
$this->assertTrue($checkbox->isChecked());
$checkbox->uncheck();
$this->assertNull($checkbox->getValue());
$this->assertFalse($checkbox->isChecked());
}
public function testSetValue()
{
$this->getSession()->visit($this->pathTo('advanced_form.html'));
$checkbox = $this->getAssertSession()->fieldExists('agreement');
$this->assertNull($checkbox->getValue());
$this->assertFalse($checkbox->isChecked());
$checkbox->setValue(true);
$this->assertEquals('yes', $checkbox->getValue());
$this->assertTrue($checkbox->isChecked());
$checkbox->setValue(false);
$this->assertNull($checkbox->getValue());
$this->assertFalse($checkbox->isChecked());
}
public function testCheckboxMultiple()
{
$this->getSession()->visit($this->pathTo('/multicheckbox_form.html'));
$webAssert = $this->getAssertSession();
$this->assertEquals('Multicheckbox Test', $webAssert->elementExists('css', 'h1')->getText());
$updateMail = $webAssert->elementExists('css', '[name="mail_types[]"][value="update"]');
$spamMail = $webAssert->elementExists('css', '[name="mail_types[]"][value="spam"]');
$this->assertEquals('update', $updateMail->getValue());
$this->assertNull($spamMail->getValue());
$this->assertTrue($updateMail->isChecked());
$this->assertFalse($spamMail->isChecked());
$updateMail->uncheck();
$this->assertFalse($updateMail->isChecked());
$this->assertFalse($spamMail->isChecked());
$spamMail->check();
$this->assertFalse($updateMail->isChecked());
$this->assertTrue($spamMail->isChecked());
}
}

View file

@ -0,0 +1,312 @@
<?php
namespace Behat\Mink\Tests\Driver\Form;
use Behat\Mink\Tests\Driver\TestCase;
class GeneralTest extends TestCase
{
// test multiple submit buttons
public function testIssue212()
{
$session = $this->getSession();
$session->visit($this->pathTo('/issue212.html'));
$field = $this->findById('poney-button');
$this->assertEquals('poney', $field->getValue());
}
public function testBasicForm()
{
$this->getSession()->visit($this->pathTo('/basic_form.html'));
$webAssert = $this->getAssertSession();
$page = $this->getSession()->getPage();
$this->assertEquals('Basic Form Page', $webAssert->elementExists('css', 'h1')->getText());
$firstname = $webAssert->fieldExists('first_name');
$lastname = $webAssert->fieldExists('lastn');
$this->assertEquals('Firstname', $firstname->getValue());
$this->assertEquals('Lastname', $lastname->getValue());
$firstname->setValue('Konstantin');
$page->fillField('last_name', 'Kudryashov');
$this->assertEquals('Konstantin', $firstname->getValue());
$this->assertEquals('Kudryashov', $lastname->getValue());
$page->findButton('Reset')->click();
$this->assertEquals('Firstname', $firstname->getValue());
$this->assertEquals('Lastname', $lastname->getValue());
$firstname->setValue('Konstantin');
$page->fillField('last_name', 'Kudryashov');
$page->findButton('Save')->click();
if ($this->safePageWait(5000, 'document.getElementById("first") !== null')) {
$this->assertEquals('Anket for Konstantin', $webAssert->elementExists('css', 'h1')->getText());
$this->assertEquals('Firstname: Konstantin', $webAssert->elementExists('css', '#first')->getText());
$this->assertEquals('Lastname: Kudryashov', $webAssert->elementExists('css', '#last')->getText());
}
}
/**
* @dataProvider formSubmitWaysDataProvider
*/
public function testFormSubmitWays($submitVia)
{
$session = $this->getSession();
$session->visit($this->pathTo('/basic_form.html'));
$page = $session->getPage();
$webAssert = $this->getAssertSession();
$firstname = $webAssert->fieldExists('first_name');
$firstname->setValue('Konstantin');
$page->findButton($submitVia)->click();
if ($this->safePageWait(5000, 'document.getElementById("first") !== null')) {
$this->assertEquals('Firstname: Konstantin', $webAssert->elementExists('css', '#first')->getText());
} else {
$this->fail('Form was never submitted');
}
}
public function formSubmitWaysDataProvider()
{
return array(
array('Save'),
array('input-type-image'),
array('button-without-type'),
array('button-type-submit'),
);
}
public function testFormSubmit()
{
$session = $this->getSession();
$session->visit($this->pathTo('/basic_form.html'));
$webAssert = $this->getAssertSession();
$webAssert->fieldExists('first_name')->setValue('Konstantin');
$webAssert->elementExists('xpath', 'descendant-or-self::form[1]')->submit();
if ($this->safePageWait(5000, 'document.getElementById("first") !== null')) {
$this->assertEquals('Firstname: Konstantin', $webAssert->elementExists('css', '#first')->getText());
};
}
public function testFormSubmitWithoutButton()
{
$session = $this->getSession();
$session->visit($this->pathTo('/form_without_button.html'));
$webAssert = $this->getAssertSession();
$webAssert->fieldExists('first_name')->setValue('Konstantin');
$webAssert->elementExists('xpath', 'descendant-or-self::form[1]')->submit();
if ($this->safePageWait(5000, 'document.getElementById("first") !== null')) {
$this->assertEquals('Firstname: Konstantin', $webAssert->elementExists('css', '#first')->getText());
};
}
public function testBasicGetForm()
{
$this->getSession()->visit($this->pathTo('/basic_get_form.php'));
$webAssert = $this->getAssertSession();
$page = $this->getSession()->getPage();
$this->assertEquals('Basic Get Form Page', $webAssert->elementExists('css', 'h1')->getText());
$search = $webAssert->fieldExists('q');
$search->setValue('some#query');
$page->pressButton('Find');
$div = $webAssert->elementExists('css', 'div');
$this->assertEquals('some#query', $div->getText());
}
public function testAdvancedForm()
{
$this->getSession()->visit($this->pathTo('/advanced_form.html'));
$page = $this->getSession()->getPage();
$page->fillField('first_name', 'ever');
$page->fillField('last_name', 'zet');
$page->pressButton('Register');
$this->assertContains('no file', $page->getContent());
$this->getSession()->visit($this->pathTo('/advanced_form.html'));
$webAssert = $this->getAssertSession();
$page = $this->getSession()->getPage();
$this->assertEquals('ADvanced Form Page', $webAssert->elementExists('css', 'h1')->getText());
$firstname = $webAssert->fieldExists('first_name');
$lastname = $webAssert->fieldExists('lastn');
$email = $webAssert->fieldExists('Your email:');
$select = $webAssert->fieldExists('select_number');
$sex = $webAssert->fieldExists('sex');
$maillist = $webAssert->fieldExists('mail_list');
$agreement = $webAssert->fieldExists('agreement');
$notes = $webAssert->fieldExists('notes');
$about = $webAssert->fieldExists('about');
$this->assertEquals('Firstname', $firstname->getValue());
$this->assertEquals('Lastname', $lastname->getValue());
$this->assertEquals('your@email.com', $email->getValue());
$this->assertEquals('20', $select->getValue());
$this->assertEquals('w', $sex->getValue());
$this->assertEquals('original notes', $notes->getValue());
$this->assertEquals('on', $maillist->getValue());
$this->assertNull($agreement->getValue());
$this->assertTrue($maillist->isChecked());
$this->assertFalse($agreement->isChecked());
$agreement->check();
$this->assertTrue($agreement->isChecked());
$maillist->uncheck();
$this->assertFalse($maillist->isChecked());
$select->selectOption('thirty');
$this->assertEquals('30', $select->getValue());
$sex->selectOption('m');
$this->assertEquals('m', $sex->getValue());
$notes->setValue('new notes');
$this->assertEquals('new notes', $notes->getValue());
$about->attachFile($this->mapRemoteFilePath(__DIR__.'/../../web-fixtures/some_file.txt'));
$button = $page->findButton('Register');
$this->assertNotNull($button);
$page->fillField('first_name', 'Foo "item"');
$page->fillField('last_name', 'Bar');
$page->fillField('Your email:', 'ever.zet@gmail.com');
$this->assertEquals('Foo "item"', $firstname->getValue());
$this->assertEquals('Bar', $lastname->getValue());
$button->press();
if ($this->safePageWait(5000, 'document.getElementsByTagName("title") !== null')) {
$out = <<<OUT
array (
'agreement' = 'on',
'email' = 'ever.zet@gmail.com',
'first_name' = 'Foo "item"',
'last_name' = 'Bar',
'notes' = 'new notes',
'select_number' = '30',
'sex' = 'm',
'submit' = 'Register',
)
some_file.txt
1 uploaded file
OUT;
$this->assertContains($out, $page->getContent());
}
}
public function testMultiInput()
{
$this->getSession()->visit($this->pathTo('/multi_input_form.html'));
$page = $this->getSession()->getPage();
$webAssert = $this->getAssertSession();
$this->assertEquals('Multi input Test', $webAssert->elementExists('css', 'h1')->getText());
$first = $webAssert->fieldExists('First');
$second = $webAssert->fieldExists('Second');
$third = $webAssert->fieldExists('Third');
$this->assertEquals('tag1', $first->getValue());
$this->assertSame('tag2', $second->getValue());
$this->assertEquals('tag1', $third->getValue());
$first->setValue('tag2');
$this->assertEquals('tag2', $first->getValue());
$this->assertSame('tag2', $second->getValue());
$this->assertEquals('tag1', $third->getValue());
$second->setValue('one');
$this->assertEquals('tag2', $first->getValue());
$this->assertSame('one', $second->getValue());
$third->setValue('tag3');
$this->assertEquals('tag2', $first->getValue());
$this->assertSame('one', $second->getValue());
$this->assertEquals('tag3', $third->getValue());
$button = $page->findButton('Register');
$this->assertNotNull($button);
$button->press();
$space = ' ';
$out = <<<OUT
'tags' =$space
array (
0 = 'tag2',
1 = 'one',
2 = 'tag3',
),
OUT;
$this->assertContains($out, $page->getContent());
}
public function testAdvancedFormSecondSubmit()
{
$this->getSession()->visit($this->pathTo('/advanced_form.html'));
$page = $this->getSession()->getPage();
$button = $page->findButton('Login');
$this->assertNotNull($button);
$button->press();
$toSearch = array(
"'agreement' = 'off',",
"'submit' = 'Login',",
'no file',
);
$pageContent = $page->getContent();
foreach ($toSearch as $searchString) {
$this->assertContains($searchString, $pageContent);
}
}
public function testSubmitEmptyTextarea()
{
$this->getSession()->visit($this->pathTo('/empty_textarea.html'));
$page = $this->getSession()->getPage();
$page->pressButton('Save');
$toSearch = array(
"'textarea' = '',",
"'submit' = 'Save',",
'no file',
);
$pageContent = $page->getContent();
foreach ($toSearch as $searchString) {
$this->assertContains($searchString, $pageContent);
}
}
}

View file

@ -0,0 +1,128 @@
<?php
namespace Behat\Mink\Tests\Driver\Form;
use Behat\Mink\Tests\Driver\TestCase;
class Html5Test extends TestCase
{
public function testHtml5FormInputAttribute()
{
$this->getSession()->visit($this->pathTo('/html5_form.html'));
$page = $this->getSession()->getPage();
$webAssert = $this->getAssertSession();
$firstName = $webAssert->fieldExists('first_name');
$lastName = $webAssert->fieldExists('last_name');
$this->assertEquals('not set', $lastName->getValue());
$firstName->setValue('John');
$lastName->setValue('Doe');
$this->assertEquals('Doe', $lastName->getValue());
$page->pressButton('Submit in form');
if ($this->safePageWait(5000, 'document.getElementsByTagName("title") !== null')) {
$out = <<<OUT
'first_name' = 'John',
'last_name' = 'Doe',
OUT;
$this->assertContains($out, $page->getContent());
$this->assertNotContains('other_field', $page->getContent());
}
}
public function testHtml5FormRadioAttribute()
{
$this->getSession()->visit($this->pathTo('html5_radio.html'));
$page = $this->getSession()->getPage();
$radio = $this->findById('sex_f');
$otherRadio = $this->findById('sex_invalid');
$this->assertEquals('f', $radio->getValue());
$this->assertEquals('invalid', $otherRadio->getValue());
$radio->selectOption('m');
$this->assertEquals('m', $radio->getValue());
$this->assertEquals('invalid', $otherRadio->getValue());
$page->pressButton('Submit in form');
$out = <<<OUT
'sex' = 'm',
OUT;
$this->assertContains($out, $page->getContent());
}
public function testHtml5FormButtonAttribute()
{
$this->getSession()->visit($this->pathTo('/html5_form.html'));
$page = $this->getSession()->getPage();
$webAssert = $this->getAssertSession();
$firstName = $webAssert->fieldExists('first_name');
$lastName = $webAssert->fieldExists('last_name');
$firstName->setValue('John');
$lastName->setValue('Doe');
$page->pressButton('Submit outside form');
if ($this->safePageWait(5000, 'document.getElementsByTagName("title") !== null')) {
$out = <<<OUT
'first_name' = 'John',
'last_name' = 'Doe',
'submit_button' = 'test',
OUT;
$this->assertContains($out, $page->getContent());
}
}
public function testHtml5FormOutside()
{
$this->getSession()->visit($this->pathTo('/html5_form.html'));
$page = $this->getSession()->getPage();
$page->fillField('other_field', 'hello');
$page->pressButton('Submit separate form');
if ($this->safePageWait(5000, 'document.getElementsByTagName("title") !== null')) {
$out = <<<OUT
'other_field' = 'hello',
OUT;
$this->assertContains($out, $page->getContent());
$this->assertNotContains('first_name', $page->getContent());
}
}
public function testHtml5Types()
{
$this->getSession()->visit($this->pathTo('html5_types.html'));
$page = $this->getSession()->getPage();
$page->fillField('url', 'http://mink.behat.org/');
$page->fillField('email', 'mink@example.org');
$page->fillField('number', '6');
$page->fillField('search', 'mink');
$page->fillField('date', '2014-05-19');
$page->fillField('color', '#ff00aa');
$page->pressButton('Submit');
$out = <<<OUT
'color' = '#ff00aa',
'date' = '2014-05-19',
'email' = 'mink@example.org',
'number' = '6',
'search' = 'mink',
'submit_button' = 'Submit',
'url' = 'http://mink.behat.org/',
OUT;
$this->assertContains($out, $page->getContent());
}
}

View file

@ -0,0 +1,84 @@
<?php
namespace Behat\Mink\Tests\Driver\Form;
use Behat\Mink\Tests\Driver\TestCase;
class RadioTest extends TestCase
{
protected function setUp()
{
$this->getSession()->visit($this->pathTo('radio.html'));
}
public function testIsChecked()
{
$option = $this->findById('first');
$option2 = $this->findById('second');
$this->assertTrue($option->isChecked());
$this->assertFalse($option2->isChecked());
$option2->selectOption('updated');
$this->assertFalse($option->isChecked());
$this->assertTrue($option2->isChecked());
}
public function testSelectOption()
{
$option = $this->findById('first');
$this->assertEquals('set', $option->getValue());
$option->selectOption('updated');
$this->assertEquals('updated', $option->getValue());
$option->selectOption('set');
$this->assertEquals('set', $option->getValue());
}
public function testSetValue()
{
$option = $this->findById('first');
$this->assertEquals('set', $option->getValue());
$option->setValue('updated');
$this->assertEquals('updated', $option->getValue());
$this->assertFalse($option->isChecked());
}
public function testSameNameInMultipleForms()
{
$option1 = $this->findById('reused_form1');
$option2 = $this->findById('reused_form2');
$this->assertEquals('test2', $option1->getValue());
$this->assertEquals('test3', $option2->getValue());
$option1->selectOption('test');
$this->assertEquals('test', $option1->getValue());
$this->assertEquals('test3', $option2->getValue());
}
/**
* @see https://github.com/Behat/MinkSahiDriver/issues/32
*/
public function testSetValueXPathEscaping()
{
$session = $this->getSession();
$session->visit($this->pathTo('/advanced_form.html'));
$page = $session->getPage();
$sex = $page->find('xpath', '//*[@name = "sex"]'."\n|\n".'//*[@id = "sex"]');
$this->assertNotNull($sex, 'xpath with line ending works');
$sex->setValue('m');
$this->assertEquals('m', $sex->getValue(), 'no double xpath escaping during radio button value change');
}
}

View file

@ -0,0 +1,134 @@
<?php
namespace Behat\Mink\Tests\Driver\Form;
use Behat\Mink\Tests\Driver\TestCase;
class SelectTest extends TestCase
{
public function testMultiselect()
{
$this->getSession()->visit($this->pathTo('/multiselect_form.html'));
$webAssert = $this->getAssertSession();
$page = $this->getSession()->getPage();
$this->assertEquals('Multiselect Test', $webAssert->elementExists('css', 'h1')->getText());
$select = $webAssert->fieldExists('select_number');
$multiSelect = $webAssert->fieldExists('select_multiple_numbers[]');
$secondMultiSelect = $webAssert->fieldExists('select_multiple_values[]');
$this->assertEquals('20', $select->getValue());
$this->assertSame(array(), $multiSelect->getValue());
$this->assertSame(array('2', '3'), $secondMultiSelect->getValue());
$select->selectOption('thirty');
$this->assertEquals('30', $select->getValue());
$multiSelect->selectOption('one', true);
$this->assertSame(array('1'), $multiSelect->getValue());
$multiSelect->selectOption('three', true);
$this->assertEquals(array('1', '3'), $multiSelect->getValue());
$secondMultiSelect->selectOption('two');
$this->assertSame(array('2'), $secondMultiSelect->getValue());
$button = $page->findButton('Register');
$this->assertNotNull($button);
$button->press();
$space = ' ';
$out = <<<OUT
'agreement' = 'off',
'select_multiple_numbers' =$space
array (
0 = '1',
1 = '3',
),
'select_multiple_values' =$space
array (
0 = '2',
),
'select_number' = '30',
OUT;
$this->assertContains($out, $page->getContent());
}
/**
* @dataProvider testElementSelectedStateCheckDataProvider
*/
public function testElementSelectedStateCheck($selectName, $optionValue, $optionText)
{
$session = $this->getSession();
$webAssert = $this->getAssertSession();
$session->visit($this->pathTo('/multiselect_form.html'));
$select = $webAssert->fieldExists($selectName);
$option = $webAssert->elementExists('named', array('option', $optionValue));
$this->assertFalse($option->isSelected());
$select->selectOption($optionText);
$this->assertTrue($option->isSelected());
}
public function testElementSelectedStateCheckDataProvider()
{
return array(
array('select_number', '30', 'thirty'),
array('select_multiple_numbers[]', '2', 'two'),
);
}
public function testSetValueSingleSelect()
{
$session = $this->getSession();
$session->visit($this->pathTo('/multiselect_form.html'));
$select = $this->getAssertSession()->fieldExists('select_number');
$select->setValue('10');
$this->assertEquals('10', $select->getValue());
}
public function testSetValueMultiSelect()
{
$session = $this->getSession();
$session->visit($this->pathTo('/multiselect_form.html'));
$select = $this->getAssertSession()->fieldExists('select_multiple_values[]');
$select->setValue(array('1', '2'));
$this->assertEquals(array('1', '2'), $select->getValue());
}
/**
* @see https://github.com/Behat/Mink/issues/193
*/
public function testOptionWithoutValue()
{
$session = $this->getSession();
$session->visit($this->pathTo('/issue193.html'));
$session->getPage()->selectFieldOption('options-without-values', 'Two');
$this->assertEquals('Two', $this->findById('options-without-values')->getValue());
$this->assertTrue($this->findById('two')->isSelected());
$this->assertFalse($this->findById('one')->isSelected());
$session->getPage()->selectFieldOption('options-with-values', 'two');
$this->assertEquals('two', $this->findById('options-with-values')->getValue());
}
/**
* @see https://github.com/Behat/Mink/issues/131
*/
public function testAccentuatedOption()
{
$this->getSession()->visit($this->pathTo('/issue131.html'));
$page = $this->getSession()->getPage();
$page->selectFieldOption('foobar', 'Gimme some accentués characters');
$this->assertEquals('1', $page->findField('foobar')->getValue());
}
}

View file

@ -0,0 +1,155 @@
<?php
namespace Behat\Mink\Tests\Driver\Js;
use Behat\Mink\Tests\Driver\TestCase;
/**
* @group slow
*/
class ChangeEventTest extends TestCase
{
/**
* 'change' event should be fired after selecting an <option> in a <select>.
*
* TODO check whether this test is redundant with other change event tests.
*/
public function testIssue255()
{
$session = $this->getSession();
$session->visit($this->pathTo('/issue255.html'));
$session->getPage()->selectFieldOption('foo_select', 'Option 3');
$session->wait(2000, '$("#output_foo_select").text() != ""');
$this->assertEquals('onChangeSelect', $this->getAssertSession()->elementExists('css', '#output_foo_select')->getText());
}
public function testIssue178()
{
$session = $this->getSession();
$session->visit($this->pathTo('/issue178.html'));
$this->findById('source')->setValue('foo');
$this->assertEquals('foo', $this->findById('target')->getText());
}
/**
* @dataProvider setValueChangeEventDataProvider
* @group change-event-detector
*/
public function testSetValueChangeEvent($elementId, $valueForEmpty, $valueForFilled = '')
{
$this->getSession()->visit($this->pathTo('/element_change_detector.html'));
$page = $this->getSession()->getPage();
$input = $this->findById($elementId);
$this->assertNull($page->findById($elementId.'-result'));
// Verify setting value, when control is initially empty.
$input->setValue($valueForEmpty);
$this->assertElementChangeCount($elementId, 'initial value setting triggers change event');
if ($valueForFilled) {
// Verify setting value, when control already has a value.
$this->findById('results')->click();
$input->setValue($valueForFilled);
$this->assertElementChangeCount($elementId, 'value change triggers change event');
}
}
public function setValueChangeEventDataProvider()
{
return array(
'input default' => array('the-input-default', 'from empty', 'from existing'),
'input text' => array('the-input-text', 'from empty', 'from existing'),
'input email' => array('the-email', 'from empty', 'from existing'),
'textarea' => array('the-textarea', 'from empty', 'from existing'),
'file' => array('the-file', 'from empty', 'from existing'),
'select' => array('the-select', '30'),
'radio' => array('the-radio-m', 'm'),
);
}
/**
* @dataProvider selectOptionChangeEventDataProvider
* @group change-event-detector
*/
public function testSelectOptionChangeEvent($elementId, $elementValue)
{
$this->getSession()->visit($this->pathTo('/element_change_detector.html'));
$page = $this->getSession()->getPage();
$input = $this->findById($elementId);
$this->assertNull($page->findById($elementId.'-result'));
$input->selectOption($elementValue);
$this->assertElementChangeCount($elementId);
}
public function selectOptionChangeEventDataProvider()
{
return array(
'select' => array('the-select', '30'),
'radio' => array('the-radio-m', 'm'),
);
}
/**
* @dataProvider checkboxTestWayDataProvider
* @group change-event-detector
*/
public function testCheckChangeEvent($useSetValue)
{
$this->getSession()->visit($this->pathTo('/element_change_detector.html'));
$page = $this->getSession()->getPage();
$checkbox = $this->findById('the-unchecked-checkbox');
$this->assertNull($page->findById('the-unchecked-checkbox-result'));
if ($useSetValue) {
$checkbox->setValue(true);
} else {
$checkbox->check();
}
$this->assertElementChangeCount('the-unchecked-checkbox');
}
/**
* @dataProvider checkboxTestWayDataProvider
* @group change-event-detector
*/
public function testUncheckChangeEvent($useSetValue)
{
$this->getSession()->visit($this->pathTo('/element_change_detector.html'));
$page = $this->getSession()->getPage();
$checkbox = $this->findById('the-checked-checkbox');
$this->assertNull($page->findById('the-checked-checkbox-result'));
if ($useSetValue) {
$checkbox->setValue(false);
} else {
$checkbox->uncheck();
}
$this->assertElementChangeCount('the-checked-checkbox');
}
public function checkboxTestWayDataProvider()
{
return array(
array(true),
array(false),
);
}
private function assertElementChangeCount($elementId, $message = '')
{
$counterElement = $this->getSession()->getPage()->findById($elementId.'-result');
$actualCount = null === $counterElement ? 0 : $counterElement->getText();
$this->assertEquals('1', $actualCount, $message);
}
}

View file

@ -0,0 +1,122 @@
<?php
namespace Behat\Mink\Tests\Driver\Js;
use Behat\Mink\Tests\Driver\TestCase;
class EventsTest extends TestCase
{
/**
* @group mouse-events
*/
public function testClick()
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$clicker = $this->getAssertSession()->elementExists('css', '.elements div#clicker');
$this->assertEquals('not clicked', $clicker->getText());
$clicker->click();
$this->assertEquals('single clicked', $clicker->getText());
}
/**
* @group mouse-events
*/
public function testDoubleClick()
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$clicker = $this->getAssertSession()->elementExists('css', '.elements div#clicker');
$this->assertEquals('not clicked', $clicker->getText());
$clicker->doubleClick();
$this->assertEquals('double clicked', $clicker->getText());
}
/**
* @group mouse-events
*/
public function testRightClick()
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$clicker = $this->getAssertSession()->elementExists('css', '.elements div#clicker');
$this->assertEquals('not clicked', $clicker->getText());
$clicker->rightClick();
$this->assertEquals('right clicked', $clicker->getText());
}
/**
* @group mouse-events
*/
public function testFocus()
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$focusBlurDetector = $this->getAssertSession()->elementExists('css', '.elements input#focus-blur-detector');
$this->assertEquals('no action detected', $focusBlurDetector->getValue());
$focusBlurDetector->focus();
$this->assertEquals('focused', $focusBlurDetector->getValue());
}
/**
* @group mouse-events
* @depends testFocus
*/
public function testBlur()
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$focusBlurDetector = $this->getAssertSession()->elementExists('css', '.elements input#focus-blur-detector');
$this->assertEquals('no action detected', $focusBlurDetector->getValue());
$focusBlurDetector->blur();
$this->assertEquals('blured', $focusBlurDetector->getValue());
}
/**
* @group mouse-events
*/
public function testMouseOver()
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$mouseOverDetector = $this->getAssertSession()->elementExists('css', '.elements div#mouseover-detector');
$this->assertEquals('no mouse action detected', $mouseOverDetector->getText());
$mouseOverDetector->mouseOver();
$this->assertEquals('mouse overed', $mouseOverDetector->getText());
}
/**
* @dataProvider provideKeyboardEventsModifiers
*/
public function testKeyboardEvents($modifier, $eventProperties)
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$webAssert = $this->getAssertSession();
$input1 = $webAssert->elementExists('css', '.elements input.input.first');
$input2 = $webAssert->elementExists('css', '.elements input.input.second');
$input3 = $webAssert->elementExists('css', '.elements input.input.third');
$event = $webAssert->elementExists('css', '.elements .text-event');
$input1->keyDown('u', $modifier);
$this->assertEquals('key downed:'.$eventProperties, $event->getText());
$input2->keyPress('r', $modifier);
$this->assertEquals('key pressed:114 / '.$eventProperties, $event->getText());
$input3->keyUp(78, $modifier);
$this->assertEquals('key upped:78 / '.$eventProperties, $event->getText());
}
public function provideKeyboardEventsModifiers()
{
return array(
'none' => array(null, '0 / 0 / 0 / 0'),
'alt' => array('alt', '1 / 0 / 0 / 0'),
// jQuery considers ctrl as being a metaKey in the normalized event
'ctrl' => array('ctrl', '0 / 1 / 0 / 1'),
'shift' => array('shift', '0 / 0 / 1 / 0'),
'meta' => array('meta', '0 / 0 / 0 / 1'),
);
}
}

View file

@ -0,0 +1,85 @@
<?php
namespace Behat\Mink\Tests\Driver\Js;
use Behat\Mink\Tests\Driver\TestCase;
class JavascriptEvaluationTest extends TestCase
{
/**
* Tests, that `wait` method returns check result after exit.
*/
public function testWaitReturnValue()
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$found = $this->getSession()->wait(5000, '$("#draggable").length == 1');
$this->assertTrue($found);
}
public function testWait()
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$waitable = $this->findById('waitable');
$waitable->click();
$this->getSession()->wait(3000, '$("#waitable").has("div").length > 0');
$this->assertEquals('arrived', $this->getAssertSession()->elementExists('css', '#waitable > div')->getText());
$waitable->click();
$this->getSession()->wait(3000, 'false');
$this->assertEquals('timeout', $this->getAssertSession()->elementExists('css', '#waitable > div')->getText());
}
/**
* @dataProvider provideExecutedScript
*/
public function testExecuteScript($script)
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->getSession()->executeScript($script);
sleep(1);
$heading = $this->getAssertSession()->elementExists('css', 'h1');
$this->assertEquals('Hello world', $heading->getText());
}
public function provideExecutedScript()
{
return array(
array('document.querySelector("h1").textContent = "Hello world"'),
array('document.querySelector("h1").textContent = "Hello world";'),
array('function () {document.querySelector("h1").textContent = "Hello world";}()'),
array('function () {document.querySelector("h1").textContent = "Hello world";}();'),
array('(function () {document.querySelector("h1").textContent = "Hello world";})()'),
array('(function () {document.querySelector("h1").textContent = "Hello world";})();'),
);
}
/**
* @dataProvider provideEvaluatedScript
*/
public function testEvaluateJavascript($script)
{
$this->getSession()->visit($this->pathTo('/index.html'));
$this->assertSame(2, $this->getSession()->evaluateScript($script));
}
public function provideEvaluatedScript()
{
return array(
array('1 + 1'),
array('1 + 1;'),
array('return 1 + 1'),
array('return 1 + 1;'),
array('function () {return 1+1;}()'),
array('(function () {return 1+1;})()'),
array('return function () { return 1+1;}()'),
array('return (function () {return 1+1;})()'),
);
}
}

View file

@ -0,0 +1,42 @@
<?php
namespace Behat\Mink\Tests\Driver\Js;
use Behat\Mink\Tests\Driver\TestCase;
class JavascriptTest extends TestCase
{
public function testAriaRoles()
{
$this->getSession()->visit($this->pathTo('/aria_roles.html'));
$this->getSession()->wait(5000, '$("#hidden-element").is(":visible") === false');
$this->getSession()->getPage()->pressButton('Toggle');
$this->getSession()->wait(5000, '$("#hidden-element").is(":visible") === true');
$this->getSession()->getPage()->clickLink('Go to Index');
$this->assertEquals($this->pathTo('/index.html'), $this->getSession()->getCurrentUrl());
}
public function testDragDrop()
{
$this->getSession()->visit($this->pathTo('/js_test.html'));
$webAssert = $this->getAssertSession();
$draggable = $webAssert->elementExists('css', '#draggable');
$droppable = $webAssert->elementExists('css', '#droppable');
$draggable->dragTo($droppable);
$this->assertEquals('Dropped!', $this->getAssertSession()->elementExists('css', 'p', $droppable)->getText());
}
// test accentuated char in button
public function testIssue225()
{
$this->getSession()->visit($this->pathTo('/issue225.html'));
$this->getSession()->getPage()->pressButton('Créer un compte');
$this->getSession()->wait(5000, '$("#panel").text() != ""');
$this->assertContains('OH AIH!', $this->getSession()->getPage()->getText());
}
}

View file

@ -0,0 +1,83 @@
<?php
namespace Behat\Mink\Tests\Driver\Js;
use Behat\Mink\Tests\Driver\TestCase;
class WindowTest extends TestCase
{
public function testWindow()
{
$this->getSession()->visit($this->pathTo('/window.html'));
$session = $this->getSession();
$page = $session->getPage();
$webAssert = $this->getAssertSession();
$page->clickLink('Popup #1');
$session->switchToWindow(null);
$page->clickLink('Popup #2');
$session->switchToWindow(null);
$el = $webAssert->elementExists('css', '#text');
$this->assertSame('Main window div text', $el->getText());
$session->switchToWindow('popup_1');
$el = $webAssert->elementExists('css', '#text');
$this->assertSame('Popup#1 div text', $el->getText());
$session->switchToWindow('popup_2');
$el = $webAssert->elementExists('css', '#text');
$this->assertSame('Popup#2 div text', $el->getText());
$session->switchToWindow(null);
$el = $webAssert->elementExists('css', '#text');
$this->assertSame('Main window div text', $el->getText());
}
public function testGetWindowNames()
{
$this->getSession()->visit($this->pathTo('/window.html'));
$session = $this->getSession();
$page = $session->getPage();
$windowName = $this->getSession()->getWindowName();
$this->assertNotNull($windowName);
$page->clickLink('Popup #1');
$page->clickLink('Popup #2');
$windowNames = $this->getSession()->getWindowNames();
$this->assertNotNull($windowNames[0]);
$this->assertNotNull($windowNames[1]);
$this->assertNotNull($windowNames[2]);
}
public function testResizeWindow()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$session = $this->getSession();
$session->resizeWindow(400, 300);
$session->wait(1000, 'false');
$script = 'return Math.abs(window.outerHeight - 300) <= 100 && Math.abs(window.outerWidth - 400) <= 100;';
$this->assertTrue($session->evaluateScript($script));
}
public function testWindowMaximize()
{
$this->getSession()->visit($this->pathTo('/index.html'));
$session = $this->getSession();
$session->maximizeWindow();
$session->wait(1000, 'false');
$script = 'return Math.abs(screen.availHeight - window.outerHeight) <= 100;';
$this->assertTrue($session->evaluateScript($script));
}
}

View file

@ -0,0 +1,167 @@
<?php
namespace Behat\Mink\Tests\Driver;
use Behat\Mink\Exception\UnsupportedDriverActionException;
use Behat\Mink\Mink;
use Behat\Mink\Session;
use Behat\Mink\WebAssert;
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
/**
* Mink session manager.
*
* @var Mink
*/
private static $mink;
/**
* @var AbstractConfig
*/
private static $config;
/**
* Initializes the test case.
*/
public static function setUpBeforeClass()
{
if (null === self::$mink) {
$session = new Session(self::getConfig()->createDriver());
self::$mink = new Mink(array('sess' => $session));
}
}
/**
* @return AbstractConfig
*
* @throws \UnexpectedValueException if the global driver_config_factory returns an invalid object
*/
private static function getConfig()
{
if (null === self::$config) {
self::$config = call_user_func($GLOBALS['driver_config_factory']);
if (!self::$config instanceof AbstractConfig) {
throw new \UnexpectedValueException('The "driver_config_factory" global variable must return a \Behat\Mink\Tests\Driver\AbstractConfig.');
}
}
return self::$config;
}
protected function checkRequirements()
{
if (null !== $message = self::getConfig()->skipMessage(get_class($this), $this->getName(false))) {
$this->markTestSkipped($message);
}
parent::checkRequirements();
}
protected function tearDown()
{
if (null !== self::$mink) {
self::$mink->resetSessions();
}
}
protected function onNotSuccessfulTest(\Exception $e)
{
if ($e instanceof UnsupportedDriverActionException) {
$this->markTestSkipped($e->getMessage());
}
parent::onNotSuccessfulTest($e);
}
/**
* Returns session.
*
* @return Session
*/
protected function getSession()
{
return self::$mink->getSession('sess');
}
/**
* Returns assert session.
*
* @return WebAssert
*/
protected function getAssertSession()
{
return self::$mink->assertSession('sess');
}
/**
* @param string $id
*
* @return \Behat\Mink\Element\NodeElement
*/
protected function findById($id)
{
return $this->getAssertSession()->elementExists('named', array('id', $id));
}
/**
* Creates a new driver instance.
*
* This driver is not associated to a session. It is meant to be used for tests on the driver
* implementation itself rather than test using the Mink API.
*
* @return \Behat\Mink\Driver\DriverInterface
*/
protected function createDriver()
{
return self::getConfig()->createDriver();
}
/**
* Map remote file path.
*
* @param string $file File path.
*
* @return string
*/
protected function mapRemoteFilePath($file)
{
$realPath = realpath($file);
if (false !== $realPath) {
$file = $realPath;
}
return self::getConfig()->mapRemoteFilePath($file);
}
/**
* @param string $path
*
* @return string
*/
protected function pathTo($path)
{
return rtrim(self::getConfig()->getWebFixturesUrl(), '/').'/'.ltrim($path, '/');
}
/**
* Waits for a condition to be true, considering than it is successful for drivers not supporting wait().
*
* @param int $time
* @param string $condition A JS condition to evaluate
*
* @return bool
*
* @see \Behat\Mink\Session::wait()
*/
protected function safePageWait($time, $condition)
{
try {
return $this->getSession()->wait($time, $condition);
} catch (UnsupportedDriverActionException $e) {
return true;
}
}
}

View file

@ -0,0 +1,2 @@
<?php header("HTTP/1.0 404 Not Found") ?>
Sorry, page not found

View file

@ -0,0 +1,2 @@
<?php header("HTTP/1.0 500 Server Error") ?>
Sorry, a server error happened

View file

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<title>ADvanced Form</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<h1>ADvanced Form Page</h1>
<form method="POST" enctype="multipart/form-data" action="advanced_form_post.php">
<input name="first_name" value="Firstname" type="text" />
<input id="lastn" name="last_name" value="Lastname" type="text" />
<label for="email">
Your email:
<input type="email" id="email" name="email" value="your@email.com" />
</label>
<select name="select_number">
<option value="10">ten</option>
<option selected="selected" value="20">twenty</option>
<option value="30">thirty</option>
</select>
<label>
<span><input type="radio" name="sex" value="m" /> m</span>
<span><input type="radio" name="sex" value="w" checked="checked" /> w</span>
</label>
<input type="checkbox" name="mail_list" checked="checked" value="on"/>
<input type="checkbox" name="agreement" value="yes"/>
<textarea name="notes">original notes</textarea>
<input type="file" name="about" />
<input type="submit" name="submit" value="Register" />
<input type="submit" name="submit" value="Login" />
</form>
</body>
</html>

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>Advanced form save</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
</head>
<body>
<?php
error_reporting(0);
if (isset($_POST['select_multiple_numbers']) && false !== strpos($_POST['select_multiple_numbers'][0], ',')) {
$_POST['select_multiple_numbers'] = explode(',', $_POST['select_multiple_numbers'][0]);
}
$_POST['agreement'] = isset($_POST['agreement']) ? 'on' : 'off';
ksort($_POST);
echo str_replace('>', '', var_export($_POST, true)) . "\n";
if (isset($_FILES['about']) && file_exists($_FILES['about']['tmp_name'])) {
echo $_FILES['about']['name'] . "\n";
echo file_get_contents($_FILES['about']['tmp_name']);
} else {
echo "no file";
}
?>
</body>
</html>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<title>ARIA roles test</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
This page tests selected ARIA roles<br />
(see <a href="http://www.w3.org/TR/wai-aria/">http://www.w3.org/TR/wai-aria/</a>)
<div id="hidden-element-toggle-button" role="button">Toggle</div>
<div id="hidden-element" style="display:none;">This content's visibility is changed by clicking the Toggle Button.</div>
<!-- This link is created programmatically -->
<div id="link-element"></div>
<script language="javascript" type="text/javascript" src="js/jquery-1.6.2-min.js"></script>
<script language="javascript" type="text/javascript">
$(document).ready(function() {
$('#hidden-element-toggle-button').click(function() {
$('#hidden-element').toggle();
});
$('#link-element').attr('role', 'link').text('Go to Index').click(function() {
window.location.href = 'index.html';
});
});
</script>
</body>
</html>

View file

@ -0,0 +1,12 @@
<?php
$username = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : false;
$password = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : false;
if ($username == 'mink-user' && $password == 'mink-password') {
echo 'is authenticated';
} else {
header('WWW-Authenticate: Basic realm="Mink Testing Area"');
header('HTTP/1.0 401 Unauthorized');
echo 'is not authenticated';
}

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>Basic Form</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<h1>Basic Form Page</h1>
<form method="POST" action="basic_form_post.php">
<input name="first_name" value="Firstname" type="text" />
<input id="lastn" name="last_name" value="Lastname" type="text" />
<input type="reset" id="Reset" />
<input type="submit" id="Save" />
<input type="image" id="input-type-image"/>
<button>button-without-type</button>
<button type="submit">button-type-submit</button>
</form>
</body>
</html>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title>Basic Form Saving</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<h1>Anket for <?php echo $_POST['first_name'] ?></h1>
<span id="first">Firstname: <?php echo $_POST['first_name'] ?></span>
<span id="last">Lastname: <?php echo $_POST['last_name'] ?></span>
</body>
</html>

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>Basic Get Form</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<h1>Basic Get Form Page</h1>
<div id="serach">
<?php echo isset($_GET['q']) && $_GET['q'] ? $_GET['q'] : 'No search query' ?>
</div>
<form>
<input name="q" value="" type="text" />
<input type="submit" value="Find" />
</form>
</body>
</html>

View file

@ -0,0 +1,21 @@
<?php
if (!isset($cookieAtRootPath)) {
$cookieAtRootPath = true;
}
if (!isset($cookieValue)) {
$cookieValue = 'srv_var_is_set';
}
setcookie('srvr_cookie', $cookieValue, null, $cookieAtRootPath ? '/' : null);
?>
<!DOCTYPE html>
<html>
<head>
<title>Basic Form</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
Basic Page With Cookie Set from Server Side
</body>
</html>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>Basic Form</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
Previous cookie: <?php echo isset($_COOKIE['srvr_cookie']) ? $_COOKIE['srvr_cookie'] : 'NO'; ?>
</body>
</html>

View file

@ -0,0 +1,16 @@
<?php
$hasCookie = isset($_COOKIE['foo']);
setcookie('foo', 'bar', 0, '/', null, false, true);
?>
<!DOCTYPE html>
<html>
<head>
<title>HttpOnly Cookie Test</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<div id="cookie-status">Has Cookie: <?php echo json_encode($hasCookie) ?></div>
</body>
</html>

View file

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>CSS Mouse Events Testing</title>
<style type="text/css">
.squares div {
width: 100px;
height: 100px;
border: 1px solid black;
margin-right: 4px;
float: left;
}
.squares div:hover {
height: 200px;
background-color: red;
}
</style>
<script language="javascript" type="text/javascript" src="js/jquery-1.6.2-min.js"></script>
</head>
<body>
<div class="squares">
<div id="reset-square">reset</div>
<div id="action-square">mouse action</div>
</div>
<script>
$('#action-square').bind('contextmenu', function (e) {
// Prevent opening the context menu on right click as the browser might consider the
// mouse is in the context menu rather than hovering the element
e.preventDefault();
});
</script>
</body>
</html>

View file

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<title>ADvanced Form</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<script src="js/jquery-1.6.2-min.js"></script>
</head>
<body>
<h1>ADvanced Form Page</h1>
<form method="POST" enctype="multipart/form-data" action="advanced_form_post.php">
<input id="the-input-default" value="" />
<input type="text" id="the-input-text" value="" />
<input type="email" id="the-email" value="" />
<select id="the-select">
<option value="10">ten</option>
<option value="20" selected="selected">twenty</option>
<option value="30">thirty</option>
</select>
<label>
<span><input type="radio" name="sex" id="the-radio-m" value="m" /> m</span>
<span><input type="radio" name="sex" id="the-radio-w" value="w" checked="checked" /> w</span>
</label>
<input type="checkbox" id="the-checked-checkbox" value="cb-val" checked/>
<input type="checkbox" id="the-unchecked-checkbox" value="cb-val"/>
<textarea id="the-textarea"></textarea>
<input type="file" id="the-file" />
</form>
<ul id="results" style="border: 1px solid red;">
<li>for easy element location</li>
</ul>
<script type="text/javascript">
$(document).ready(function () {
var $change_registry = {},
$results = $('#results');
$(':input').change(function () {
var $result_id = this.id + '-result';
if (!$change_registry[this.id]) {
$change_registry[this.id] = 1;
$results.append('<li id="' + $result_id + '"></li>');
}
else {
$change_registry[this.id]++;
}
$('#' + $result_id).text($change_registry[this.id]);
});
$results.click(function () {
$results.empty();
$change_registry = {};
});
});
</script>
</body>
</html>

View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Empty textarea submission</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<h1>Empty textarea submission</h1>
<form method="POST" action="advanced_form_post.php">
<textarea name="textarea"></textarea>
<input type="submit" name="submit" value="Save" />
</form>
</body>
</html>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Form submission without button test</title>
</head>
<body>
<form action="basic_form_post.php" method="POST">
<input name="first_name" type="text" value="not set">
<input name="last_name" type="text" value="not set">
</form>
</body>
</html>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>Headers page</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<?php print_r($_SERVER); ?>
</body>
</html>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML5 form attribute test</title>
</head>
<body>
<form action="advanced_form_post.php" method="POST" id="test-form">
<input name="first_name" type="text" value="not set">
<input name="other_field" type="text" value="not submitted" form="another">
<input type="submit" value="Submit separate form" form="another">
<input type="submit" value="Submit in form">
</form>
<input name="last_name" type="text" form="test-form" value="not set">
<button type="submit" form="test-form" name="submit_button" value="test">Submit outside form</button>
<form id="another" method="post" action="advanced_form_post.php"></form>
</body>
</html>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML5 form attribute test</title>
</head>
<body>
<form action="advanced_form_post.php" method="POST" id="test-form">
<input name="sex" type="radio" value="m" id="sex_m">
<input name="sex" type="radio" value="invalid" form="another" id="sex_invalid" checked="checked">
<input type="submit" value="Submit in form">
</form>
<input name="sex" type="radio" form="test-form" value="f" id="sex_f" checked="checked">
<form id="another" method="post" action="advanced_form_post.php"></form>
</body>
</html>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML5 form attribute test</title>
</head>
<body>
<form action="advanced_form_post.php" method="POST">
<input name="url" type="url">
<input name="email" type="email">
<input name="number" type="number">
<input name="search" type="search">
<input name="color" type="color">
<input name="date" type="date">
<input type="submit" name="submit_button" value="Submit">
</form>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<title>HTML Decoding Test</title>
</head>
<body>
<div>
<span custom-attr="&amp;">some text</span>
<form method="post" action="index.html">
<input value="&amp;"/>
<input type="submit" value="Send"/>
</form>
</div>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<iframe src="iframe_inner.html" name="subframe"></iframe>
<div id="text">
Main window div text
</div>
</body>
</html>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<body>
<div id="text">
iFrame div text
</div>
</body>
</html>

View file

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<title>Index page</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<h1>Extremely useless page</h1>
<div id="core">
<strong>Lorem</strong> ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim <strong>veniam</strong>, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla <strong class="super-duper">pariatur</strong>. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
<div id="empty">
An empty <em></em> tag should be rendered with both open and close tags.
</div>
<div id="some-element" data-href="http://mink.behat.org">
some <div>very
</div>
<em>interesting</em> text
</div>
<div class="attribute-testing">
<input type="text" id="attr-elem[with-value]" with-value="some-value"/>
<input type="text" id="attr-elem[without-value]" without-value/>
<input type="text" id="attr-elem[with-empty-value]" with-empty-value=""/>
<input type="text" id="attr-elem[with-missing]"/>
</div>
<div class="travers">
<div class="sub">el1</div>
<div class="sub">el2</div>
<div class="sub">
<a href="some_url">some <strong>deep</strong> url</a>
</div>
</div>
<div class="sub">el4</div>
</div>
<footer>
<form id="search-form">
<input type="text" placeholder="Search site..." />
</form>
<form id="profile">
<div data-custom="something">
<label>
<input type="text" id="user-name" name="username" />
</label>
</div>
<input type="submit" />
</form>
</footer>
</body>
</html>

View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<body>
<?php
if ('1' === $_GET['p']) {
echo '<a href="issue130.php?p=2">Go to 2</a>';
} else {
echo '<strong>'.$_SERVER['HTTP_REFERER'].'</strong>';
}
?>
</body>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Issue 131</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<h1>There is a non breaking&#160;space</h1>
<pre id="foobar">Some accentués characters</pre>
<form>
<select name="foobar">
<option value="1">Gimme some accentués characters</option>
</select>
<input type="submit" />
</form>
</body>
</html>

View file

@ -0,0 +1,16 @@
<?php
if (!empty($_POST)) {
setcookie("tc", $_POST['cookie_value'], null, '/');
} elseif (isset($_GET["show_value"])) {
echo $_COOKIE["tc"];
die();
}
?>
<!DOCTYPE html>
<html>
<body>
<form method="post">
<input name="cookie_value">
<input type="submit" value="Set cookie">
</form>
</body>

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Index page</title>
</head>
<body>
<form action="#">
<div>
<input type="text" name="source" id="source"
onkeyup="document.getElementById('target').innerHTML = this.value" value="bar">
</div>
</form>
<div id="target"></div>
</body>
</html>

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>Index page</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<form action="#">
<select id="options-without-values" name="without">
<option>none selected</option>
<option id="one">One</option>
<option id="two">Two</option>
<option>Three</option>
</select>
<select id="options-with-values" name="with">
<option value="none">none selected</option>
<option value="one">One</option>
<option value="two">Two</option>
<option value="three">Three</option>
</select>
</form>
</body>
</html>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<title>Index page</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<form action="#">
<p>
<label for="phone">Téléphone</label>
<input type="text" name="phone" id="phone" />
</p>
<p>
<label for="daphone">DaPhone</label>
<input type="text" name="daphone" id="daphone" />
</p>
<input type="submit" value="Send" />
</form>
</body>
</html>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<body>
<form action="/" method="post" id="user-login-form">
<input type="submit" name="toto" id="jaguar-button" value="jaguar"/>
<input type="submit" name="toto" id="poney-button" value="poney"/>
</form>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Index page</title>
</head>
<body>
<form action="#">
<textarea rows="10" cols="10" id="textarea">
foo
bar
</textarea>
</form>
</body>
</html>

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<title>Index page</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<script src="js/jquery-1.6.2-min.js"></script>
</head>
<body>
<button id="btn">Créer un compte</button>
<div id="panel"></div>
<script type="text/javascript">
$('#btn').click(function () {
$('#panel').text('OH ' + 'AIH!');
});
</script>
</body>
</html>

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Issue 255</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<script src="js/jquery-1.6.2-min.js"></script>
</head>
<body>
<form>
<label for="foo_select">Foo</label>
<select name="foo_select" id="foo_select">
<option value="1" selected="selected">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<input type="checkbox" id="foo_check" />
<input type="submit" />
<p id="output_foo_select"></p>
<p id="output_foo_check"></p>
</form>
<script type="text/javascript">
(function() {
$('#foo_select').change(function () {
$('#output_foo_select').text("onChangeSelect");
});
$('#foo_check').change(function () {
$('#output_foo_check').text("onChangeCheck");
});
})();
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,127 @@
/*!
* jQuery UI 1.8.14
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI
*/
(function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if("area"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:"a"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.14",
keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();
b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,
"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",
function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(n)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,
outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,"tabindex")))},tabbable:function(a){var b=c.attr(a,"tabindex"),d=isNaN(b);
return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=
0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&&c.ui.isOverAxis(b,e,i)}})}})(jQuery);
;/*!
* jQuery UI Widget 1.8.14
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Widget
*/
(function(b,j){if(b.cleanData){var k=b.cleanData;b.cleanData=function(a){for(var c=0,d;(d=a[c])!=null;c++)b(d).triggerHandler("remove");k(a)}}else{var l=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add([this]).each(function(){b(this).triggerHandler("remove")});return l.call(b(this),a,c)})}}b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,
a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend(true,{},c.options);b[e][a].prototype=b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.charAt(0)==="_")return h;
e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==j){h=i;return false}}):this.each(function(){var g=b.data(this,a);g?g.option(d||{})._init():b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){b.data(c,this.widgetName,this);this.element=b(c);this.options=b.extend(true,{},this.options,
this._getCreateOptions(),a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},
widget:function(){return this.element},option:function(a,c){var d=a;if(arguments.length===0)return b.extend({},this.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}this._setOptions(d);return this},_setOptions:function(a){var c=this;b.each(a,function(d,e){c._setOption(d,e)});return this},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},
enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
;/*!
* jQuery UI Mouse 1.8.14
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Mouse
*
* Depends:
* jquery.ui.widget.js
*/
(function(b){var d=false;b(document).mousedown(function(){d=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(c){return a._mouseDown(c)}).bind("click."+this.widgetName,function(c){if(true===b.data(c.target,a.widgetName+".preventClickEvent")){b.removeData(c.target,a.widgetName+".preventClickEvent");c.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+
this.widgetName)},_mouseDown:function(a){if(!d){this._mouseStarted&&this._mouseUp(a);this._mouseDownEvent=a;var c=this,f=a.which==1,g=typeof this.options.cancel=="string"?b(a.target).closest(this.options.cancel).length:false;if(!f||g||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){c.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==
false;if(!this._mouseStarted){a.preventDefault();return true}}true===b.data(a.target,this.widgetName+".preventClickEvent")&&b.removeData(a.target,this.widgetName+".preventClickEvent");this._mouseMoveDelegate=function(e){return c._mouseMove(e)};this._mouseUpDelegate=function(e){return c._mouseUp(e)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);a.preventDefault();return d=true}},_mouseMove:function(a){if(b.browser.msie&&
!(document.documentMode>=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=
false;a.target==this._mouseDownEvent.target&&b.data(a.target,this.widgetName+".preventClickEvent",true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
;/*
* jQuery UI Draggable 1.8.14
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Draggables
*
* Depends:
* jquery.ui.core.js
* jquery.ui.mouse.js
* jquery.ui.widget.js
*/
(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper==
"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b=
this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;d(b.iframeFix===true?"iframe":b.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")});return true},_mouseStart:function(a){var b=this.options;this.helper=
this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});
this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);d.ui.ddmanager&&d.ui.ddmanager.dragStart(this,a);return true},
_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=
false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,
10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},_mouseUp:function(a){this.options.iframeFix===true&&d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)});d.ui.ddmanager&&d.ui.ddmanager.dragStop(this,a);return d.ui.mouse.prototype._mouseUp.call(this,a)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||
!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone().removeAttr("id"):this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&
a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=
this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),
10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),
10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[a.containment=="document"?0:d(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,a.containment=="document"?0:d(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,
(a.containment=="document"?0:d(window).scrollLeft())+d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a.containment=="document"?0:d(window).scrollTop())+(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&a.containment.constructor!=Array){a=d(a.containment);var b=a[0];if(b){a.offset();var c=d(b).css("overflow")!=
"hidden";this.containment=[(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0),(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0),(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),
10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom];this.relative_container=a}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+
this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&
!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,h=a.pageY;if(this.originalPosition){var g;if(this.containment){if(this.relative_container){g=this.relative_container.offset();g=[this.containment[0]+g.left,this.containment[1]+g.top,this.containment[2]+g.left,this.containment[3]+g.top]}else g=this.containment;if(a.pageX-this.offset.click.left<g[0])e=g[0]+this.offset.click.left;
if(a.pageY-this.offset.click.top<g[1])h=g[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>g[2])e=g[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>g[3])h=g[3]+this.offset.click.top}if(b.grid){h=b.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/b.grid[1])*b.grid[1]:this.originalPageY;h=g?!(h-this.offset.click.top<g[1]||h-this.offset.click.top>g[3])?h:!(h-this.offset.click.top<g[1])?h-b.grid[1]:h+b.grid[1]:h;e=b.grid[0]?this.originalPageX+Math.round((e-this.originalPageX)/
b.grid[0])*b.grid[0]:this.originalPageX;e=g?!(e-this.offset.click.left<g[0]||e-this.offset.click.left>g[2])?e:!(e-this.offset.click.left<g[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<
526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,
c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.14"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var h=d.data(this,"sortable");if(h&&!h.options.disabled){c.sortables.push({instance:h,shouldRevert:h.options.revert});
h.refreshPositions();h._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=
false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=d(f).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",true);
this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top;
c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&
this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("opacity"))b._opacity=
a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){if(!c.axis||c.axis!=
"x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-b.overflowOffset.left<
c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()-
c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable","snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this,
width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),f=c.options,e=f.snapTolerance,h=b.offset.left,g=h+c.helperProportions.width,n=b.offset.top,o=n+c.helperProportions.height,i=c.snapElements.length-1;i>=0;i--){var j=c.snapElements[i].left,l=j+c.snapElements[i].width,k=c.snapElements[i].top,m=k+c.snapElements[i].height;if(j-e<h&&h<l+e&&k-e<n&&n<m+e||j-e<h&&h<l+e&&k-e<o&&o<m+e||j-e<g&&g<l+e&&k-e<n&&n<m+e||j-e<g&&g<l+e&&k-e<o&&
o<m+e){if(f.snapMode!="inner"){var p=Math.abs(k-o)<=e,q=Math.abs(m-n)<=e,r=Math.abs(j-g)<=e,s=Math.abs(l-h)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:k-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:m,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:j-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:l}).left-c.margins.left}var t=
p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(k-n)<=e;q=Math.abs(m-o)<=e;r=Math.abs(j-h)<=e;s=Math.abs(l-g)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:k,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:m-c.helperProportions.height,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:j}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:l-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[i].snapping&&
(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[i].item}));c.snapElements[i].snapping=p||q||r||s||t}else{c.snapElements[i].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[i].item}));c.snapElements[i].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),
10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
;/*
* jQuery UI Droppable 1.8.14
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Droppables
*
* Depends:
* jquery.ui.core.js
* jquery.ui.widget.js
* jquery.ui.mouse.js
* jquery.ui.draggable.js
*/
(function(d){d.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var a=this.options,b=a.accept;this.isover=0;this.isout=1;this.accept=d.isFunction(b)?b:function(c){return c.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};d.ui.ddmanager.droppables[a.scope]=d.ui.ddmanager.droppables[a.scope]||[];d.ui.ddmanager.droppables[a.scope].push(this);
a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var a=d.ui.ddmanager.droppables[this.options.scope],b=0;b<a.length;b++)a[b]==this&&a.splice(b,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(a,b){if(a=="accept")this.accept=d.isFunction(b)?b:function(c){return c.is(b)};d.Widget.prototype._setOption.apply(this,arguments)},_activate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&
this.element.addClass(this.options.activeClass);b&&this._trigger("activate",a,this.ui(b))},_deactivate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);b&&this._trigger("deactivate",a,this.ui(b))},_over:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass);
this._trigger("over",a,this.ui(b))}},_out:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",a,this.ui(b))}},_drop:function(a,b){var c=b||d.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return false;var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var g=
d.data(this,"droppable");if(g.options.greedy&&!g.options.disabled&&g.options.scope==c.options.scope&&g.accept.call(g.element[0],c.currentItem||c.element)&&d.ui.intersect(c,d.extend(g,{offset:g.element.offset()}),g.options.tolerance)){e=true;return false}});if(e)return false;if(this.accept.call(this.element[0],c.currentItem||c.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop",
a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.14"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height;
switch(c){case "fit":return i<=e&&g<=k&&j<=f&&h<=l;case "intersect":return i<e+a.helperProportions.width/2&&g-a.helperProportions.width/2<k&&j<f+a.helperProportions.height/2&&h-a.helperProportions.height/2<l;case "pointer":return d.ui.isOver((a.positionAbs||a.position.absolute).top+(a.clickOffset||a.offset.click).top,(a.positionAbs||a.position.absolute).left+(a.clickOffset||a.offset.click).left,j,i,b.proportions.height,b.proportions.width);case "touch":return(f>=j&&f<=l||h>=j&&h<=l||f<j&&h>l)&&(e>=
i&&e<=k||g>=i&&g<=k||e<i&&g>k);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f<c.length;f++)if(!(c[f].options.disabled||a&&!c[f].accept.call(c[f].element[0],a.currentItem||a.element))){for(var h=0;h<g.length;h++)if(g[h]==c[f].element[0]){c[f].proportions.height=0;continue a}c[f].visible=c[f].element.css("display")!=
"none";if(c[f].visible){e=="mousedown"&&c[f]._activate.call(c[f],b);c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight}}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem||
a.element)){this.isout=1;this.isover=0;this._deactivate.call(this,b)}}});return c},dragStart:function(a,b){a.element.parentsUntil("body").bind("scroll.droppable",function(){a.options.refreshPositions||d.ui.ddmanager.prepareOffsets(a,b)})},drag:function(a,b){a.options.refreshPositions&&d.ui.ddmanager.prepareOffsets(a,b);d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var c=d.ui.intersect(a,this,this.options.tolerance);if(c=
!c&&this.isover==1?"isout":c&&this.isover==0?"isover":null){var e;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");if(g.length){e=d.data(g[0],"droppable");e.greedyChild=c=="isover"?1:0}}if(e&&c=="isover"){e.isover=0;e.isout=1;e._out.call(e,b)}this[c]=1;this[c=="isout"?"isover":"isout"]=0;this[c=="isover"?"_over":"_out"].call(this,b);if(e&&c=="isout"){e.isout=0;e.isover=1;e._over.call(e,b)}}}})},dragStop:function(a,b){a.element.parentsUntil("body").unbind("scroll.droppable");
a.options.refreshPositions||d.ui.ddmanager.prepareOffsets(a,b)}}})(jQuery);
;

View file

@ -0,0 +1,114 @@
<!DOCTYPE html>
<html>
<head>
<title>JS elements test</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<style>
#draggable {
width: 100px; height: 100px; padding: 0.5em; float: left; margin: 10px 10px 10px 0;
background:#ccc;
opacity:0.5;
}
#droppable {
width: 150px; height: 150px; padding: 0.5em; float: left; margin: 10px;
background:#eee;
}
#waitable {
width: 150px; height: 150px; padding: 0.5em; float: left; margin: 10px;
background:#eee;
}
</style>
</head>
<body>
<div class="elements">
<div id="clicker">not clicked</div>
<div id="mouseover-detector">no mouse action detected</div>
<div id="invisible" style="display: none">invisible man</div>
<input id="focus-blur-detector" type="text" value="no action detected"/>
<input class="input first" type="text" value="" />
<input class="input second" type="text" value="" />
<input class="input third" type="text" value="" />
<div class="text-event"></div>
</div>
<div id="draggable" class="ui-widget-content"></div>
<div id="droppable" class="ui-widget-header">
<p>Drop here</p>
</div>
<div id="waitable"></div>
<script src="js/jquery-1.6.2-min.js"></script>
<script src="js/jquery-ui-1.8.14.custom.min.js"></script>
<script>
$(document).ready(function() {
var $clicker = $('#clicker');
$clicker.click(function() {
$(this).text('single clicked');
});
$clicker.dblclick(function() {
$(this).text('double clicked');
});
$clicker.bind('contextmenu', function() {
$(this).text('right clicked');
});
var $focusDetector = $('#focus-blur-detector');
$focusDetector.focus(function() {
$(this).val('focused');
});
$focusDetector.blur(function() {
$(this).val('blured');
});
$('#mouseover-detector').mouseover(function() {
$(this).text('mouse overed');
});
$('.elements input.input.first').keydown(function(ev) {
$('.text-event').text('key downed:' + ev.altKey * 1 + ' / ' + ev.ctrlKey * 1 + ' / ' + ev.shiftKey * 1 + ' / ' + ev.metaKey * 1);
});
$('.elements input.input.second').keypress(function(ev) {
$('.text-event').text('key pressed:' + ev.which + ' / ' + ev.altKey * 1 + ' / ' + ev.ctrlKey * 1 + ' / ' + ev.shiftKey * 1 + ' / ' + ev.metaKey * 1);
});
$('.elements input.input.third').keyup(function(ev) {
$('.text-event').text('key upped:' + ev.which + ' / ' + ev.altKey * 1 + ' / ' + ev.ctrlKey * 1 + ' / ' + ev.shiftKey * 1 + ' / ' + ev.metaKey * 1);
});
$( "#draggable" ).draggable();
$( "#droppable" ).droppable({
drop: function( event, ui ) {
$( this ).find( "p" ).html( "Dropped!" );
}
});
var t1, t2;
$('#waitable').click(function() {
var el = $(this);
el.html('');
clearTimeout(t1);
clearTimeout(t2);
t1 = setTimeout(function() {
el.html('<div>arrived</div>');
}, 1000);
t2 = setTimeout(function() {
el.html('<div>timeout</div>');
}, 2000);
});
});
</script>
</body>
</html>

View file

@ -0,0 +1,7 @@
<?php
echo json_encode(array(
'key1' => 'val1',
'key2' => 234,
'key3' => array(1, 2, 3)
));

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>Links page</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<a href="redirector.php">Redirect me to</a>
<a href="randomizer.php">Random number page</a>
<a href="links.html?quoted">Link with a '</a>
<a href="basic_form.html">
<img src="basic_form" alt="basic form image"/>
</a>
</body>
</html>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<title>Multi input Test</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<h1>Multi input Test</h1>
<form method="POST" action="advanced_form_post.php">
<label>
First
<input type="text" name="tags[]" value="tag1">
</label>
<label>
Second
<input type="text" name="tags[]" value="tag2">
</label>
<label>
Third
<input type="text" name="tags[]" value="tag1">
</label>
<input type="submit" name="submit" value="Register" />
</form>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<title>Multicheckbox Test</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<h1>Multicheckbox Test</h1>
<form method="POST" action="advanced_form_post.php">
<input type="checkbox" name="mail_types[]" checked="checked" value="update"/>
<input type="checkbox" name="mail_types[]" value="spam"/>
<input type="submit" name="submit" value="Register" />
</form>
</body>
</html>

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<title>Multiselect Test</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<h1>Multiselect Test</h1>
<form method="POST" action="advanced_form_post.php">
<select name="select_number">
<option value="10">ten</option>
<option selected="selected" value="20">twenty</option>
<option value="30">thirty</option>
</select>
<select name="select_multiple_numbers[]" multiple="multiple">
<option value="1">one</option>
<option value="2">two</option>
<option value="3">three</option>
</select>
<select name="select_multiple_values[]" multiple="multiple">
<option value="1">one</option>
<option value="2" selected="selected">two</option>
<option value="3" selected="selected">three</option>
</select>
<input type="submit" name="submit" value="Register" />
</form>
</body>
</html>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title>popup_1</title>
</head>
<body>
<div id="text">
Popup#1 div text
</div>
</body>
</html>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title>popup_2</title>
</head>
<body>
<div id="text">
Popup#2 div text
</div>
</body>
</html>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>Cookies page</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<?php echo str_replace('>', '', var_export($_COOKIE, true)); ?>
</body>
</html>

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Radio group</title>
</head>
<body>
<form id="form1">
<input name="group1" type="radio" value="set" id="first" checked="checked">
<input name="group1" type="radio" value="updated" id="second">
<input name="reused" type="radio" value="test" id="reused_form1">
<input name="reused" type="radio" value="test2" id="reused2_form1" checked="checked">
</form>
<form id="form2">
<input name="reused" type="radio" value="test3" id="reused_form2" checked="checked">
<input name="reused" type="radio" value="test4" id="reused2_form2">
</form>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Index page</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<h1 id="number"><?php echo rand() ?></h1>
</body>
</html>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>Redirect destination</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
You were redirected!
</body>
</html>

View file

@ -0,0 +1,3 @@
<?php
header('location: redirect_destination.html');

View file

@ -0,0 +1,15 @@
<?php
header('X-Mink-Test: response-headers');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Response headers</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<h1>Response headers</h1>
</body>
</html>

View file

@ -0,0 +1,18 @@
<?php
session_name('_SESS');
session_start();
if (isset($_GET['login'])) {
session_regenerate_id();
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Session Test</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<div id="session-id"><?php echo session_id() ?></div>
</body>
</html>

View file

@ -0,0 +1 @@
1 uploaded file

View file

@ -0,0 +1,4 @@
<?php
$cookieAtRootPath = false;
$cookieValue = 'srv_var_is_set_sub_folder';
require_once __DIR__ . '/../' . basename(__FILE__);

View file

@ -0,0 +1,2 @@
<?php
require_once __DIR__ . '/../' . basename(__FILE__);

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<body>
<script>
function newPopup(url, title) {
popupWindow = window.open(
url, title,'height=100,width=200,left=10,top=10,resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=yes'
);
}
</script>
<a href="popup1.html" onclick="newPopup(this.href, 'popup_1'); return false;">
Popup #1
</a>
<a href="popup2.html" onclick="newPopup(this.href, 'popup_2'); return false;">
Popup #2
</a>
<div id="text">
Main window div text
</div>
</body>
</html>

125
vendor/behat/mink/phpdoc.ini.dist vendored Normal file
View file

@ -0,0 +1,125 @@
; Default configuration file for PHPDoctor
; This config file will cause PHPDoctor to generate API documentation of
; itself.
; PHPDoctor settings
; -----------------------------------------------------------------------------
; Names of files to parse. This can be a single filename, or a comma separated
; list of filenames. Wildcards are allowed.
files = "*.php"
; Names of files or directories to ignore. This can be a single filename, or a
; comma separated list of filenames. Wildcards are NOT allowed.
ignore = "CVS, .svn, .git, _compiled"
; The directory to look for files in, if not used the PHPDoctor will look in
; the current directory (the directory it is run from).
source_path = "./src"
; If you do not want PHPDoctor to look in each sub directory for files
; uncomment this line.
;subdirs = off
; Set how loud PHPDoctor is as it runs. Quiet mode suppresses all output other
; than warnings and errors. Verbose mode outputs additional messages during
; execution.
;quiet = on
;verbose = on
; Select the doclet to use for generating output.
doclet = standard
;doclet = debug
; The directory to find the doclet in. Doclets are expected to be in a
; directory named after themselves at the location given.
;doclet_path = ./doclets
; The directory to find taglets in. Taglets allow you to make PHPDoctor handle
; new tags and to alter the behavour of existing tags and their output.
;taglet_path = ./taglets
; If the code you are parsing does not use package tags or not all elements
; have package tags, use this setting to place unbound elements into a
; particular package.
default_package = "Behat\Mink"
; Specifies the name of a HTML file containing text for the overview
; documentation to be placed on the overview page. The path is relative to
; "source_path" unless an absolute path is given.
overview = readme.html
; Package comments will be looked for in a file named package.html in the same
; directory as the first source file parsed in that package or in the directory
; given below. If package comments are placed in the directory given below then
; they should be named "<packageName>.html".
package_comment_dir = ./
; Parse out global variables and/or global constants?
;globals = off
;constants = off
; Generate documentation for all class members
;private = on
; Generate documentation for public and protected class members
;protected = on
; Generate documentation for only public class members
public = on
; Use the PEAR compatible handling of the docblock first sentence
;pear_compat = on
; Standard doclet settings
; -----------------------------------------------------------------------------
; The directory to place generated documentation in. If the given path is
; relative to it will be relative to "source_path".
d = "api"
; Specifies the title to be placed in the HTML <title> tag.
windowtitle = "Behat\Mink"
; Specifies the title to be placed near the top of the overview summary file.
doctitle = "Behat\Mink: browser emulators abstraction library for PHP"
; Specifies the header text to be placed at the top of each output file. The
; header will be placed to the right of the upper navigation bar.
header = "Behat\Mink"
; Specifies the footer text to be placed at the bottom of each output file. The
; footer will be placed to the right of the lower navigation bar.
footer = "Behat\Mink"
; Specifies the text to be placed at the bottom of each output file. The text
; will be placed at the bottom of the page, below the lower navigation bar.
;bottom = "This document was generated by <a href="http://phpdoctor.sourceforge.net/">PHPDoctor: The PHP Documentation Creator</a>"
; Create a class tree?
tree = on

15
vendor/behat/mink/phpunit.xml.dist vendored Normal file
View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="Behat Mink test suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src</directory>
</whitelist>
</filter>
</phpunit>

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;
}
}

Some files were not shown because too many files have changed in this diff Show more