Commit de3b291a7d484d2eb2670f9e384d72f718051cdd

Authored by 王子强
1 parent 3a5ed823

rm gi submodule

Showing 37 changed files with 4587 additions and 1 deletions

Too many changes to show.

To preserve performance only 37 of 59 files are displayed.

mink @ 04ab7af6
1   -Subproject commit 04ab7af68536ac2c80fd6c08a6fd3620d3409891
  1 +/tests export-ignore
  2 +.gitattributes export-ignore
  3 +.gitignore export-ignore
  4 +.travis.yml export-ignore
  5 +CONTRIBUTING.md export-ignore
  6 +phpdoc.ini.dist export-ignore
  7 +phpunit.xml.dist export-ignore
... ...
  1 +*.tgz
  2 +*.phar
  3 +phpunit.xml
  4 +composer.lock
  5 +vendor
... ...
  1 +language: php
  2 +
  3 +sudo: false
  4 +
  5 +php: [5.4, 5.5, 5.6, 7.0, 7.1, 7.2]
  6 +
  7 +matrix:
  8 + fast_finish: true
  9 + include:
  10 + - php: 5.3
  11 + dist: precise
  12 + - php: 7.1
  13 + env: COMPOSER_FLAGS='--prefer-lowest --prefer-stable' SYMFONY_DEPRECATIONS_HELPER=weak
  14 + - php: 7.2
  15 + env: DEPENDENCIES=dev
  16 +
  17 +cache:
  18 + directories:
  19 + - $HOME/.composer/cache/files
  20 + - $HOME/symfony-bridge/.phpunit
  21 +
  22 +before_install:
  23 + - if [ "$DEPENDENCIES" = "dev" ]; then composer config minimum-stability dev; fi;
  24 +
  25 +install:
  26 + - composer update $COMPOSER_FLAGS
  27 + - vendor/bin/simple-phpunit install
  28 +
  29 +script: vendor/bin/simple-phpunit -v --coverage-clover=coverage.clover
  30 +
  31 +after_script:
  32 + - wget https://scrutinizer-ci.com/ocular.phar
  33 + - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
... ...
  1 +1.7.1 / 2016-03-05
  2 +==================
  3 +
  4 +Bug fixes:
  5 +
  6 +* Refactored the CssSelector to use the new API of the Symfony CssSelector component to be compatible with Symfony 3
  7 +
  8 +
  9 +Testsuite:
  10 +
  11 +* Disallowed failures on PHP 7 on Travis (tests were passing since a long time)
  12 +
  13 +Driver testsuite:
  14 +
  15 +* Fixed the driver testsuite to account for driver inheritance when checking recommended practices
  16 +* Added a test for cookie values with semicolon, to ensure all drivers support it
  17 +* Improved the window resize test to consider headless browsers
  18 +* Fixed the compatibility of the testsuite with PHPUnit 5
  19 +* Added a test ensuring that `wait()` always return a boolean even when the JS expression does not cast the value
  20 +* Added HTML escaping of submitted values in the driver testsuite web-fixtures
  21 +
  22 +Misc:
  23 +
  24 +* Removed the Mink testsuite from archives generated by Github to make them smaller
  25 +
  26 +1.7.0 / 2015-09-20
  27 +==================
  28 +
  29 +New features:
  30 +
  31 +* Added `Session::getResponseHeader` to access a response header easily
  32 +* Added support for header assertions
  33 +* Added a forward compatibility layer for drivers to allow them to prepare
  34 + for Mink 2.0 (they won't require any change if they use it). They should
  35 + now overwrite `CoreDriver::findElementXpaths` instead of implementing `find`
  36 + and `setSession` themselves.
  37 +* Added escaping of the locator in the NamedSelector rather than expecting
  38 + the caller to perform the escaping. Passing an escaped locator is still
  39 + supported but deprecated.
  40 +* Remove the dependency on the Session in expectation exceptions. Passing
  41 + the session in the exception constructor is now deprecated. The driver
  42 + should be passed instead.
  43 +
  44 +Bug fixes:
  45 +
  46 +* Fixed the URL assertions when comparing paths ending in ``.php``
  47 +* Silenced deprecation warnings (following the Symfony convention) to make
  48 + them less invasive. Use the `symfony/phpunit-bridge` to get them reported
  49 + when using Mink in your PHPUnit tests.
  50 +* Fixed `NodeElement::hasClass` in case the class attribute contains newlines
  51 +
  52 +Testsuite:
  53 +
  54 +* Made the testsuite compatible with PHPUnit strict timing mode (only the library testsuite, not the driver one)
  55 +* Added testing against PHP 7
  56 +* Added testing against lowest version of dependencies to ensure we got the lower bounds right
  57 +
  58 +Driver testsuite:
  59 +
  60 +* Added an extra test to ensure the right behavior when getting the HTML with empty elements
  61 +* Added a few more safeguards to ensure test failures rather than fatal errors for misbehaving drivers
  62 +* Added a test ensuring that drivers follow recommended practices
  63 +
  64 +Misc:
  65 +
  66 +* Added a few missing deprecation warnings for deprecated APIs or classes.
  67 +
  68 +1.6.1 / 2015-02-04
  69 +==================
  70 +
  71 +Bug fixes:
  72 +
  73 +* Added a check for empty path in `WebAssert::cleanUrl()`
  74 +
  75 +Driver testsuite:
  76 +
  77 +* Added an extra test to ensure the right behavior for traversal
  78 +
  79 +Misc:
  80 +
  81 +* Changed the description in the composer.json
  82 +* Switched the repository structure to use PSR-4
  83 +* Updated URLs for the move to the new Github organization
  84 +
  85 +1.6.0 / 2014-09-26
  86 +==================
  87 +
  88 + * [BC break] Changed the named selector to prefer exact matches over partial matches
  89 + * [BC break] Changed `NodeElement::getValue` for checkboxes to return the value rather than the checked state (use `isChecked` for that)
  90 + * Fixed the XPath prefixing when searching inside an existing element
  91 + * Refactored the driver testsuite entirely and expand it to cover drivers entirely (covering many more cases for consistency)
  92 + * Changed `NodeElement::setValue` to support any fields rather than only input elements
  93 + * Removed the wrapping of any driver-level exception in a MinkException on invalid usage as it was making the code too complex
  94 + * Fixed the matching of the input type in the named selector to be case insensitive according to the HTML spec
  95 + * Introduced `Behat\Mink\Selector\Xpath\Escaper` to allow reusing the XPath escaping
  96 + * Deprecated `Element::getSession`. Code needing the session should get it from outside rather than the element
  97 + * Changed ElementNotFoundException to extend from ExpectationException
  98 + * Added `Element::getOuterHtml` to get the HTML code of the element including itself
  99 + * Fixed the name selectors to match on the `placeholder` only for textual inputs
  100 + * Enforced consistent behavior for drivers on 4xx and 5xx response to return the response rather than throwing an exception
  101 + * Added `Element::waitFor` to allow retrying some code until it succeeds or the timeout is reached
  102 + * Added `Element::isValid` to check whether an element still exists in the page
  103 + * Made `Session::executeScript` compatible across drivers by ensuring they all support the same syntaxes for the JS expression
  104 + * Made `Session::evaluateScript` compatible across drivers by ensuring they all support the same syntaxes for the JS expression
  105 + * Removed `hasClass` from `DocumentElement` (instead of triggering a fatal error)
  106 + * Added testing on HHVM to ensure consistency
  107 + * Fixed `NodeElement::getTagName` to ensure that the tag name is lowercase for all drivers
  108 + * Fixed `Element::hasAttribute` to ensure it supports attributes with an empty value
  109 + * Fixed the `field` selector to avoid matching inputs with the type `submit` or `reset`
  110 + * Changed the button XPath selection to accept `reset` buttons as well
  111 + * Changed `Session::wait` to return the condition value rather than nothing
  112 + * Added `Session::getWindowName` and `Session::getWindowNames` to get the name of the current and of all windows
  113 + * Added `Session::maximizeWindow` to maximize the window
  114 + * Added `NodeElement::isSelected` to check whether an `<option>` is selected
  115 + * Added `NodeElement::submitForm` to allow submitting a form without using a button
  116 + * Added assertions about the value of an attribute
  117 + * Added the anchor in the assertion on the URL in `WebAssert`
  118 +
  119 +1.5.0 / 2013-04-14
  120 +==================
  121 +
  122 + * Add `CoreDriver` to simplify future drivers improvements
  123 + * Add `Mink::isSessionStarted()` method
  124 + * Fix multibite string `preg_replace` bugs
  125 + * Fix handling of whitespaces in `WebAssert::pageText...()` methods
  126 +
  127 +1.4.3 / 2013-03-02
  128 +==================
  129 +
  130 + * Bump dependencies constraints
  131 +
  132 +1.4.2 / 2013-02-13
  133 +==================
  134 +
  135 + * Fix wrong test case to ensure that core drivers work as expected
  136 +
  137 +1.4.1 / 2013-02-10
  138 +==================
  139 +
  140 + * Update dependencies
  141 + * Add ElementException to element actions
  142 + * Rel attribute support for named selectors
  143 + * Add hasClass() helper to traversable elements
  144 + * Add getScreenshot() method to session
  145 + * Name attr support in named selector for button
  146 + * Fix for bunch of bugs
  147 +
  148 +1.4.0 / 2012-05-40
  149 +==================
  150 +
  151 + * New `Session::selectWindow()` and `Session::selectIFrame()` methods
  152 + * New built-in `WebAssert` class
  153 + * Fixed DocBlocks (autocompletion in any IDE now should just work)
  154 + * Moved Behat-related code into `Behat\MinkExtension`
  155 + * Removed PHPUnit test case class
  156 + * Updated composer dependencies to not require custom repository anymore
  157 + * All drivers moved into separate packages
  158 +
  159 +1.3.3 / 2012-03-23
  160 +==================
  161 +
  162 + * Prevent exceptions in `__toString()`
  163 + * Added couple of useful step definitions for Behat
  164 + * Fixed issues #168, #211, #212, #208
  165 + * Lot of small bug fixes and improvements
  166 + * Fixed dependencies and composer installation routine
  167 +
  168 +1.3.2 / 2011-12-21
  169 +==================
  170 +
  171 + * Fixed webdriver registration in MinkContext
  172 +
  173 +1.3.1 / 2011-12-21
  174 +==================
  175 +
  176 + * Fixed Composer package
  177 +
  178 +1.3.0 / 2011-12-21
  179 +==================
  180 +
  181 + * Brand new Selenium2Driver (webdriver session)
  182 + * Multiselect bugfixes
  183 + * ZombieDriver back in the business
  184 + * Composer now manages dependencies
  185 + * Some MinkContext steps got fixes
  186 + * Lots of bug fixes and cleanup
  187 +
  188 +1.2.0 / 2011-11-04
  189 +==================
  190 +
  191 + * Brand new SeleniumDriver (thanks @alexandresalome)
  192 + * Multiselect support (multiple options selection), including new Behat steps
  193 + * Ability to select option by it's text (in addition to value)
  194 + * ZombieDriver updates
  195 + * Use SuiteHooks to populate parameters (no need to call parent __construct anymore)
  196 + * Updated Goutte and all vendors
  197 + * Lot of bugfixes and new tests
  198 +
  199 +1.1.1 / 2011-08-12
  200 +==================
  201 +
  202 + * Fixed Zombie.js server termination on Linux
  203 + * Fixed base_url usage for external URLs
  204 +
  205 +1.1.0 / 2011-08-08
  206 +==================
  207 +
  208 + * Added Zombie.js driver (thanks @b00giZm)
  209 + * Added pt translation (thanks Daniel Gomes)
  210 + * Refactored MinkContext and MinkTestCase
  211 +
  212 +1.0.3 / 2011-08-02
  213 +==================
  214 +
  215 + * File uploads for empty fields fixed (GoutteDriver)
  216 + * Lazy sessions restart
  217 + * `show_tmp_dir` option in MinkContext
  218 + * Updated to stable Symfony2 components
  219 + * SahiClient connection limit bumped to 60 seconds
  220 + * Dutch language support
  221 +
  222 +1.0.2 / 2011-07-22
  223 +==================
  224 +
  225 + * ElementHtmlException fixed (thanks @Stof)
  226 +
  227 +1.0.1 / 2011-07-21
  228 +==================
  229 +
  230 + * Fixed buggy assertions in MinkContext
  231 +
  232 +1.0.0 / 2011-07-20
  233 +==================
  234 +
  235 + * Added missing tests for almost everything
  236 + * Hude speedup for SahiDriver
  237 + * Support for Behat 2.0 contexts
  238 + * Bundled PHPUnit TestCase
  239 + * Deep element traversing
  240 + * Correct behavior of getText() method
  241 + * New getHtml() method
  242 + * Basic HTTP auth support
  243 + * Soft and hard session resetting
  244 + * Cookies management
  245 + * Browser history interactions (reload(), back(), forward())
  246 + * Weaverryan'd exception messages
  247 + * Huge amount of bugfixes and small additions
  248 +
  249 +0.3.2 / 2011-06-20
  250 +==================
  251 +
  252 + * Fixed file uploads in Goutte driver
  253 + * Fixed setting of long texts into fields
  254 + * Added getPlainText() (returns text without tags and whitespaces) method to the element's API
  255 + * Start_url is now optional parameter
  256 + * Default session (if needed) name now need to be always specified by hands with setDefaultSessionName()
  257 + * default_driver => default_session
  258 + * Updated Symfony Components
  259 +
  260 +0.3.1 / 2011-05-17
  261 +==================
  262 +
  263 + * Small SahiClient update (it generates SID now if no provided)
  264 + * setActiveSessionName => setDefaultSessionName method rename
  265 +
  266 +0.3.0 / 2011-05-17
  267 +==================
  268 +
  269 + * Rewritten from scratch Mink drivers handler. Now it's sessions handler. And Mink now
  270 + sessions-centric tool. See examples in readme. Much cleaner API now.
  271 +
  272 +0.2.4 / 2011-05-12
  273 +==================
  274 +
  275 + * Fixed wrong url locator function
  276 + * Fixed wrong regex in `should see` step
  277 + * Fixed delimiters use in `should see` step
  278 + * Added url-match step for checking urls against regex
  279 +
  280 +0.2.3 / 2011-05-01
  281 +==================
  282 +
  283 + * Updated SahiClient with new version, which is faster and cleaner with it's exceptions
  284 +
  285 +0.2.2 / 2011-05-01
  286 +==================
  287 +
  288 + * Ability to use already started browser as SahiDriver aim
  289 + * Added japanese translation for bundled steps (thanks @hidenorigoto)
  290 + * 10 seconds limit for browser connection in SahiDriver
  291 +
  292 +0.2.1 / 2011-04-21
  293 +==================
  294 +
  295 + * Fixed some bundled step definitions
  296 +
  297 +0.2.0 / 2011-04-21
  298 +==================
  299 +
  300 + * Additional step definitions
  301 + * Support for extended drivers configuration through behat.yml environment parameters
  302 + * Lots of new named selectors
  303 + * Bug fixes
  304 + * Small improvements
  305 +
  306 +0.1.2 / 2011-04-08
  307 +==================
  308 +
  309 + * Fixed Sahi url escaping
  310 +
  311 +0.1.1 / 2011-04-06
  312 +==================
  313 +
  314 + * Fixed should/should_not steps
  315 + * Added spanish translation
  316 + * Fixed forms to use <base> element
  317 + * Fixed small UnsupportedByDriverException issue
  318 +
  319 +0.1.0 / 2011-04-04
  320 +==================
  321 +
  322 + * Initial release
... ...
  1 +# Contributing
  2 +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:
  3 +
  4 +## Submitting an issues
  5 +- __Driver-related__ issues must be reported in the corresponding driver repository
  6 +- A reproducible example is required for every bug report, otherwise it will most probably be __closed without warning__
  7 +- If you are going to make a big, substantial change, let's discuss it first
  8 +
  9 +## Working with Pull Requests
  10 +1. Create your feature addition or a bug fix branch based on `master` branch in your repository's fork.
  11 +2. Make necessary changes, but __don't mix__ code reformatting with code changes on topic.
  12 +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.
  13 +4. Commit your code, but do not mess with `CHANGES.md`.
  14 +5. Squash your commits by topic to preserve a clean and readable log.
  15 +6. Create Pull Request.
  16 +
  17 +# Running tests
  18 +Make sure that you don't break anything with your changes by running:
  19 +
  20 +```bash
  21 +$> phpunit
  22 +```
... ...
  1 +Copyright (c) 2011-2015 Konstantin Kudryashov <ever.zet@gmail.com>
  2 +
  3 +Permission is hereby granted, free of charge, to any person
  4 +obtaining a copy of this software and associated documentation
  5 +files (the "Software"), to deal in the Software without
  6 +restriction, including without limitation the rights to use,
  7 +copy, modify, merge, publish, distribute, sublicense, and/or sell
  8 +copies of the Software, and to permit persons to whom the
  9 +Software is furnished to do so, subject to the following
  10 +conditions:
  11 +
  12 +The above copyright notice and this permission notice shall be
  13 +included in all copies or substantial portions of the Software.
  14 +
  15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  17 +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  19 +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  20 +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22 +OTHER DEALINGS IN THE SOFTWARE.
... ...
  1 +Mink
  2 +====
  3 +[![Latest Stable Version](https://poser.pugx.org/behat/mink/v/stable.svg)](https://packagist.org/packages/behat/mink)
  4 +[![Latest Unstable Version](https://poser.pugx.org/behat/mink/v/unstable.svg)](https://packagist.org/packages/behat/mink)
  5 +[![Total Downloads](https://poser.pugx.org/behat/mink/downloads.svg)](https://packagist.org/packages/behat/mink)
  6 +[![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)
  7 +[![Code Coverage](https://scrutinizer-ci.com/g/minkphp/Mink/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/minkphp/Mink/)
  8 +[![Build Status](https://travis-ci.org/minkphp/Mink.svg?branch=master)](https://travis-ci.org/minkphp/Mink)
  9 +[![SensioLabsInsight](https://insight.sensiolabs.com/projects/5bb8fab0-978f-428a-ae23-44ee4e129fbc/mini.png)](https://insight.sensiolabs.com/projects/5bb8fab0-978f-428a-ae23-44ee4e129fbc)
  10 +[![License](https://poser.pugx.org/behat/mink/license.svg)](https://packagist.org/packages/behat/mink)
  11 +
  12 +
  13 +Useful Links
  14 +------------
  15 +
  16 +- The main website with documentation is at [http://mink.behat.org](http://mink.behat.org)
  17 +- Official Google Group is at [http://groups.google.com/group/behat](http://groups.google.com/group/behat)
  18 +- IRC channel on [#freenode](http://freenode.net/) is `#behat`
  19 +- [Note on Patches/Pull Requests](CONTRIBUTING.md)
  20 +
  21 +Usage Example
  22 +-------------
  23 +
  24 +``` php
  25 +<?php
  26 +
  27 +use Behat\Mink\Mink,
  28 + Behat\Mink\Session,
  29 + Behat\Mink\Driver\GoutteDriver,
  30 + Behat\Mink\Driver\Goutte\Client as GoutteClient;
  31 +
  32 +$startUrl = 'http://example.com';
  33 +
  34 +// init Mink and register sessions
  35 +$mink = new Mink(array(
  36 + 'goutte1' => new Session(new GoutteDriver(new GoutteClient())),
  37 + 'goutte2' => new Session(new GoutteDriver(new GoutteClient())),
  38 + 'custom' => new Session(new MyCustomDriver($startUrl))
  39 +));
  40 +
  41 +// set the default session name
  42 +$mink->setDefaultSessionName('goutte2');
  43 +
  44 +// visit a page
  45 +$mink->getSession()->visit($startUrl);
  46 +
  47 +// call to getSession() without argument will always return a default session if has one (goutte2 here)
  48 +$mink->getSession()->getPage()->findLink('Downloads')->click();
  49 +echo $mink->getSession()->getPage()->getContent();
  50 +
  51 +// call to getSession() with argument will return session by its name
  52 +$mink->getSession('custom')->getPage()->findLink('Downloads')->click();
  53 +echo $mink->getSession('custom')->getPage()->getContent();
  54 +
  55 +// this all is done to make possible mixing sessions
  56 +$mink->getSession('goutte1')->getPage()->findLink('Chat')->click();
  57 +$mink->getSession('goutte2')->getPage()->findLink('Chat')->click();
  58 +```
  59 +
  60 +Install Dependencies
  61 +--------------------
  62 +
  63 +``` bash
  64 +$> curl -sS https://getcomposer.org/installer | php
  65 +$> php composer.phar install
  66 +```
  67 +
  68 +Contributors
  69 +------------
  70 +
  71 +* Konstantin Kudryashov [everzet](https://github.com/everzet) [lead developer]
  72 +* Christophe Coevoet [stof](https://github.com/stof) [lead developer]
  73 +* Alexander Obuhovich [aik099](https://github.com/aik099) [lead developer]
  74 +* Other [awesome developers](https://github.com/minkphp/Mink/graphs/contributors)
... ...
  1 +{
  2 + "name": "behat/mink",
  3 + "description": "Browser controller/emulator abstraction for PHP",
  4 + "keywords": ["web", "testing", "browser"],
  5 + "homepage": "http://mink.behat.org/",
  6 + "type": "library",
  7 + "license": "MIT",
  8 +
  9 + "authors": [
  10 + {
  11 + "name": "Konstantin Kudryashov",
  12 + "email": "ever.zet@gmail.com",
  13 + "homepage": "http://everzet.com"
  14 + }
  15 + ],
  16 +
  17 + "require": {
  18 + "php": ">=5.3.1",
  19 + "symfony/css-selector": "^2.7|^3.0|^4.0"
  20 + },
  21 +
  22 + "require-dev": {
  23 + "symfony/phpunit-bridge": "^3.3|^4.0"
  24 + },
  25 +
  26 + "suggest": {
  27 + "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)",
  28 + "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation",
  29 + "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)",
  30 + "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)"
  31 + },
  32 +
  33 + "autoload": {
  34 + "psr-4": {
  35 + "Behat\\Mink\\": "src/"
  36 + }
  37 + },
  38 +
  39 + "autoload-dev": {
  40 + "psr-4": {
  41 + "Behat\\Mink\\Tests\\": "tests"
  42 + }
  43 + },
  44 +
  45 + "extra": {
  46 + "branch-alias": {
  47 + "dev-master": "1.7.x-dev"
  48 + }
  49 + }
  50 +}
... ...
  1 +; Default configuration file for PHPDoctor
  2 +
  3 +; This config file will cause PHPDoctor to generate API documentation of
  4 +; itself.
  5 +
  6 +
  7 +; PHPDoctor settings
  8 +; -----------------------------------------------------------------------------
  9 +
  10 +; Names of files to parse. This can be a single filename, or a comma separated
  11 +; list of filenames. Wildcards are allowed.
  12 +
  13 +files = "*.php"
  14 +
  15 +; Names of files or directories to ignore. This can be a single filename, or a
  16 +; comma separated list of filenames. Wildcards are NOT allowed.
  17 +
  18 +ignore = "CVS, .svn, .git, _compiled"
  19 +
  20 +; The directory to look for files in, if not used the PHPDoctor will look in
  21 +; the current directory (the directory it is run from).
  22 +
  23 +source_path = "./src"
  24 +
  25 +; If you do not want PHPDoctor to look in each sub directory for files
  26 +; uncomment this line.
  27 +
  28 +;subdirs = off
  29 +
  30 +; Set how loud PHPDoctor is as it runs. Quiet mode suppresses all output other
  31 +; than warnings and errors. Verbose mode outputs additional messages during
  32 +; execution.
  33 +
  34 +;quiet = on
  35 +;verbose = on
  36 +
  37 +; Select the doclet to use for generating output.
  38 +
  39 +doclet = standard
  40 +;doclet = debug
  41 +
  42 +; The directory to find the doclet in. Doclets are expected to be in a
  43 +; directory named after themselves at the location given.
  44 +
  45 +;doclet_path = ./doclets
  46 +
  47 +; The directory to find taglets in. Taglets allow you to make PHPDoctor handle
  48 +; new tags and to alter the behavour of existing tags and their output.
  49 +
  50 +;taglet_path = ./taglets
  51 +
  52 +; If the code you are parsing does not use package tags or not all elements
  53 +; have package tags, use this setting to place unbound elements into a
  54 +; particular package.
  55 +
  56 +default_package = "Behat\Mink"
  57 +
  58 +; Specifies the name of a HTML file containing text for the overview
  59 +; documentation to be placed on the overview page. The path is relative to
  60 +; "source_path" unless an absolute path is given.
  61 +
  62 +overview = readme.html
  63 +
  64 +; Package comments will be looked for in a file named package.html in the same
  65 +; directory as the first source file parsed in that package or in the directory
  66 +; given below. If package comments are placed in the directory given below then
  67 +; they should be named "<packageName>.html".
  68 +
  69 +package_comment_dir = ./
  70 +
  71 +; Parse out global variables and/or global constants?
  72 +
  73 +;globals = off
  74 +;constants = off
  75 +
  76 +; Generate documentation for all class members
  77 +
  78 +;private = on
  79 +
  80 +; Generate documentation for public and protected class members
  81 +
  82 +;protected = on
  83 +
  84 +; Generate documentation for only public class members
  85 +
  86 +public = on
  87 +
  88 +; Use the PEAR compatible handling of the docblock first sentence
  89 +
  90 +;pear_compat = on
  91 +
  92 +; Standard doclet settings
  93 +; -----------------------------------------------------------------------------
  94 +
  95 +; The directory to place generated documentation in. If the given path is
  96 +; relative to it will be relative to "source_path".
  97 +
  98 +d = "api"
  99 +
  100 +; Specifies the title to be placed in the HTML <title> tag.
  101 +
  102 +windowtitle = "Behat\Mink"
  103 +
  104 +; Specifies the title to be placed near the top of the overview summary file.
  105 +
  106 +doctitle = "Behat\Mink: browser emulators abstraction library for PHP"
  107 +
  108 +; Specifies the header text to be placed at the top of each output file. The
  109 +; header will be placed to the right of the upper navigation bar.
  110 +
  111 +header = "Behat\Mink"
  112 +
  113 +; Specifies the footer text to be placed at the bottom of each output file. The
  114 +; footer will be placed to the right of the lower navigation bar.
  115 +
  116 +footer = "Behat\Mink"
  117 +
  118 +; Specifies the text to be placed at the bottom of each output file. The text
  119 +; will be placed at the bottom of the page, below the lower navigation bar.
  120 +
  121 +;bottom = "This document was generated by <a href="http://phpdoctor.sourceforge.net/">PHPDoctor: The PHP Documentation Creator</a>"
  122 +
  123 +; Create a class tree?
  124 +
  125 +tree = on
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +
  3 +<phpunit colors="true" bootstrap="vendor/autoload.php">
  4 + <testsuites>
  5 + <testsuite name="Behat Mink test suite">
  6 + <directory>tests</directory>
  7 + </testsuite>
  8 + </testsuites>
  9 +
  10 + <filter>
  11 + <whitelist>
  12 + <directory>./src</directory>
  13 + </whitelist>
  14 + </filter>
  15 +</phpunit>
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Driver;
  12 +
  13 +use Behat\Mink\Element\NodeElement;
  14 +use Behat\Mink\Exception\UnsupportedDriverActionException;
  15 +use Behat\Mink\Session;
  16 +
  17 +/**
  18 + * Core driver.
  19 + * All other drivers should extend this class for future compatibility.
  20 + *
  21 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  22 + */
  23 +abstract class CoreDriver implements DriverInterface
  24 +{
  25 + /**
  26 + * @var Session
  27 + */
  28 + private $session;
  29 +
  30 + /**
  31 + * {@inheritdoc}
  32 + */
  33 + public function setSession(Session $session)
  34 + {
  35 + $this->session = $session;
  36 + }
  37 +
  38 + /**
  39 + * {@inheritdoc}
  40 + */
  41 + public function start()
  42 + {
  43 + throw new UnsupportedDriverActionException('Starting the driver is not supported by %s', $this);
  44 + }
  45 +
  46 + /**
  47 + * {@inheritdoc}
  48 + */
  49 + public function isStarted()
  50 + {
  51 + throw new UnsupportedDriverActionException('Checking the driver state is not supported by %s', $this);
  52 + }
  53 +
  54 + /**
  55 + * {@inheritdoc}
  56 + */
  57 + public function stop()
  58 + {
  59 + throw new UnsupportedDriverActionException('Stopping the driver is not supported by %s', $this);
  60 + }
  61 +
  62 + /**
  63 + * {@inheritdoc}
  64 + */
  65 + public function reset()
  66 + {
  67 + throw new UnsupportedDriverActionException('Resetting the driver is not supported by %s', $this);
  68 + }
  69 +
  70 + /**
  71 + * {@inheritdoc}
  72 + */
  73 + public function visit($url)
  74 + {
  75 + throw new UnsupportedDriverActionException('Visiting an url is not supported by %s', $this);
  76 + }
  77 +
  78 + /**
  79 + * {@inheritdoc}
  80 + */
  81 + public function getCurrentUrl()
  82 + {
  83 + throw new UnsupportedDriverActionException('Getting the current url is not supported by %s', $this);
  84 + }
  85 +
  86 + /**
  87 + * {@inheritdoc}
  88 + */
  89 + public function getContent()
  90 + {
  91 + throw new UnsupportedDriverActionException('Getting the page content is not supported by %s', $this);
  92 + }
  93 +
  94 + /**
  95 + * {@inheritdoc}
  96 + */
  97 + public function find($xpath)
  98 + {
  99 + $elements = array();
  100 +
  101 + foreach ($this->findElementXpaths($xpath) as $xpath) {
  102 + $elements[] = new NodeElement($xpath, $this->session);
  103 + }
  104 +
  105 + return $elements;
  106 + }
  107 +
  108 + /**
  109 + * Finds elements with specified XPath query.
  110 + *
  111 + * @see find()
  112 + *
  113 + * @param string $xpath
  114 + *
  115 + * @return string[] The XPath of the matched elements
  116 + *
  117 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  118 + */
  119 + protected function findElementXpaths($xpath)
  120 + {
  121 + throw new UnsupportedDriverActionException('Finding elements is not supported by %s', $this);
  122 + }
  123 +
  124 + /**
  125 + * {@inheritdoc}
  126 + */
  127 + public function getTagName($xpath)
  128 + {
  129 + throw new UnsupportedDriverActionException('Getting the tag name is not supported by %s', $this);
  130 + }
  131 +
  132 + /**
  133 + * {@inheritdoc}
  134 + */
  135 + public function getText($xpath)
  136 + {
  137 + throw new UnsupportedDriverActionException('Getting the element text is not supported by %s', $this);
  138 + }
  139 +
  140 + /**
  141 + * {@inheritdoc}
  142 + */
  143 + public function getHtml($xpath)
  144 + {
  145 + throw new UnsupportedDriverActionException('Getting the element inner HTML is not supported by %s', $this);
  146 + }
  147 +
  148 + /**
  149 + * {@inheritdoc}
  150 + */
  151 + public function getOuterHtml($xpath)
  152 + {
  153 + throw new UnsupportedDriverActionException('Getting the element outer HTML is not supported by %s', $this);
  154 + }
  155 +
  156 + /**
  157 + * {@inheritdoc}
  158 + */
  159 + public function getAttribute($xpath, $name)
  160 + {
  161 + throw new UnsupportedDriverActionException('Getting the element attribute is not supported by %s', $this);
  162 + }
  163 +
  164 + /**
  165 + * {@inheritdoc}
  166 + */
  167 + public function getValue($xpath)
  168 + {
  169 + throw new UnsupportedDriverActionException('Getting the field value is not supported by %s', $this);
  170 + }
  171 +
  172 + /**
  173 + * {@inheritdoc}
  174 + */
  175 + public function setValue($xpath, $value)
  176 + {
  177 + throw new UnsupportedDriverActionException('Setting the field value is not supported by %s', $this);
  178 + }
  179 +
  180 + /**
  181 + * {@inheritdoc}
  182 + */
  183 + public function check($xpath)
  184 + {
  185 + throw new UnsupportedDriverActionException('Checking a checkbox is not supported by %s', $this);
  186 + }
  187 +
  188 + /**
  189 + * {@inheritdoc}
  190 + */
  191 + public function uncheck($xpath)
  192 + {
  193 + throw new UnsupportedDriverActionException('Unchecking a checkbox is not supported by %s', $this);
  194 + }
  195 +
  196 + /**
  197 + * {@inheritdoc}
  198 + */
  199 + public function isChecked($xpath)
  200 + {
  201 + throw new UnsupportedDriverActionException('Getting the state of a checkbox is not supported by %s', $this);
  202 + }
  203 +
  204 + /**
  205 + * {@inheritdoc}
  206 + */
  207 + public function selectOption($xpath, $value, $multiple = false)
  208 + {
  209 + throw new UnsupportedDriverActionException('Selecting an option is not supported by %s', $this);
  210 + }
  211 +
  212 + /**
  213 + * {@inheritdoc}
  214 + */
  215 + public function click($xpath)
  216 + {
  217 + throw new UnsupportedDriverActionException('Clicking on an element is not supported by %s', $this);
  218 + }
  219 +
  220 + /**
  221 + * {@inheritdoc}
  222 + */
  223 + public function attachFile($xpath, $path)
  224 + {
  225 + throw new UnsupportedDriverActionException('Attaching a file in an input is not supported by %s', $this);
  226 + }
  227 +
  228 + /**
  229 + * {@inheritdoc}
  230 + */
  231 + public function reload()
  232 + {
  233 + throw new UnsupportedDriverActionException('Page reloading is not supported by %s', $this);
  234 + }
  235 +
  236 + /**
  237 + * {@inheritdoc}
  238 + */
  239 + public function forward()
  240 + {
  241 + throw new UnsupportedDriverActionException('Forward action is not supported by %s', $this);
  242 + }
  243 +
  244 + /**
  245 + * {@inheritdoc}
  246 + */
  247 + public function back()
  248 + {
  249 + throw new UnsupportedDriverActionException('Backward action is not supported by %s', $this);
  250 + }
  251 +
  252 + /**
  253 + * {@inheritdoc}
  254 + */
  255 + public function setBasicAuth($user, $password)
  256 + {
  257 + throw new UnsupportedDriverActionException('Basic auth setup is not supported by %s', $this);
  258 + }
  259 +
  260 + /**
  261 + * {@inheritdoc}
  262 + */
  263 + public function switchToWindow($name = null)
  264 + {
  265 + throw new UnsupportedDriverActionException('Windows management is not supported by %s', $this);
  266 + }
  267 +
  268 + /**
  269 + * {@inheritdoc}
  270 + */
  271 + public function switchToIFrame($name = null)
  272 + {
  273 + throw new UnsupportedDriverActionException('iFrames management is not supported by %s', $this);
  274 + }
  275 +
  276 + /**
  277 + * {@inheritdoc}
  278 + */
  279 + public function setRequestHeader($name, $value)
  280 + {
  281 + throw new UnsupportedDriverActionException('Request headers manipulation is not supported by %s', $this);
  282 + }
  283 +
  284 + /**
  285 + * {@inheritdoc}
  286 + */
  287 + public function getResponseHeaders()
  288 + {
  289 + throw new UnsupportedDriverActionException('Response headers are not available from %s', $this);
  290 + }
  291 +
  292 + /**
  293 + * {@inheritdoc}
  294 + */
  295 + public function setCookie($name, $value = null)
  296 + {
  297 + throw new UnsupportedDriverActionException('Cookies manipulation is not supported by %s', $this);
  298 + }
  299 +
  300 + /**
  301 + * {@inheritdoc}
  302 + */
  303 + public function getCookie($name)
  304 + {
  305 + throw new UnsupportedDriverActionException('Cookies are not available from %s', $this);
  306 + }
  307 +
  308 + /**
  309 + * {@inheritdoc}
  310 + */
  311 + public function getStatusCode()
  312 + {
  313 + throw new UnsupportedDriverActionException('Status code is not available from %s', $this);
  314 + }
  315 +
  316 + /**
  317 + * {@inheritdoc}
  318 + */
  319 + public function getScreenshot()
  320 + {
  321 + throw new UnsupportedDriverActionException('Screenshots are not supported by %s', $this);
  322 + }
  323 +
  324 + /**
  325 + * {@inheritdoc}
  326 + */
  327 + public function getWindowNames()
  328 + {
  329 + throw new UnsupportedDriverActionException('Listing all window names is not supported by %s', $this);
  330 + }
  331 +
  332 + /**
  333 + * {@inheritdoc}
  334 + */
  335 + public function getWindowName()
  336 + {
  337 + throw new UnsupportedDriverActionException('Listing this window name is not supported by %s', $this);
  338 + }
  339 +
  340 + /**
  341 + * {@inheritdoc}
  342 + */
  343 + public function doubleClick($xpath)
  344 + {
  345 + throw new UnsupportedDriverActionException('Double-clicking is not supported by %s', $this);
  346 + }
  347 +
  348 + /**
  349 + * {@inheritdoc}
  350 + */
  351 + public function rightClick($xpath)
  352 + {
  353 + throw new UnsupportedDriverActionException('Right-clicking is not supported by %s', $this);
  354 + }
  355 +
  356 + /**
  357 + * {@inheritdoc}
  358 + */
  359 + public function isVisible($xpath)
  360 + {
  361 + throw new UnsupportedDriverActionException('Element visibility check is not supported by %s', $this);
  362 + }
  363 +
  364 + /**
  365 + * {@inheritdoc}
  366 + */
  367 + public function isSelected($xpath)
  368 + {
  369 + throw new UnsupportedDriverActionException('Element selection check is not supported by %s', $this);
  370 + }
  371 +
  372 + /**
  373 + * {@inheritdoc}
  374 + */
  375 + public function mouseOver($xpath)
  376 + {
  377 + throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
  378 + }
  379 +
  380 + /**
  381 + * {@inheritdoc}
  382 + */
  383 + public function focus($xpath)
  384 + {
  385 + throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
  386 + }
  387 +
  388 + /**
  389 + * {@inheritdoc}
  390 + */
  391 + public function blur($xpath)
  392 + {
  393 + throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
  394 + }
  395 +
  396 + /**
  397 + * {@inheritdoc}
  398 + */
  399 + public function keyPress($xpath, $char, $modifier = null)
  400 + {
  401 + throw new UnsupportedDriverActionException('Keyboard manipulations are not supported by %s', $this);
  402 + }
  403 +
  404 + /**
  405 + * {@inheritdoc}
  406 + */
  407 + public function keyDown($xpath, $char, $modifier = null)
  408 + {
  409 + throw new UnsupportedDriverActionException('Keyboard manipulations are not supported by %s', $this);
  410 + }
  411 +
  412 + /**
  413 + * {@inheritdoc}
  414 + */
  415 + public function keyUp($xpath, $char, $modifier = null)
  416 + {
  417 + throw new UnsupportedDriverActionException('Keyboard manipulations are not supported by %s', $this);
  418 + }
  419 +
  420 + /**
  421 + * {@inheritdoc}
  422 + */
  423 + public function dragTo($sourceXpath, $destinationXpath)
  424 + {
  425 + throw new UnsupportedDriverActionException('Mouse manipulations are not supported by %s', $this);
  426 + }
  427 +
  428 + /**
  429 + * {@inheritdoc}
  430 + */
  431 + public function executeScript($script)
  432 + {
  433 + throw new UnsupportedDriverActionException('JS is not supported by %s', $this);
  434 + }
  435 +
  436 + /**
  437 + * {@inheritdoc}
  438 + */
  439 + public function evaluateScript($script)
  440 + {
  441 + throw new UnsupportedDriverActionException('JS is not supported by %s', $this);
  442 + }
  443 +
  444 + /**
  445 + * {@inheritdoc}
  446 + */
  447 + public function wait($timeout, $condition)
  448 + {
  449 + throw new UnsupportedDriverActionException('JS is not supported by %s', $this);
  450 + }
  451 +
  452 + /**
  453 + * {@inheritdoc}
  454 + */
  455 + public function resizeWindow($width, $height, $name = null)
  456 + {
  457 + throw new UnsupportedDriverActionException('Window resizing is not supported by %s', $this);
  458 + }
  459 +
  460 + /**
  461 + * {@inheritdoc}
  462 + */
  463 + public function maximizeWindow($name = null)
  464 + {
  465 + throw new UnsupportedDriverActionException('Window maximize is not supported by %s', $this);
  466 + }
  467 +
  468 + /**
  469 + * {@inheritdoc}
  470 + */
  471 + public function submitForm($xpath)
  472 + {
  473 + throw new UnsupportedDriverActionException('Form submission is not supported by %s', $this);
  474 + }
  475 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Driver;
  12 +
  13 +use Behat\Mink\Element\NodeElement;
  14 +use Behat\Mink\Exception\DriverException;
  15 +use Behat\Mink\Exception\UnsupportedDriverActionException;
  16 +use Behat\Mink\Session;
  17 +
  18 +/**
  19 + * Driver interface.
  20 + *
  21 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  22 + */
  23 +interface DriverInterface
  24 +{
  25 + /**
  26 + * Sets driver's current session.
  27 + *
  28 + * @param Session $session
  29 + */
  30 + public function setSession(Session $session);
  31 +
  32 + /**
  33 + * Starts driver.
  34 + *
  35 + * Once started, the driver should be ready to visit a page.
  36 + *
  37 + * Calling any action before visiting a page is an undefined behavior.
  38 + * The only supported method calls on a fresh driver are
  39 + * - visit()
  40 + * - setRequestHeader()
  41 + * - setBasicAuth()
  42 + * - reset()
  43 + * - stop()
  44 + *
  45 + * Calling start on a started driver is an undefined behavior. Driver
  46 + * implementations are free to handle it silently or to fail with an
  47 + * exception.
  48 + *
  49 + * @throws DriverException When the driver cannot be started
  50 + */
  51 + public function start();
  52 +
  53 + /**
  54 + * Checks whether driver is started.
  55 + *
  56 + * @return Boolean
  57 + */
  58 + public function isStarted();
  59 +
  60 + /**
  61 + * Stops driver.
  62 + *
  63 + * Once stopped, the driver should be started again before using it again.
  64 + *
  65 + * Calling any action on a stopped driver is an undefined behavior.
  66 + * The only supported method call after stopping a driver is starting it again.
  67 + *
  68 + * Calling stop on a stopped driver is an undefined behavior. Driver
  69 + * implementations are free to handle it silently or to fail with an
  70 + * exception.
  71 + *
  72 + * @throws DriverException When the driver cannot be closed
  73 + */
  74 + public function stop();
  75 +
  76 + /**
  77 + * Resets driver state.
  78 + *
  79 + * This should reset cookies, request headers and basic authentication.
  80 + * When possible, the history should be reset as well, but this is not enforced
  81 + * as some implementations may not be able to reset it without restarting the
  82 + * driver entirely. Consumers requiring a clean history should restart the driver
  83 + * to enforce it.
  84 + *
  85 + * Once reset, the driver should be ready to visit a page.
  86 + * Calling any action before visiting a page is an undefined behavior.
  87 + * The only supported method calls on a fresh driver are
  88 + * - visit()
  89 + * - setRequestHeader()
  90 + * - setBasicAuth()
  91 + * - reset()
  92 + * - stop()
  93 + *
  94 + * Calling reset on a stopped driver is an undefined behavior.
  95 + */
  96 + public function reset();
  97 +
  98 + /**
  99 + * Visit specified URL.
  100 + *
  101 + * @param string $url url of the page
  102 + *
  103 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  104 + * @throws DriverException When the operation cannot be done
  105 + */
  106 + public function visit($url);
  107 +
  108 + /**
  109 + * Returns current URL address.
  110 + *
  111 + * @return string
  112 + *
  113 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  114 + * @throws DriverException When the operation cannot be done
  115 + */
  116 + public function getCurrentUrl();
  117 +
  118 + /**
  119 + * Reloads current page.
  120 + *
  121 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  122 + * @throws DriverException When the operation cannot be done
  123 + */
  124 + public function reload();
  125 +
  126 + /**
  127 + * Moves browser forward 1 page.
  128 + *
  129 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  130 + * @throws DriverException When the operation cannot be done
  131 + */
  132 + public function forward();
  133 +
  134 + /**
  135 + * Moves browser backward 1 page.
  136 + *
  137 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  138 + * @throws DriverException When the operation cannot be done
  139 + */
  140 + public function back();
  141 +
  142 + /**
  143 + * Sets HTTP Basic authentication parameters.
  144 + *
  145 + * @param string|Boolean $user user name or false to disable authentication
  146 + * @param string $password password
  147 + *
  148 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  149 + * @throws DriverException When the operation cannot be done
  150 + */
  151 + public function setBasicAuth($user, $password);
  152 +
  153 + /**
  154 + * Switches to specific browser window.
  155 + *
  156 + * @param string $name window name (null for switching back to main window)
  157 + *
  158 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  159 + * @throws DriverException When the operation cannot be done
  160 + */
  161 + public function switchToWindow($name = null);
  162 +
  163 + /**
  164 + * Switches to specific iFrame.
  165 + *
  166 + * @param string $name iframe name (null for switching back)
  167 + *
  168 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  169 + * @throws DriverException When the operation cannot be done
  170 + */
  171 + public function switchToIFrame($name = null);
  172 +
  173 + /**
  174 + * Sets specific request header on client.
  175 + *
  176 + * @param string $name
  177 + * @param string $value
  178 + *
  179 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  180 + * @throws DriverException When the operation cannot be done
  181 + */
  182 + public function setRequestHeader($name, $value);
  183 +
  184 + /**
  185 + * Returns last response headers.
  186 + *
  187 + * @return array
  188 + *
  189 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  190 + * @throws DriverException When the operation cannot be done
  191 + */
  192 + public function getResponseHeaders();
  193 +
  194 + /**
  195 + * Sets cookie.
  196 + *
  197 + * @param string $name
  198 + * @param string $value
  199 + *
  200 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  201 + * @throws DriverException When the operation cannot be done
  202 + */
  203 + public function setCookie($name, $value = null);
  204 +
  205 + /**
  206 + * Returns cookie by name.
  207 + *
  208 + * @param string $name
  209 + *
  210 + * @return string|null
  211 + *
  212 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  213 + * @throws DriverException When the operation cannot be done
  214 + */
  215 + public function getCookie($name);
  216 +
  217 + /**
  218 + * Returns last response status code.
  219 + *
  220 + * @return int
  221 + *
  222 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  223 + * @throws DriverException When the operation cannot be done
  224 + */
  225 + public function getStatusCode();
  226 +
  227 + /**
  228 + * Returns last response content.
  229 + *
  230 + * @return string
  231 + *
  232 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  233 + * @throws DriverException When the operation cannot be done
  234 + */
  235 + public function getContent();
  236 +
  237 + /**
  238 + * Capture a screenshot of the current window.
  239 + *
  240 + * @return string screenshot of MIME type image/* depending
  241 + * on driver (e.g., image/png, image/jpeg)
  242 + *
  243 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  244 + * @throws DriverException When the operation cannot be done
  245 + */
  246 + public function getScreenshot();
  247 +
  248 + /**
  249 + * Return the names of all open windows.
  250 + *
  251 + * @return array array of all open windows
  252 + *
  253 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  254 + * @throws DriverException When the operation cannot be done
  255 + */
  256 + public function getWindowNames();
  257 +
  258 + /**
  259 + * Return the name of the currently active window.
  260 + *
  261 + * @return string the name of the current window
  262 + *
  263 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  264 + * @throws DriverException When the operation cannot be done
  265 + */
  266 + public function getWindowName();
  267 +
  268 + /**
  269 + * Finds elements with specified XPath query.
  270 + *
  271 + * @param string $xpath
  272 + *
  273 + * @return NodeElement[]
  274 + *
  275 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  276 + * @throws DriverException When the operation cannot be done
  277 + */
  278 + public function find($xpath);
  279 +
  280 + /**
  281 + * Returns element's tag name by it's XPath query.
  282 + *
  283 + * @param string $xpath
  284 + *
  285 + * @return string
  286 + *
  287 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  288 + * @throws DriverException When the operation cannot be done
  289 + */
  290 + public function getTagName($xpath);
  291 +
  292 + /**
  293 + * Returns element's text by it's XPath query.
  294 + *
  295 + * @param string $xpath
  296 + *
  297 + * @return string
  298 + *
  299 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  300 + * @throws DriverException When the operation cannot be done
  301 + */
  302 + public function getText($xpath);
  303 +
  304 + /**
  305 + * Returns element's inner html by it's XPath query.
  306 + *
  307 + * @param string $xpath
  308 + *
  309 + * @return string
  310 + *
  311 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  312 + * @throws DriverException When the operation cannot be done
  313 + */
  314 + public function getHtml($xpath);
  315 +
  316 + /**
  317 + * Returns element's outer html by it's XPath query.
  318 + *
  319 + * @param string $xpath
  320 + *
  321 + * @return string
  322 + *
  323 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  324 + * @throws DriverException When the operation cannot be done
  325 + */
  326 + public function getOuterHtml($xpath);
  327 +
  328 + /**
  329 + * Returns element's attribute by it's XPath query.
  330 + *
  331 + * @param string $xpath
  332 + * @param string $name
  333 + *
  334 + * @return string|null
  335 + *
  336 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  337 + * @throws DriverException When the operation cannot be done
  338 + */
  339 + public function getAttribute($xpath, $name);
  340 +
  341 + /**
  342 + * Returns element's value by it's XPath query.
  343 + *
  344 + * @param string $xpath
  345 + *
  346 + * @return string|bool|array
  347 + *
  348 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  349 + * @throws DriverException When the operation cannot be done
  350 + *
  351 + * @see \Behat\Mink\Element\NodeElement::getValue
  352 + */
  353 + public function getValue($xpath);
  354 +
  355 + /**
  356 + * Sets element's value by it's XPath query.
  357 + *
  358 + * @param string $xpath
  359 + * @param string|bool|array $value
  360 + *
  361 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  362 + * @throws DriverException When the operation cannot be done
  363 + *
  364 + * @see \Behat\Mink\Element\NodeElement::setValue
  365 + */
  366 + public function setValue($xpath, $value);
  367 +
  368 + /**
  369 + * Checks checkbox by it's XPath query.
  370 + *
  371 + * @param string $xpath
  372 + *
  373 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  374 + * @throws DriverException When the operation cannot be done
  375 + *
  376 + * @see \Behat\Mink\Element\NodeElement::check
  377 + */
  378 + public function check($xpath);
  379 +
  380 + /**
  381 + * Unchecks checkbox by it's XPath query.
  382 + *
  383 + * @param string $xpath
  384 + *
  385 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  386 + * @throws DriverException When the operation cannot be done
  387 + *
  388 + * @see \Behat\Mink\Element\NodeElement::uncheck
  389 + */
  390 + public function uncheck($xpath);
  391 +
  392 + /**
  393 + * Checks whether checkbox or radio button located by it's XPath query is checked.
  394 + *
  395 + * @param string $xpath
  396 + *
  397 + * @return Boolean
  398 + *
  399 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  400 + * @throws DriverException When the operation cannot be done
  401 + *
  402 + * @see \Behat\Mink\Element\NodeElement::isChecked
  403 + */
  404 + public function isChecked($xpath);
  405 +
  406 + /**
  407 + * Selects option from select field or value in radio group located by it's XPath query.
  408 + *
  409 + * @param string $xpath
  410 + * @param string $value
  411 + * @param Boolean $multiple
  412 + *
  413 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  414 + * @throws DriverException When the operation cannot be done
  415 + *
  416 + * @see \Behat\Mink\Element\NodeElement::selectOption
  417 + */
  418 + public function selectOption($xpath, $value, $multiple = false);
  419 +
  420 + /**
  421 + * Checks whether select option, located by it's XPath query, is selected.
  422 + *
  423 + * @param string $xpath
  424 + *
  425 + * @return Boolean
  426 + *
  427 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  428 + * @throws DriverException When the operation cannot be done
  429 + *
  430 + * @see \Behat\Mink\Element\NodeElement::isSelected
  431 + */
  432 + public function isSelected($xpath);
  433 +
  434 + /**
  435 + * Clicks button or link located by it's XPath query.
  436 + *
  437 + * @param string $xpath
  438 + *
  439 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  440 + * @throws DriverException When the operation cannot be done
  441 + */
  442 + public function click($xpath);
  443 +
  444 + /**
  445 + * Double-clicks button or link located by it's XPath query.
  446 + *
  447 + * @param string $xpath
  448 + *
  449 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  450 + * @throws DriverException When the operation cannot be done
  451 + */
  452 + public function doubleClick($xpath);
  453 +
  454 + /**
  455 + * Right-clicks button or link located by it's XPath query.
  456 + *
  457 + * @param string $xpath
  458 + *
  459 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  460 + * @throws DriverException When the operation cannot be done
  461 + */
  462 + public function rightClick($xpath);
  463 +
  464 + /**
  465 + * Attaches file path to file field located by it's XPath query.
  466 + *
  467 + * @param string $xpath
  468 + * @param string $path
  469 + *
  470 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  471 + * @throws DriverException When the operation cannot be done
  472 + *
  473 + * @see \Behat\Mink\Element\NodeElement::attachFile
  474 + */
  475 + public function attachFile($xpath, $path);
  476 +
  477 + /**
  478 + * Checks whether element visible located by it's XPath query.
  479 + *
  480 + * @param string $xpath
  481 + *
  482 + * @return Boolean
  483 + *
  484 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  485 + * @throws DriverException When the operation cannot be done
  486 + */
  487 + public function isVisible($xpath);
  488 +
  489 + /**
  490 + * Simulates a mouse over on the element.
  491 + *
  492 + * @param string $xpath
  493 + *
  494 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  495 + * @throws DriverException When the operation cannot be done
  496 + */
  497 + public function mouseOver($xpath);
  498 +
  499 + /**
  500 + * Brings focus to element.
  501 + *
  502 + * @param string $xpath
  503 + *
  504 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  505 + * @throws DriverException When the operation cannot be done
  506 + */
  507 + public function focus($xpath);
  508 +
  509 + /**
  510 + * Removes focus from element.
  511 + *
  512 + * @param string $xpath
  513 + *
  514 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  515 + * @throws DriverException When the operation cannot be done
  516 + */
  517 + public function blur($xpath);
  518 +
  519 + /**
  520 + * Presses specific keyboard key.
  521 + *
  522 + * @param string $xpath
  523 + * @param string|int $char could be either char ('b') or char-code (98)
  524 + * @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
  525 + *
  526 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  527 + * @throws DriverException When the operation cannot be done
  528 + */
  529 + public function keyPress($xpath, $char, $modifier = null);
  530 +
  531 + /**
  532 + * Pressed down specific keyboard key.
  533 + *
  534 + * @param string $xpath
  535 + * @param string|int $char could be either char ('b') or char-code (98)
  536 + * @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
  537 + *
  538 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  539 + * @throws DriverException When the operation cannot be done
  540 + */
  541 + public function keyDown($xpath, $char, $modifier = null);
  542 +
  543 + /**
  544 + * Pressed up specific keyboard key.
  545 + *
  546 + * @param string $xpath
  547 + * @param string|int $char could be either char ('b') or char-code (98)
  548 + * @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
  549 + *
  550 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  551 + * @throws DriverException When the operation cannot be done
  552 + */
  553 + public function keyUp($xpath, $char, $modifier = null);
  554 +
  555 + /**
  556 + * Drag one element onto another.
  557 + *
  558 + * @param string $sourceXpath
  559 + * @param string $destinationXpath
  560 + *
  561 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  562 + * @throws DriverException When the operation cannot be done
  563 + */
  564 + public function dragTo($sourceXpath, $destinationXpath);
  565 +
  566 + /**
  567 + * Executes JS script.
  568 + *
  569 + * @param string $script
  570 + *
  571 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  572 + * @throws DriverException When the operation cannot be done
  573 + */
  574 + public function executeScript($script);
  575 +
  576 + /**
  577 + * Evaluates JS script.
  578 + *
  579 + * The "return" keyword is optional in the script passed as argument. Driver implementations
  580 + * must accept the expression both with and without the keyword.
  581 + *
  582 + * @param string $script
  583 + *
  584 + * @return mixed
  585 + *
  586 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  587 + * @throws DriverException When the operation cannot be done
  588 + */
  589 + public function evaluateScript($script);
  590 +
  591 + /**
  592 + * Waits some time or until JS condition turns true.
  593 + *
  594 + * @param int $timeout timeout in milliseconds
  595 + * @param string $condition JS condition
  596 + *
  597 + * @return bool
  598 + *
  599 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  600 + * @throws DriverException When the operation cannot be done
  601 + */
  602 + public function wait($timeout, $condition);
  603 +
  604 + /**
  605 + * Set the dimensions of the window.
  606 + *
  607 + * @param int $width set the window width, measured in pixels
  608 + * @param int $height set the window height, measured in pixels
  609 + * @param string $name window name (null for the main window)
  610 + *
  611 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  612 + * @throws DriverException When the operation cannot be done
  613 + */
  614 + public function resizeWindow($width, $height, $name = null);
  615 +
  616 + /**
  617 + * Maximizes the window if it is not maximized already.
  618 + *
  619 + * @param string $name window name (null for the main window)
  620 + *
  621 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  622 + * @throws DriverException When the operation cannot be done
  623 + */
  624 + public function maximizeWindow($name = null);
  625 +
  626 + /**
  627 + * Submits the form.
  628 + *
  629 + * @param string $xpath Xpath.
  630 + *
  631 + * @throws UnsupportedDriverActionException When operation not supported by the driver
  632 + * @throws DriverException When the operation cannot be done
  633 + *
  634 + * @see \Behat\Mink\Element\NodeElement::submitForm
  635 + */
  636 + public function submitForm($xpath);
  637 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Element;
  12 +
  13 +/**
  14 + * Document element.
  15 + *
  16 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  17 + */
  18 +class DocumentElement extends TraversableElement
  19 +{
  20 + /**
  21 + * Returns XPath for handled element.
  22 + *
  23 + * @return string
  24 + */
  25 + public function getXpath()
  26 + {
  27 + return '//html';
  28 + }
  29 +
  30 + /**
  31 + * Returns document content.
  32 + *
  33 + * @return string
  34 + */
  35 + public function getContent()
  36 + {
  37 + return trim($this->getDriver()->getContent());
  38 + }
  39 +
  40 + /**
  41 + * Check whether document has specified content.
  42 + *
  43 + * @param string $content
  44 + *
  45 + * @return Boolean
  46 + */
  47 + public function hasContent($content)
  48 + {
  49 + return $this->has('named', array('content', $content));
  50 + }
  51 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Element;
  12 +
  13 +use Behat\Mink\Driver\DriverInterface;
  14 +use Behat\Mink\Exception\ElementNotFoundException;
  15 +use Behat\Mink\Selector\SelectorsHandler;
  16 +use Behat\Mink\Selector\Xpath\Manipulator;
  17 +use Behat\Mink\Session;
  18 +
  19 +/**
  20 + * Base element.
  21 + *
  22 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  23 + */
  24 +abstract class Element implements ElementInterface
  25 +{
  26 + /**
  27 + * @var Session
  28 + */
  29 + private $session;
  30 +
  31 + /**
  32 + * Driver.
  33 + *
  34 + * @var DriverInterface
  35 + */
  36 + private $driver;
  37 +
  38 + /**
  39 + * @var SelectorsHandler
  40 + */
  41 + private $selectorsHandler;
  42 +
  43 + /**
  44 + * @var Manipulator
  45 + */
  46 + private $xpathManipulator;
  47 +
  48 + /**
  49 + * Initialize element.
  50 + *
  51 + * @param Session $session
  52 + */
  53 + public function __construct(Session $session)
  54 + {
  55 + $this->xpathManipulator = new Manipulator();
  56 + $this->session = $session;
  57 +
  58 + $this->driver = $session->getDriver();
  59 + $this->selectorsHandler = $session->getSelectorsHandler();
  60 + }
  61 +
  62 + /**
  63 + * Returns element session.
  64 + *
  65 + * @return Session
  66 + *
  67 + * @deprecated Accessing the session from the element is deprecated as of 1.6 and will be impossible in 2.0.
  68 + */
  69 + public function getSession()
  70 + {
  71 + @trigger_error(sprintf('The method %s is deprecated as of 1.6 and will be removed in 2.0', __METHOD__), E_USER_DEPRECATED);
  72 +
  73 + return $this->session;
  74 + }
  75 +
  76 + /**
  77 + * Returns element's driver.
  78 + *
  79 + * @return DriverInterface
  80 + */
  81 + protected function getDriver()
  82 + {
  83 + return $this->driver;
  84 + }
  85 +
  86 + /**
  87 + * Returns selectors handler.
  88 + *
  89 + * @return SelectorsHandler
  90 + *
  91 + * @deprecated Accessing the selectors handler in the element is deprecated as of 1.7 and will be impossible in 2.0.
  92 + */
  93 + protected function getSelectorsHandler()
  94 + {
  95 + @trigger_error(sprintf('The method %s is deprecated as of 1.7 and will be removed in 2.0', __METHOD__), E_USER_DEPRECATED);
  96 +
  97 + return $this->selectorsHandler;
  98 + }
  99 +
  100 + /**
  101 + * {@inheritdoc}
  102 + */
  103 + public function has($selector, $locator)
  104 + {
  105 + return null !== $this->find($selector, $locator);
  106 + }
  107 +
  108 + /**
  109 + * {@inheritdoc}
  110 + */
  111 + public function isValid()
  112 + {
  113 + return 1 === count($this->getDriver()->find($this->getXpath()));
  114 + }
  115 +
  116 + /**
  117 + * {@inheritdoc}
  118 + */
  119 + public function waitFor($timeout, $callback)
  120 + {
  121 + if (!is_callable($callback)) {
  122 + throw new \InvalidArgumentException('Given callback is not a valid callable');
  123 + }
  124 +
  125 + $start = microtime(true);
  126 + $end = $start + $timeout;
  127 +
  128 + do {
  129 + $result = call_user_func($callback, $this);
  130 +
  131 + if ($result) {
  132 + break;
  133 + }
  134 +
  135 + usleep(100000);
  136 + } while (microtime(true) < $end);
  137 +
  138 + return $result;
  139 + }
  140 +
  141 + /**
  142 + * {@inheritdoc}
  143 + */
  144 + public function find($selector, $locator)
  145 + {
  146 + $items = $this->findAll($selector, $locator);
  147 +
  148 + return count($items) ? current($items) : null;
  149 + }
  150 +
  151 + /**
  152 + * {@inheritdoc}
  153 + */
  154 + public function findAll($selector, $locator)
  155 + {
  156 + if ('named' === $selector) {
  157 + $items = $this->findAll('named_exact', $locator);
  158 + if (empty($items)) {
  159 + $items = $this->findAll('named_partial', $locator);
  160 + }
  161 +
  162 + return $items;
  163 + }
  164 +
  165 + $xpath = $this->selectorsHandler->selectorToXpath($selector, $locator);
  166 + $xpath = $this->xpathManipulator->prepend($xpath, $this->getXpath());
  167 +
  168 + return $this->getDriver()->find($xpath);
  169 + }
  170 +
  171 + /**
  172 + * {@inheritdoc}
  173 + */
  174 + public function getText()
  175 + {
  176 + return $this->getDriver()->getText($this->getXpath());
  177 + }
  178 +
  179 + /**
  180 + * {@inheritdoc}
  181 + */
  182 + public function getHtml()
  183 + {
  184 + return $this->getDriver()->getHtml($this->getXpath());
  185 + }
  186 +
  187 + /**
  188 + * Returns element outer html.
  189 + *
  190 + * @return string
  191 + */
  192 + public function getOuterHtml()
  193 + {
  194 + return $this->getDriver()->getOuterHtml($this->getXpath());
  195 + }
  196 +
  197 + /**
  198 + * Builds an ElementNotFoundException.
  199 + *
  200 + * @param string $type
  201 + * @param string|null $selector
  202 + * @param string|null $locator
  203 + *
  204 + * @return ElementNotFoundException
  205 + *
  206 + * @deprecated as of 1.7, to be removed in 2.0
  207 + */
  208 + protected function elementNotFound($type, $selector = null, $locator = null)
  209 + {
  210 + @trigger_error(sprintf('The method %s is deprecated as of 1.7 and will be removed in 2.0', __METHOD__), E_USER_DEPRECATED);
  211 +
  212 + return new ElementNotFoundException($this->driver, $type, $selector, $locator);
  213 + }
  214 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Element;
  12 +
  13 +use Behat\Mink\Session;
  14 +
  15 +/**
  16 + * Element interface.
  17 + *
  18 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  19 + */
  20 +interface ElementInterface
  21 +{
  22 + /**
  23 + * Returns XPath for handled element.
  24 + *
  25 + * @return string
  26 + */
  27 + public function getXpath();
  28 +
  29 + /**
  30 + * Returns element's session.
  31 + *
  32 + * @return Session
  33 + *
  34 + * @deprecated Accessing the session from the element is deprecated as of 1.6 and will be impossible in 2.0.
  35 + */
  36 + public function getSession();
  37 +
  38 + /**
  39 + * Checks whether element with specified selector exists inside the current element.
  40 + *
  41 + * @param string $selector selector engine name
  42 + * @param string|array $locator selector locator
  43 + *
  44 + * @return Boolean
  45 + *
  46 + * @see ElementInterface::findAll for the supported selectors
  47 + */
  48 + public function has($selector, $locator);
  49 +
  50 + /**
  51 + * Checks if an element still exists in the DOM.
  52 + *
  53 + * @return bool
  54 + */
  55 + public function isValid();
  56 +
  57 + /**
  58 + * Waits for an element(-s) to appear and returns it.
  59 + *
  60 + * @param int|float $timeout Maximal allowed waiting time in seconds.
  61 + * @param callable $callback Callback, which result is both used as waiting condition and returned.
  62 + * Will receive reference to `this element` as first argument.
  63 + *
  64 + * @return mixed
  65 + *
  66 + * @throws \InvalidArgumentException When invalid callback given.
  67 + */
  68 + public function waitFor($timeout, $callback);
  69 +
  70 + /**
  71 + * Finds first element with specified selector inside the current element.
  72 + *
  73 + * @param string $selector selector engine name
  74 + * @param string|array $locator selector locator
  75 + *
  76 + * @return NodeElement|null
  77 + *
  78 + * @see ElementInterface::findAll for the supported selectors
  79 + */
  80 + public function find($selector, $locator);
  81 +
  82 + /**
  83 + * Finds all elements with specified selector inside the current element.
  84 + *
  85 + * Valid selector engines are named, xpath, css, named_partial and named_exact.
  86 + *
  87 + * 'named' is a pseudo selector engine which prefers an exact match but
  88 + * will return a partial match if no exact match is found.
  89 + * 'xpath' is a pseudo selector engine supported by SelectorsHandler.
  90 + *
  91 + * More selector engines can be registered in the SelectorsHandler.
  92 + *
  93 + * @param string $selector selector engine name
  94 + * @param string|array $locator selector locator
  95 + *
  96 + * @return NodeElement[]
  97 + *
  98 + * @see NamedSelector for the locators supported by the named selectors
  99 + */
  100 + public function findAll($selector, $locator);
  101 +
  102 + /**
  103 + * Returns element text (inside tag).
  104 + *
  105 + * @return string
  106 + */
  107 + public function getText();
  108 +
  109 + /**
  110 + * Returns element inner html.
  111 + *
  112 + * @return string
  113 + */
  114 + public function getHtml();
  115 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Element;
  12 +
  13 +use Behat\Mink\Session;
  14 +use Behat\Mink\Exception\ElementNotFoundException;
  15 +
  16 +/**
  17 + * Page element node.
  18 + *
  19 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  20 + */
  21 +class NodeElement extends TraversableElement
  22 +{
  23 + private $xpath;
  24 +
  25 + /**
  26 + * Initializes node element.
  27 + *
  28 + * @param string $xpath element xpath
  29 + * @param Session $session session instance
  30 + */
  31 + public function __construct($xpath, Session $session)
  32 + {
  33 + $this->xpath = $xpath;
  34 +
  35 + parent::__construct($session);
  36 + }
  37 +
  38 + /**
  39 + * Returns XPath for handled element.
  40 + *
  41 + * @return string
  42 + */
  43 + public function getXpath()
  44 + {
  45 + return $this->xpath;
  46 + }
  47 +
  48 + /**
  49 + * Returns parent element to the current one.
  50 + *
  51 + * @return NodeElement
  52 + */
  53 + public function getParent()
  54 + {
  55 + return $this->find('xpath', '..');
  56 + }
  57 +
  58 + /**
  59 + * Returns current node tag name.
  60 + *
  61 + * The value is always returned in lowercase to allow an easy comparison.
  62 + *
  63 + * @return string
  64 + */
  65 + public function getTagName()
  66 + {
  67 + return strtolower($this->getDriver()->getTagName($this->getXpath()));
  68 + }
  69 +
  70 + /**
  71 + * Returns the value of the form field or option element.
  72 + *
  73 + * For checkbox fields, the value is a boolean indicating whether the checkbox is checked.
  74 + * For radio buttons, the value is the value of the selected button in the radio group
  75 + * or null if no button is selected.
  76 + * For single select boxes, the value is the value of the selected option.
  77 + * For multiple select boxes, the value is an array of selected option values.
  78 + * for file inputs, the return value is undefined given that browsers don't allow accessing
  79 + * the value of file inputs for security reasons. Some drivers may allow accessing the
  80 + * path of the file set in the field, but this is not required if it cannot be implemented.
  81 + * For textarea elements and all textual fields, the value is the content of the field.
  82 + * Form option elements, the value is the value of the option (the value attribute or the text
  83 + * content if the attribute is not set).
  84 + *
  85 + * Calling this method on other elements than form fields or option elements is not allowed.
  86 + *
  87 + * @return string|bool|array
  88 + */
  89 + public function getValue()
  90 + {
  91 + return $this->getDriver()->getValue($this->getXpath());
  92 + }
  93 +
  94 + /**
  95 + * Sets the value of the form field.
  96 + *
  97 + * Calling this method on other elements than form fields is not allowed.
  98 + *
  99 + * @param string|bool|array $value
  100 + *
  101 + * @see NodeElement::getValue for the format of the value for each type of field
  102 + */
  103 + public function setValue($value)
  104 + {
  105 + $this->getDriver()->setValue($this->getXpath(), $value);
  106 + }
  107 +
  108 + /**
  109 + * Checks whether element has attribute with specified name.
  110 + *
  111 + * @param string $name
  112 + *
  113 + * @return Boolean
  114 + */
  115 + public function hasAttribute($name)
  116 + {
  117 + return null !== $this->getDriver()->getAttribute($this->getXpath(), $name);
  118 + }
  119 +
  120 + /**
  121 + * Returns specified attribute value.
  122 + *
  123 + * @param string $name
  124 + *
  125 + * @return string|null
  126 + */
  127 + public function getAttribute($name)
  128 + {
  129 + return $this->getDriver()->getAttribute($this->getXpath(), $name);
  130 + }
  131 +
  132 + /**
  133 + * Checks whether an element has a named CSS class.
  134 + *
  135 + * @param string $className Name of the class
  136 + *
  137 + * @return bool
  138 + */
  139 + public function hasClass($className)
  140 + {
  141 + if ($this->hasAttribute('class')) {
  142 + return in_array($className, preg_split('/\s+/', $this->getAttribute('class')));
  143 + }
  144 +
  145 + return false;
  146 + }
  147 +
  148 + /**
  149 + * Clicks current node.
  150 + */
  151 + public function click()
  152 + {
  153 + $this->getDriver()->click($this->getXpath());
  154 + }
  155 +
  156 + /**
  157 + * Presses current button.
  158 + */
  159 + public function press()
  160 + {
  161 + $this->click();
  162 + }
  163 +
  164 + /**
  165 + * Double-clicks current node.
  166 + */
  167 + public function doubleClick()
  168 + {
  169 + $this->getDriver()->doubleClick($this->getXpath());
  170 + }
  171 +
  172 + /**
  173 + * Right-clicks current node.
  174 + */
  175 + public function rightClick()
  176 + {
  177 + $this->getDriver()->rightClick($this->getXpath());
  178 + }
  179 +
  180 + /**
  181 + * Checks current node if it's a checkbox field.
  182 + */
  183 + public function check()
  184 + {
  185 + $this->getDriver()->check($this->getXpath());
  186 + }
  187 +
  188 + /**
  189 + * Unchecks current node if it's a checkbox field.
  190 + */
  191 + public function uncheck()
  192 + {
  193 + $this->getDriver()->uncheck($this->getXpath());
  194 + }
  195 +
  196 + /**
  197 + * Checks whether current node is checked if it's a checkbox or radio field.
  198 + *
  199 + * Calling this method on any other elements is not allowed.
  200 + *
  201 + * @return Boolean
  202 + */
  203 + public function isChecked()
  204 + {
  205 + return (Boolean) $this->getDriver()->isChecked($this->getXpath());
  206 + }
  207 +
  208 + /**
  209 + * Selects specified option for select field or specified radio button in the group.
  210 + *
  211 + * If the current node is a select box, this selects the option found by its value or
  212 + * its text.
  213 + * If the current node is a radio button, this selects the radio button with the given
  214 + * value in the radio button group of the current node.
  215 + *
  216 + * Calling this method on any other elements is not allowed.
  217 + *
  218 + * @param string $option
  219 + * @param Boolean $multiple whether the option should be added to the selection for multiple selects
  220 + *
  221 + * @throws ElementNotFoundException when the option is not found in the select box
  222 + */
  223 + public function selectOption($option, $multiple = false)
  224 + {
  225 + if ('select' !== $this->getTagName()) {
  226 + $this->getDriver()->selectOption($this->getXpath(), $option, $multiple);
  227 +
  228 + return;
  229 + }
  230 +
  231 + $opt = $this->find('named', array('option', $option));
  232 +
  233 + if (null === $opt) {
  234 + throw new ElementNotFoundException($this->getDriver(), 'select option', 'value|text', $option);
  235 + }
  236 +
  237 + $this->getDriver()->selectOption($this->getXpath(), $opt->getValue(), $multiple);
  238 + }
  239 +
  240 + /**
  241 + * Checks whether current node is selected if it's a option field.
  242 + *
  243 + * Calling this method on any other elements is not allowed.
  244 + *
  245 + * @return Boolean
  246 + */
  247 + public function isSelected()
  248 + {
  249 + return (Boolean) $this->getDriver()->isSelected($this->getXpath());
  250 + }
  251 +
  252 + /**
  253 + * Attach file to current node if it's a file input.
  254 + *
  255 + * Calling this method on any other elements than file input is not allowed.
  256 + *
  257 + * @param string $path path to file (local)
  258 + */
  259 + public function attachFile($path)
  260 + {
  261 + $this->getDriver()->attachFile($this->getXpath(), $path);
  262 + }
  263 +
  264 + /**
  265 + * Checks whether current node is visible on page.
  266 + *
  267 + * @return Boolean
  268 + */
  269 + public function isVisible()
  270 + {
  271 + return (Boolean) $this->getDriver()->isVisible($this->getXpath());
  272 + }
  273 +
  274 + /**
  275 + * Simulates a mouse over on the element.
  276 + */
  277 + public function mouseOver()
  278 + {
  279 + $this->getDriver()->mouseOver($this->getXpath());
  280 + }
  281 +
  282 + /**
  283 + * Drags current node onto other node.
  284 + *
  285 + * @param ElementInterface $destination other node
  286 + */
  287 + public function dragTo(ElementInterface $destination)
  288 + {
  289 + $this->getDriver()->dragTo($this->getXpath(), $destination->getXpath());
  290 + }
  291 +
  292 + /**
  293 + * Brings focus to element.
  294 + */
  295 + public function focus()
  296 + {
  297 + $this->getDriver()->focus($this->getXpath());
  298 + }
  299 +
  300 + /**
  301 + * Removes focus from element.
  302 + */
  303 + public function blur()
  304 + {
  305 + $this->getDriver()->blur($this->getXpath());
  306 + }
  307 +
  308 + /**
  309 + * Presses specific keyboard key.
  310 + *
  311 + * @param string|int $char could be either char ('b') or char-code (98)
  312 + * @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
  313 + */
  314 + public function keyPress($char, $modifier = null)
  315 + {
  316 + $this->getDriver()->keyPress($this->getXpath(), $char, $modifier);
  317 + }
  318 +
  319 + /**
  320 + * Pressed down specific keyboard key.
  321 + *
  322 + * @param string|int $char could be either char ('b') or char-code (98)
  323 + * @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
  324 + */
  325 + public function keyDown($char, $modifier = null)
  326 + {
  327 + $this->getDriver()->keyDown($this->getXpath(), $char, $modifier);
  328 + }
  329 +
  330 + /**
  331 + * Pressed up specific keyboard key.
  332 + *
  333 + * @param string|int $char could be either char ('b') or char-code (98)
  334 + * @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
  335 + */
  336 + public function keyUp($char, $modifier = null)
  337 + {
  338 + $this->getDriver()->keyUp($this->getXpath(), $char, $modifier);
  339 + }
  340 +
  341 + /**
  342 + * Submits the form.
  343 + *
  344 + * Calling this method on anything else than form elements is not allowed.
  345 + */
  346 + public function submit()
  347 + {
  348 + $this->getDriver()->submitForm($this->getXpath());
  349 + }
  350 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Element;
  12 +
  13 +use Behat\Mink\Exception\ElementNotFoundException;
  14 +
  15 +/**
  16 + * Traversable element.
  17 + *
  18 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  19 + */
  20 +abstract class TraversableElement extends Element
  21 +{
  22 + /**
  23 + * Finds element by its id.
  24 + *
  25 + * @param string $id element id
  26 + *
  27 + * @return NodeElement|null
  28 + */
  29 + public function findById($id)
  30 + {
  31 + return $this->find('named', array('id', $id));
  32 + }
  33 +
  34 + /**
  35 + * Checks whether element has a link with specified locator.
  36 + *
  37 + * @param string $locator link id, title, text or image alt
  38 + *
  39 + * @return Boolean
  40 + */
  41 + public function hasLink($locator)
  42 + {
  43 + return null !== $this->findLink($locator);
  44 + }
  45 +
  46 + /**
  47 + * Finds link with specified locator.
  48 + *
  49 + * @param string $locator link id, title, text or image alt
  50 + *
  51 + * @return NodeElement|null
  52 + */
  53 + public function findLink($locator)
  54 + {
  55 + return $this->find('named', array('link', $locator));
  56 + }
  57 +
  58 + /**
  59 + * Clicks link with specified locator.
  60 + *
  61 + * @param string $locator link id, title, text or image alt
  62 + *
  63 + * @throws ElementNotFoundException
  64 + */
  65 + public function clickLink($locator)
  66 + {
  67 + $link = $this->findLink($locator);
  68 +
  69 + if (null === $link) {
  70 + throw new ElementNotFoundException($this->getDriver(), 'link', 'id|title|alt|text', $locator);
  71 + }
  72 +
  73 + $link->click();
  74 + }
  75 +
  76 + /**
  77 + * Checks whether element has a button (input[type=submit|image|button|reset], button) with specified locator.
  78 + *
  79 + * @param string $locator button id, value or alt
  80 + *
  81 + * @return Boolean
  82 + */
  83 + public function hasButton($locator)
  84 + {
  85 + return null !== $this->findButton($locator);
  86 + }
  87 +
  88 + /**
  89 + * Finds button (input[type=submit|image|button|reset], button) with specified locator.
  90 + *
  91 + * @param string $locator button id, value or alt
  92 + *
  93 + * @return NodeElement|null
  94 + */
  95 + public function findButton($locator)
  96 + {
  97 + return $this->find('named', array('button', $locator));
  98 + }
  99 +
  100 + /**
  101 + * Presses button (input[type=submit|image|button|reset], button) with specified locator.
  102 + *
  103 + * @param string $locator button id, value or alt
  104 + *
  105 + * @throws ElementNotFoundException
  106 + */
  107 + public function pressButton($locator)
  108 + {
  109 + $button = $this->findButton($locator);
  110 +
  111 + if (null === $button) {
  112 + throw new ElementNotFoundException($this->getDriver(), 'button', 'id|name|title|alt|value', $locator);
  113 + }
  114 +
  115 + $button->press();
  116 + }
  117 +
  118 + /**
  119 + * Checks whether element has a field (input, textarea, select) with specified locator.
  120 + *
  121 + * @param string $locator input id, name or label
  122 + *
  123 + * @return Boolean
  124 + */
  125 + public function hasField($locator)
  126 + {
  127 + return null !== $this->findField($locator);
  128 + }
  129 +
  130 + /**
  131 + * Finds field (input, textarea, select) with specified locator.
  132 + *
  133 + * @param string $locator input id, name or label
  134 + *
  135 + * @return NodeElement|null
  136 + */
  137 + public function findField($locator)
  138 + {
  139 + return $this->find('named', array('field', $locator));
  140 + }
  141 +
  142 + /**
  143 + * Fills in field (input, textarea, select) with specified locator.
  144 + *
  145 + * @param string $locator input id, name or label
  146 + * @param string $value value
  147 + *
  148 + * @throws ElementNotFoundException
  149 + *
  150 + * @see NodeElement::setValue
  151 + */
  152 + public function fillField($locator, $value)
  153 + {
  154 + $field = $this->findField($locator);
  155 +
  156 + if (null === $field) {
  157 + throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value|placeholder', $locator);
  158 + }
  159 +
  160 + $field->setValue($value);
  161 + }
  162 +
  163 + /**
  164 + * Checks whether element has a checkbox with specified locator, which is checked.
  165 + *
  166 + * @param string $locator input id, name or label
  167 + *
  168 + * @return Boolean
  169 + *
  170 + * @see NodeElement::isChecked
  171 + */
  172 + public function hasCheckedField($locator)
  173 + {
  174 + $field = $this->findField($locator);
  175 +
  176 + return null !== $field && $field->isChecked();
  177 + }
  178 +
  179 + /**
  180 + * Checks whether element has a checkbox with specified locator, which is unchecked.
  181 + *
  182 + * @param string $locator input id, name or label
  183 + *
  184 + * @return Boolean
  185 + *
  186 + * @see NodeElement::isChecked
  187 + */
  188 + public function hasUncheckedField($locator)
  189 + {
  190 + $field = $this->findField($locator);
  191 +
  192 + return null !== $field && !$field->isChecked();
  193 + }
  194 +
  195 + /**
  196 + * Checks checkbox with specified locator.
  197 + *
  198 + * @param string $locator input id, name or label
  199 + *
  200 + * @throws ElementNotFoundException
  201 + */
  202 + public function checkField($locator)
  203 + {
  204 + $field = $this->findField($locator);
  205 +
  206 + if (null === $field) {
  207 + throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value', $locator);
  208 + }
  209 +
  210 + $field->check();
  211 + }
  212 +
  213 + /**
  214 + * Unchecks checkbox with specified locator.
  215 + *
  216 + * @param string $locator input id, name or label
  217 + *
  218 + * @throws ElementNotFoundException
  219 + */
  220 + public function uncheckField($locator)
  221 + {
  222 + $field = $this->findField($locator);
  223 +
  224 + if (null === $field) {
  225 + throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value', $locator);
  226 + }
  227 +
  228 + $field->uncheck();
  229 + }
  230 +
  231 + /**
  232 + * Checks whether element has a select field with specified locator.
  233 + *
  234 + * @param string $locator select id, name or label
  235 + *
  236 + * @return Boolean
  237 + */
  238 + public function hasSelect($locator)
  239 + {
  240 + return $this->has('named', array('select', $locator));
  241 + }
  242 +
  243 + /**
  244 + * Selects option from select field with specified locator.
  245 + *
  246 + * @param string $locator input id, name or label
  247 + * @param string $value option value
  248 + * @param Boolean $multiple select multiple options
  249 + *
  250 + * @throws ElementNotFoundException
  251 + *
  252 + * @see NodeElement::selectOption
  253 + */
  254 + public function selectFieldOption($locator, $value, $multiple = false)
  255 + {
  256 + $field = $this->findField($locator);
  257 +
  258 + if (null === $field) {
  259 + throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value', $locator);
  260 + }
  261 +
  262 + $field->selectOption($value, $multiple);
  263 + }
  264 +
  265 + /**
  266 + * Checks whether element has a table with specified locator.
  267 + *
  268 + * @param string $locator table id or caption
  269 + *
  270 + * @return Boolean
  271 + */
  272 + public function hasTable($locator)
  273 + {
  274 + return $this->has('named', array('table', $locator));
  275 + }
  276 +
  277 + /**
  278 + * Attach file to file field with specified locator.
  279 + *
  280 + * @param string $locator input id, name or label
  281 + * @param string $path path to file
  282 + *
  283 + * @throws ElementNotFoundException
  284 + *
  285 + * @see NodeElement::attachFile
  286 + */
  287 + public function attachFileToField($locator, $path)
  288 + {
  289 + $field = $this->findField($locator);
  290 +
  291 + if (null === $field) {
  292 + throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value', $locator);
  293 + }
  294 +
  295 + $field->attachFile($path);
  296 + }
  297 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Exception;
  12 +
  13 +/**
  14 + * Exception thrown by drivers when they fail to perform an action.
  15 + *
  16 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  17 + */
  18 +class DriverException extends Exception
  19 +{
  20 + /**
  21 + * Initializes exception.
  22 + *
  23 + * @param string $message
  24 + * @param int $code
  25 + * @param \Exception|null $previous
  26 + */
  27 + public function __construct($message, $code = 0, \Exception $previous = null)
  28 + {
  29 + parent::__construct($message, $code, $previous);
  30 + }
  31 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Exception;
  12 +
  13 +@trigger_error('The class '.__NAMESPACE__.'\ElementException is deprecated as of Mink 1.6 and will be removed in 2.0', E_USER_DEPRECATED);
  14 +
  15 +use Behat\Mink\Element\Element;
  16 +
  17 +/**
  18 + * A standard way for elements to re-throw exceptions.
  19 + *
  20 + * @deprecated This exception class is not used anymore in Mink 1.6 and will be removed in 2.0
  21 + *
  22 + * @author Chris Worfolk <xmeltrut@gmail.com>
  23 + */
  24 +class ElementException extends Exception
  25 +{
  26 + private $element;
  27 +
  28 + /**
  29 + * Initialises exception.
  30 + *
  31 + * @param Element $element optional message
  32 + * @param \Exception $exception exception
  33 + */
  34 + public function __construct(Element $element, \Exception $exception)
  35 + {
  36 + $this->element = $element;
  37 +
  38 + parent::__construct(sprintf("Exception thrown by %s\n%s", $element->getXpath(), $exception->getMessage()));
  39 + }
  40 +
  41 + /**
  42 + * Override default toString so we don't send a full backtrace in verbose mode.
  43 + *
  44 + * @return string
  45 + */
  46 + public function __toString()
  47 + {
  48 + return $this->getMessage();
  49 + }
  50 +
  51 + /**
  52 + * Get the element that caused the exception.
  53 + *
  54 + * @return Element
  55 + */
  56 + public function getElement()
  57 + {
  58 + return $this->element;
  59 + }
  60 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Exception;
  12 +
  13 +use Behat\Mink\Driver\DriverInterface;
  14 +use Behat\Mink\Element\Element;
  15 +use Behat\Mink\Session;
  16 +
  17 +/**
  18 + * Exception thrown when an expectation on the HTML of an element fails.
  19 + *
  20 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  21 + */
  22 +class ElementHtmlException extends ExpectationException
  23 +{
  24 + /**
  25 + * Element instance.
  26 + *
  27 + * @var Element
  28 + */
  29 + protected $element;
  30 +
  31 + /**
  32 + * Initializes exception.
  33 + *
  34 + * @param string $message optional message
  35 + * @param DriverInterface|Session $driver driver instance
  36 + * @param Element $element element
  37 + * @param \Exception $exception expectation exception
  38 + */
  39 + public function __construct($message, $driver, Element $element, \Exception $exception = null)
  40 + {
  41 + $this->element = $element;
  42 +
  43 + parent::__construct($message, $driver, $exception);
  44 + }
  45 +
  46 + protected function getContext()
  47 + {
  48 + return $this->element->getOuterHtml();
  49 + }
  50 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Exception;
  12 +
  13 +use Behat\Mink\Driver\DriverInterface;
  14 +use Behat\Mink\Session;
  15 +
  16 +/**
  17 + * Exception thrown when an expected element is not found.
  18 + *
  19 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  20 + */
  21 +class ElementNotFoundException extends ExpectationException
  22 +{
  23 + /**
  24 + * Initializes exception.
  25 + *
  26 + * @param DriverInterface|Session $driver driver instance
  27 + * @param string $type element type
  28 + * @param string $selector element selector type
  29 + * @param string $locator element locator
  30 + */
  31 + public function __construct($driver, $type = null, $selector = null, $locator = null)
  32 + {
  33 + $message = '';
  34 +
  35 + if (null !== $type) {
  36 + $message .= ucfirst($type);
  37 + } else {
  38 + $message .= 'Tag';
  39 + }
  40 +
  41 + if (null !== $locator) {
  42 + if (null === $selector || in_array($selector, array('css', 'xpath'))) {
  43 + $selector = 'matching '.($selector ?: 'locator');
  44 + } else {
  45 + $selector = 'with '.$selector;
  46 + }
  47 + $message .= ' '.$selector.' "'.$locator.'"';
  48 + }
  49 +
  50 + $message .= ' not found.';
  51 +
  52 + parent::__construct($message, $driver);
  53 + }
  54 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Exception;
  12 +
  13 +/**
  14 + * Exception thrown when an expectation on the text of an element fails.
  15 + *
  16 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  17 + */
  18 +class ElementTextException extends ElementHtmlException
  19 +{
  20 + protected function getContext()
  21 + {
  22 + return $this->element->getText();
  23 + }
  24 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Exception;
  12 +
  13 +/**
  14 + * Mink base exception class.
  15 + *
  16 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  17 + */
  18 +abstract class Exception extends \Exception
  19 +{
  20 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Exception;
  12 +
  13 +use Behat\Mink\Driver\DriverInterface;
  14 +use Behat\Mink\Session;
  15 +
  16 +/**
  17 + * Exception thrown for failed expectations.
  18 + *
  19 + * Some specialized child classes are available to customize the error rendering.
  20 + *
  21 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  22 + */
  23 +class ExpectationException extends Exception
  24 +{
  25 + private $session;
  26 + private $driver;
  27 +
  28 + /**
  29 + * Initializes exception.
  30 + *
  31 + * @param string $message optional message
  32 + * @param DriverInterface|Session $driver driver instance (or session for BC)
  33 + * @param \Exception|null $exception expectation exception
  34 + */
  35 + public function __construct($message, $driver, \Exception $exception = null)
  36 + {
  37 + if ($driver instanceof Session) {
  38 + @trigger_error('Passing a Session object to the ExpectationException constructor is deprecated as of Mink 1.7. Pass the driver instead.', E_USER_DEPRECATED);
  39 +
  40 + $this->session = $driver;
  41 + $this->driver = $driver->getDriver();
  42 + } elseif (!$driver instanceof DriverInterface) {
  43 + // Trigger an exception as we cannot typehint a disjunction
  44 + throw new \InvalidArgumentException('The ExpectationException constructor expects a DriverInterface or a Session.');
  45 + } else {
  46 + $this->driver = $driver;
  47 + }
  48 +
  49 + if (!$message && null !== $exception) {
  50 + $message = $exception->getMessage();
  51 + }
  52 +
  53 + parent::__construct($message, 0, $exception);
  54 + }
  55 +
  56 + /**
  57 + * Returns exception message with additional context info.
  58 + *
  59 + * @return string
  60 + */
  61 + public function __toString()
  62 + {
  63 + try {
  64 + $pageText = $this->pipeString($this->trimString($this->getContext())."\n");
  65 + $string = sprintf("%s\n\n%s%s", $this->getMessage(), $this->getResponseInfo(), $pageText);
  66 + } catch (\Exception $e) {
  67 + return $this->getMessage();
  68 + }
  69 +
  70 + return $string;
  71 + }
  72 +
  73 + /**
  74 + * Gets the context rendered for this exception.
  75 + *
  76 + * @return string
  77 + */
  78 + protected function getContext()
  79 + {
  80 + return $this->trimBody($this->driver->getContent());
  81 + }
  82 +
  83 + /**
  84 + * Returns driver.
  85 + *
  86 + * @return DriverInterface
  87 + */
  88 + protected function getDriver()
  89 + {
  90 + return $this->driver;
  91 + }
  92 +
  93 + /**
  94 + * Returns exception session.
  95 + *
  96 + * @return Session
  97 + *
  98 + * @deprecated since 1.7, to be removed in 2.0. Use getDriver and the driver API instead.
  99 + */
  100 + protected function getSession()
  101 + {
  102 + if (null === $this->session) {
  103 + throw new \LogicException(sprintf('The deprecated method %s cannot be used when passing a driver in the constructor', __METHOD__));
  104 + }
  105 +
  106 + @trigger_error(sprintf('The method %s is deprecated as of Mink 1.7 and will be removed in 2.0. Use getDriver and the driver API instead.', __METHOD__), E_USER_DEPRECATED);
  107 +
  108 + return $this->session;
  109 + }
  110 +
  111 + /**
  112 + * Prepends every line in a string with pipe (|).
  113 + *
  114 + * @param string $string
  115 + *
  116 + * @return string
  117 + */
  118 + protected function pipeString($string)
  119 + {
  120 + return '| '.strtr($string, array("\n" => "\n| "));
  121 + }
  122 +
  123 + /**
  124 + * Removes response header/footer, letting only <body /> content.
  125 + *
  126 + * @param string $string response content
  127 + *
  128 + * @return string
  129 + */
  130 + protected function trimBody($string)
  131 + {
  132 + $string = preg_replace(array('/^.*<body>/s', '/<\/body>.*$/s'), array('<body>', '</body>'), $string);
  133 +
  134 + return $string;
  135 + }
  136 +
  137 + /**
  138 + * Trims string to specified number of chars.
  139 + *
  140 + * @param string $string response content
  141 + * @param int $count trim count
  142 + *
  143 + * @return string
  144 + */
  145 + protected function trimString($string, $count = 1000)
  146 + {
  147 + $string = trim($string);
  148 +
  149 + if ($count < mb_strlen($string)) {
  150 + return mb_substr($string, 0, $count - 3).'...';
  151 + }
  152 +
  153 + return $string;
  154 + }
  155 +
  156 + /**
  157 + * Returns response information string.
  158 + *
  159 + * @return string
  160 + */
  161 + protected function getResponseInfo()
  162 + {
  163 + $driver = basename(str_replace('\\', '/', get_class($this->driver)));
  164 +
  165 + $info = '+--[ ';
  166 + try {
  167 + $info .= 'HTTP/1.1 '.$this->driver->getStatusCode().' | ';
  168 + } catch (UnsupportedDriverActionException $e) {
  169 + // Ignore the status code when not supported
  170 + }
  171 + $info .= $this->driver->getCurrentUrl().' | '.$driver." ]\n|\n";
  172 +
  173 + return $info;
  174 + }
  175 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Exception;
  12 +
  13 +/**
  14 + * Exception thrown when an expectation on the response text fails.
  15 + *
  16 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  17 + */
  18 +class ResponseTextException extends ExpectationException
  19 +{
  20 + protected function getContext()
  21 + {
  22 + return $this->getDriver()->getText('//html');
  23 + }
  24 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Exception;
  12 +
  13 +use Behat\Mink\Driver\DriverInterface;
  14 +
  15 +/**
  16 + * Exception thrown by drivers when they don't support the requested action.
  17 + *
  18 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  19 + */
  20 +class UnsupportedDriverActionException extends DriverException
  21 +{
  22 + /**
  23 + * Initializes exception.
  24 + *
  25 + * @param string $template what is unsupported?
  26 + * @param DriverInterface $driver driver instance
  27 + * @param \Exception $previous previous exception
  28 + */
  29 + public function __construct($template, DriverInterface $driver, \Exception $previous = null)
  30 + {
  31 + $message = sprintf($template, get_class($driver));
  32 +
  33 + parent::__construct($message, 0, $previous);
  34 + }
  35 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink;
  12 +
  13 +/**
  14 + * Mink sessions manager.
  15 + *
  16 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  17 + */
  18 +class Mink
  19 +{
  20 + private $defaultSessionName;
  21 +
  22 + /**
  23 + * Sessions.
  24 + *
  25 + * @var Session[]
  26 + */
  27 + private $sessions = array();
  28 +
  29 + /**
  30 + * Initializes manager.
  31 + *
  32 + * @param Session[] $sessions
  33 + */
  34 + public function __construct(array $sessions = array())
  35 + {
  36 + foreach ($sessions as $name => $session) {
  37 + $this->registerSession($name, $session);
  38 + }
  39 + }
  40 +
  41 + /**
  42 + * Stops all started sessions.
  43 + */
  44 + public function __destruct()
  45 + {
  46 + $this->stopSessions();
  47 + }
  48 +
  49 + /**
  50 + * Registers new session.
  51 + *
  52 + * @param string $name
  53 + * @param Session $session
  54 + */
  55 + public function registerSession($name, Session $session)
  56 + {
  57 + $name = strtolower($name);
  58 +
  59 + $this->sessions[$name] = $session;
  60 + }
  61 +
  62 + /**
  63 + * Checks whether session with specified name is registered.
  64 + *
  65 + * @param string $name
  66 + *
  67 + * @return Boolean
  68 + */
  69 + public function hasSession($name)
  70 + {
  71 + return isset($this->sessions[strtolower($name)]);
  72 + }
  73 +
  74 + /**
  75 + * Sets default session name to use.
  76 + *
  77 + * @param string $name name of the registered session
  78 + *
  79 + * @throws \InvalidArgumentException
  80 + */
  81 + public function setDefaultSessionName($name)
  82 + {
  83 + $name = strtolower($name);
  84 +
  85 + if (!isset($this->sessions[$name])) {
  86 + throw new \InvalidArgumentException(sprintf('Session "%s" is not registered.', $name));
  87 + }
  88 +
  89 + $this->defaultSessionName = $name;
  90 + }
  91 +
  92 + /**
  93 + * Returns default session name or null if none.
  94 + *
  95 + * @return null|string
  96 + */
  97 + public function getDefaultSessionName()
  98 + {
  99 + return $this->defaultSessionName;
  100 + }
  101 +
  102 + /**
  103 + * Returns registered session by it's name or default one.
  104 + *
  105 + * @param string $name session name
  106 + *
  107 + * @return Session
  108 + *
  109 + * @throws \InvalidArgumentException If the named session is not registered
  110 + */
  111 + public function getSession($name = null)
  112 + {
  113 + return $this->locateSession($name);
  114 + }
  115 +
  116 + /**
  117 + * Checks whether a named session (or the default session) has already been started.
  118 + *
  119 + * @param string $name session name - if null then the default session will be checked
  120 + *
  121 + * @return bool whether the session has been started
  122 + *
  123 + * @throws \InvalidArgumentException If the named session is not registered
  124 + */
  125 + public function isSessionStarted($name = null)
  126 + {
  127 + $session = $this->locateSession($name);
  128 +
  129 + return $session->isStarted();
  130 + }
  131 +
  132 + /**
  133 + * Returns session asserter.
  134 + *
  135 + * @param Session|string $session session object or name
  136 + *
  137 + * @return WebAssert
  138 + */
  139 + public function assertSession($session = null)
  140 + {
  141 + if (!($session instanceof Session)) {
  142 + $session = $this->getSession($session);
  143 + }
  144 +
  145 + return new WebAssert($session);
  146 + }
  147 +
  148 + /**
  149 + * Resets all started sessions.
  150 + */
  151 + public function resetSessions()
  152 + {
  153 + foreach ($this->sessions as $session) {
  154 + if ($session->isStarted()) {
  155 + $session->reset();
  156 + }
  157 + }
  158 + }
  159 +
  160 + /**
  161 + * Restarts all started sessions.
  162 + */
  163 + public function restartSessions()
  164 + {
  165 + foreach ($this->sessions as $session) {
  166 + if ($session->isStarted()) {
  167 + $session->restart();
  168 + }
  169 + }
  170 + }
  171 +
  172 + /**
  173 + * Stops all started sessions.
  174 + */
  175 + public function stopSessions()
  176 + {
  177 + foreach ($this->sessions as $session) {
  178 + if ($session->isStarted()) {
  179 + $session->stop();
  180 + }
  181 + }
  182 + }
  183 +
  184 + /**
  185 + * Returns the named or default session without starting it.
  186 + *
  187 + * @param string $name session name
  188 + *
  189 + * @return Session
  190 + *
  191 + * @throws \InvalidArgumentException If the named session is not registered
  192 + */
  193 + protected function locateSession($name = null)
  194 + {
  195 + $name = strtolower($name) ?: $this->defaultSessionName;
  196 +
  197 + if (null === $name) {
  198 + throw new \InvalidArgumentException('Specify session name to get');
  199 + }
  200 +
  201 + if (!isset($this->sessions[$name])) {
  202 + throw new \InvalidArgumentException(sprintf('Session "%s" is not registered.', $name));
  203 + }
  204 +
  205 + $session = $this->sessions[$name];
  206 +
  207 + return $session;
  208 + }
  209 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Selector;
  12 +
  13 +use Symfony\Component\CssSelector\CssSelector as CSS;
  14 +use Symfony\Component\CssSelector\CssSelectorConverter;
  15 +
  16 +/**
  17 + * CSS selector engine. Transforms CSS to XPath.
  18 + *
  19 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  20 + */
  21 +class CssSelector implements SelectorInterface
  22 +{
  23 + /**
  24 + * Translates CSS into XPath.
  25 + *
  26 + * @param string|array $locator current selector locator
  27 + *
  28 + * @return string
  29 + */
  30 + public function translateToXPath($locator)
  31 + {
  32 + if (!is_string($locator)) {
  33 + throw new \InvalidArgumentException('The CssSelector expects to get a string as locator');
  34 + }
  35 +
  36 + // Symfony 2.8+ API
  37 + if (class_exists('Symfony\Component\CssSelector\CssSelectorConverter')) {
  38 + $converter = new CssSelectorConverter();
  39 +
  40 + return $converter->toXPath($locator);
  41 + }
  42 +
  43 + // old static API for Symfony 2.7 and older
  44 + return CSS::toXPath($locator);
  45 + }
  46 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Selector;
  12 +
  13 +/**
  14 + * Exact match selector engine. Like the Named selector engine but ignores partial matches.
  15 + */
  16 +class ExactNamedSelector extends NamedSelector
  17 +{
  18 + public function __construct()
  19 + {
  20 + $this->registerReplacement('%tagTextMatch%', 'normalize-space(string(.)) = %locator%');
  21 + $this->registerReplacement('%valueMatch%', './@value = %locator%');
  22 + $this->registerReplacement('%titleMatch%', './@title = %locator%');
  23 + $this->registerReplacement('%altMatch%', './@alt = %locator%');
  24 + $this->registerReplacement('%relMatch%', './@rel = %locator%');
  25 + $this->registerReplacement('%labelAttributeMatch%', './@label = %locator%');
  26 +
  27 + parent::__construct();
  28 + }
  29 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Selector;
  12 +
  13 +use Behat\Mink\Selector\Xpath\Escaper;
  14 +
  15 +/**
  16 + * Named selectors engine. Uses registered XPath selectors to create new expressions.
  17 + *
  18 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  19 + */
  20 +class NamedSelector implements SelectorInterface
  21 +{
  22 + private $replacements = array(
  23 + // simple replacements
  24 + '%lowercaseType%' => "translate(./@type, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')",
  25 + '%lowercaseRole%' => "translate(./@role, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')",
  26 + '%tagTextMatch%' => 'contains(normalize-space(string(.)), %locator%)',
  27 + '%labelTextMatch%' => './@id = //label[%tagTextMatch%]/@for',
  28 + '%idMatch%' => './@id = %locator%',
  29 + '%valueMatch%' => 'contains(./@value, %locator%)',
  30 + '%idOrValueMatch%' => '(%idMatch% or %valueMatch%)',
  31 + '%idOrNameMatch%' => '(%idMatch% or ./@name = %locator%)',
  32 + '%placeholderMatch%' => './@placeholder = %locator%',
  33 + '%titleMatch%' => 'contains(./@title, %locator%)',
  34 + '%altMatch%' => 'contains(./@alt, %locator%)',
  35 + '%relMatch%' => 'contains(./@rel, %locator%)',
  36 + '%labelAttributeMatch%' => 'contains(./@label, %locator%)',
  37 +
  38 + // complex replacements
  39 + '%inputTypeWithoutPlaceholderFilter%' => "%lowercaseType% = 'radio' or %lowercaseType% = 'checkbox' or %lowercaseType% = 'file'",
  40 + '%fieldFilterWithPlaceholder%' => 'self::input[not(%inputTypeWithoutPlaceholderFilter%)] | self::textarea',
  41 + '%fieldMatchWithPlaceholder%' => '(%idOrNameMatch% or %labelTextMatch% or %placeholderMatch%)',
  42 + '%fieldMatchWithoutPlaceholder%' => '(%idOrNameMatch% or %labelTextMatch%)',
  43 + '%fieldFilterWithoutPlaceholder%' => 'self::input[%inputTypeWithoutPlaceholderFilter%] | self::select',
  44 + '%buttonTypeFilter%' => "%lowercaseType% = 'submit' or %lowercaseType% = 'image' or %lowercaseType% = 'button' or %lowercaseType% = 'reset'",
  45 + '%notFieldTypeFilter%' => "not(%buttonTypeFilter% or %lowercaseType% = 'hidden')",
  46 + '%buttonMatch%' => '%idOrNameMatch% or %valueMatch% or %titleMatch%',
  47 + '%linkMatch%' => '(%idMatch% or %tagTextMatch% or %titleMatch% or %relMatch%)',
  48 + '%imgAltMatch%' => './/img[%altMatch%]',
  49 + );
  50 +
  51 + private $selectors = array(
  52 + 'fieldset' => <<<XPATH
  53 +.//fieldset
  54 +[(%idMatch% or .//legend[%tagTextMatch%])]
  55 +XPATH
  56 +
  57 + ,'field' => <<<XPATH
  58 +.//*
  59 +[%fieldFilterWithPlaceholder%][%notFieldTypeFilter%][%fieldMatchWithPlaceholder%]
  60 +|
  61 +.//label[%tagTextMatch%]//.//*[%fieldFilterWithPlaceholder%][%notFieldTypeFilter%]
  62 +|
  63 +.//*
  64 +[%fieldFilterWithoutPlaceholder%][%notFieldTypeFilter%][%fieldMatchWithoutPlaceholder%]
  65 +|
  66 +.//label[%tagTextMatch%]//.//*[%fieldFilterWithoutPlaceholder%][%notFieldTypeFilter%]
  67 +XPATH
  68 +
  69 + ,'link' => <<<XPATH
  70 +.//a
  71 +[./@href][(%linkMatch% or %imgAltMatch%)]
  72 +|
  73 +.//*
  74 +[%lowercaseRole% = 'link'][(%idOrValueMatch% or %titleMatch% or %tagTextMatch%)]
  75 +XPATH
  76 +
  77 + ,'button' => <<<XPATH
  78 +.//input
  79 +[%buttonTypeFilter%][(%buttonMatch%)]
  80 +|
  81 +.//input
  82 +[%lowercaseType% = 'image'][%altMatch%]
  83 +|
  84 +.//button
  85 +[(%buttonMatch% or %tagTextMatch%)]
  86 +|
  87 +.//*
  88 +[%lowercaseRole% = 'button'][(%buttonMatch% or %tagTextMatch%)]
  89 +XPATH
  90 +
  91 + ,'link_or_button' => <<<XPATH
  92 +.//a
  93 +[./@href][(%linkMatch% or %imgAltMatch%)]
  94 +|
  95 +.//input
  96 +[%buttonTypeFilter%][(%idOrValueMatch% or %titleMatch%)]
  97 +|
  98 +.//input
  99 +[%lowercaseType% = 'image'][%altMatch%]
  100 +|
  101 +.//button
  102 +[(%idOrValueMatch% or %titleMatch% or %tagTextMatch%)]
  103 +|
  104 +.//*
  105 +[(%lowercaseRole% = 'button' or %lowercaseRole% = 'link')][(%idOrValueMatch% or %titleMatch% or %tagTextMatch%)]
  106 +XPATH
  107 +
  108 + ,'content' => <<<XPATH
  109 +./descendant-or-self::*
  110 +[%tagTextMatch%]
  111 +XPATH
  112 +
  113 + ,'select' => <<<XPATH
  114 +.//select
  115 +[%fieldMatchWithoutPlaceholder%]
  116 +|
  117 +.//label[%tagTextMatch%]//.//select
  118 +XPATH
  119 +
  120 + ,'checkbox' => <<<XPATH
  121 +.//input
  122 +[%lowercaseType% = 'checkbox'][%fieldMatchWithoutPlaceholder%]
  123 +|
  124 +.//label[%tagTextMatch%]//.//input[%lowercaseType% = 'checkbox']
  125 +XPATH
  126 +
  127 + ,'radio' => <<<XPATH
  128 +.//input
  129 +[%lowercaseType% = 'radio'][%fieldMatchWithoutPlaceholder%]
  130 +|
  131 +.//label[%tagTextMatch%]//.//input[%lowercaseType% = 'radio']
  132 +XPATH
  133 +
  134 + ,'file' => <<<XPATH
  135 +.//input
  136 +[%lowercaseType% = 'file'][%fieldMatchWithoutPlaceholder%]
  137 +|
  138 +.//label[%tagTextMatch%]//.//input[%lowercaseType% = 'file']
  139 +XPATH
  140 +
  141 + ,'optgroup' => <<<XPATH
  142 +.//optgroup
  143 +[%labelAttributeMatch%]
  144 +XPATH
  145 +
  146 + ,'option' => <<<XPATH
  147 +.//option
  148 +[(./@value = %locator% or %tagTextMatch%)]
  149 +XPATH
  150 +
  151 + ,'table' => <<<XPATH
  152 +.//table
  153 +[(%idMatch% or .//caption[%tagTextMatch%])]
  154 +XPATH
  155 + ,'id' => <<<XPATH
  156 +.//*[%idMatch%]
  157 +XPATH
  158 + ,'id_or_name' => <<<XPATH
  159 +.//*[%idOrNameMatch%]
  160 +XPATH
  161 + );
  162 + private $xpathEscaper;
  163 +
  164 + /**
  165 + * Creates selector instance.
  166 + */
  167 + public function __construct()
  168 + {
  169 + $this->xpathEscaper = new Escaper();
  170 +
  171 + foreach ($this->replacements as $from => $to) {
  172 + $this->replacements[$from] = strtr($to, $this->replacements);
  173 + }
  174 +
  175 + foreach ($this->selectors as $alias => $selector) {
  176 + $this->selectors[$alias] = strtr($selector, $this->replacements);
  177 + }
  178 + }
  179 +
  180 + /**
  181 + * Registers new XPath selector with specified name.
  182 + *
  183 + * @param string $name name for selector
  184 + * @param string $xpath xpath expression
  185 + */
  186 + public function registerNamedXpath($name, $xpath)
  187 + {
  188 + $this->selectors[$name] = $xpath;
  189 + }
  190 +
  191 + /**
  192 + * Translates provided locator into XPath.
  193 + *
  194 + * @param string|array $locator selector name or array of (selector_name, locator)
  195 + *
  196 + * @return string
  197 + *
  198 + * @throws \InvalidArgumentException
  199 + */
  200 + public function translateToXPath($locator)
  201 + {
  202 + if (\is_array($locator)) {
  203 + if (2 !== \count($locator)) {
  204 + throw new \InvalidArgumentException('NamedSelector expects array(name, locator) as argument');
  205 + }
  206 +
  207 + $selector = $locator[0];
  208 + $locator = $locator[1];
  209 + } else {
  210 + $selector = (string) $locator;
  211 + $locator = null;
  212 + }
  213 +
  214 + if (!isset($this->selectors[$selector])) {
  215 + throw new \InvalidArgumentException(sprintf(
  216 + 'Unknown named selector provided: "%s". Expected one of (%s)',
  217 + $selector,
  218 + implode(', ', array_keys($this->selectors))
  219 + ));
  220 + }
  221 +
  222 + $xpath = $this->selectors[$selector];
  223 +
  224 + if (null !== $locator) {
  225 + $xpath = strtr($xpath, array('%locator%' => $this->escapeLocator($locator)));
  226 + }
  227 +
  228 + return $xpath;
  229 + }
  230 +
  231 + /**
  232 + * Registers a replacement in the list of replacements.
  233 + *
  234 + * This method must be called in the constructor before calling the parent constructor.
  235 + *
  236 + * @param string $from
  237 + * @param string $to
  238 + */
  239 + protected function registerReplacement($from, $to)
  240 + {
  241 + $this->replacements[$from] = $to;
  242 + }
  243 +
  244 + private function escapeLocator($locator)
  245 + {
  246 + // If the locator looks like an escaped one, don't escape it again for BC reasons.
  247 + if (
  248 + preg_match('/^\'[^\']*+\'$/', $locator)
  249 + || (false !== strpos($locator, '\'') && preg_match('/^"[^"]*+"$/', $locator))
  250 + || ((8 < $length = strlen($locator)) && 'concat(' === substr($locator, 0, 7) && ')' === $locator[$length - 1])
  251 + ) {
  252 + @trigger_error(
  253 + 'Passing an escaped locator to the named selector is deprecated as of 1.7 and will be removed in 2.0.'
  254 + .' Pass the raw value instead.',
  255 + E_USER_DEPRECATED
  256 + );
  257 +
  258 + return $locator;
  259 + }
  260 +
  261 + return $this->xpathEscaper->escapeLiteral($locator);
  262 + }
  263 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Selector;
  12 +
  13 +/**
  14 + * Named selectors engine. Uses registered XPath selectors to create new expressions.
  15 + *
  16 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  17 + */
  18 +class PartialNamedSelector extends NamedSelector
  19 +{
  20 + public function __construct()
  21 + {
  22 + $this->registerReplacement('%tagTextMatch%', 'contains(normalize-space(string(.)), %locator%)');
  23 + $this->registerReplacement('%valueMatch%', 'contains(./@value, %locator%)');
  24 + $this->registerReplacement('%titleMatch%', 'contains(./@title, %locator%)');
  25 + $this->registerReplacement('%altMatch%', 'contains(./@alt, %locator%)');
  26 + $this->registerReplacement('%relMatch%', 'contains(./@rel, %locator%)');
  27 + $this->registerReplacement('%labelAttributeMatch%', 'contains(./@label, %locator%)');
  28 +
  29 + parent::__construct();
  30 + }
  31 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Selector;
  12 +
  13 +/**
  14 + * Mink selector engine interface.
  15 + *
  16 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  17 + */
  18 +interface SelectorInterface
  19 +{
  20 + /**
  21 + * Translates provided locator into XPath.
  22 + *
  23 + * @param string|array $locator current selector locator
  24 + *
  25 + * @return string
  26 + */
  27 + public function translateToXPath($locator);
  28 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Selector;
  12 +
  13 +use Behat\Mink\Selector\Xpath\Escaper;
  14 +
  15 +/**
  16 + * Selectors handler.
  17 + *
  18 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  19 + */
  20 +class SelectorsHandler
  21 +{
  22 + private $selectors;
  23 + private $escaper;
  24 +
  25 + /**
  26 + * Initializes selectors handler.
  27 + *
  28 + * @param SelectorInterface[] $selectors default selectors to register
  29 + */
  30 + public function __construct(array $selectors = array())
  31 + {
  32 + $this->escaper = new Escaper();
  33 +
  34 + $this->registerSelector('named_partial', new PartialNamedSelector());
  35 + $this->registerSelector('named_exact', new ExactNamedSelector());
  36 + $this->registerSelector('css', new CssSelector());
  37 +
  38 + foreach ($selectors as $name => $selector) {
  39 + $this->registerSelector($name, $selector);
  40 + }
  41 + }
  42 +
  43 + /**
  44 + * Registers new selector engine with specified name.
  45 + *
  46 + * @param string $name selector engine name
  47 + * @param SelectorInterface $selector selector engine instance
  48 + */
  49 + public function registerSelector($name, SelectorInterface $selector)
  50 + {
  51 + $this->selectors[$name] = $selector;
  52 + }
  53 +
  54 + /**
  55 + * Checks whether selector with specified name is registered on handler.
  56 + *
  57 + * @param string $name selector engine name
  58 + *
  59 + * @return Boolean
  60 + */
  61 + public function isSelectorRegistered($name)
  62 + {
  63 + return isset($this->selectors[$name]);
  64 + }
  65 +
  66 + /**
  67 + * Returns selector engine with specified name.
  68 + *
  69 + * @param string $name selector engine name
  70 + *
  71 + * @return SelectorInterface
  72 + *
  73 + * @throws \InvalidArgumentException
  74 + */
  75 + public function getSelector($name)
  76 + {
  77 + if ('named' === $name) {
  78 + @trigger_error(
  79 + 'Using the "named" selector directly from the handler is deprecated as of 1.6 and will be removed in 2.0.'
  80 + .' Use the "named_partial" or use the "named" selector through the Element API instead.',
  81 + E_USER_DEPRECATED
  82 + );
  83 + $name = 'named_partial';
  84 + }
  85 +
  86 + if (!$this->isSelectorRegistered($name)) {
  87 + throw new \InvalidArgumentException("Selector \"$name\" is not registered.");
  88 + }
  89 +
  90 + return $this->selectors[$name];
  91 + }
  92 +
  93 + /**
  94 + * Translates selector with specified name to XPath.
  95 + *
  96 + * @param string $selector selector engine name (registered)
  97 + * @param string|array $locator selector locator (an array or a string depending of the selector being used)
  98 + *
  99 + * @return string
  100 + */
  101 + public function selectorToXpath($selector, $locator)
  102 + {
  103 + if ('xpath' === $selector) {
  104 + if (!is_string($locator)) {
  105 + throw new \InvalidArgumentException('The xpath selector expects to get a string as locator');
  106 + }
  107 +
  108 + return $locator;
  109 + }
  110 +
  111 + return $this->getSelector($selector)->translateToXPath($locator);
  112 + }
  113 +
  114 + /**
  115 + * Translates string to XPath literal.
  116 + *
  117 + * @deprecated since Mink 1.7. Use \Behat\Mink\Selector\Xpath\Escaper::escapeLiteral when building Xpath
  118 + * or pass the unescaped value when using the named selector.
  119 + *
  120 + * @param string $s
  121 + *
  122 + * @return string
  123 + */
  124 + public function xpathLiteral($s)
  125 + {
  126 + @trigger_error(
  127 + 'The '.__METHOD__.' method is deprecated as of 1.7 and will be removed in 2.0.'
  128 + .' Use \Behat\Mink\Selector\Xpath\Escaper::escapeLiteral instead when building Xpath'
  129 + .' or pass the unescaped value when using the named selector.',
  130 + E_USER_DEPRECATED
  131 + );
  132 +
  133 + return $this->escaper->escapeLiteral($s);
  134 + }
  135 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Selector\Xpath;
  12 +
  13 +/**
  14 + * XPath escaper.
  15 + *
  16 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  17 + */
  18 +class Escaper
  19 +{
  20 + /**
  21 + * Escapes the string as a XPath literal.
  22 + *
  23 + * @param string $s
  24 + *
  25 + * @return string
  26 + */
  27 + public function escapeLiteral($s)
  28 + {
  29 + if (false === strpos($s, "'")) {
  30 + return sprintf("'%s'", $s);
  31 + }
  32 +
  33 + if (false === strpos($s, '"')) {
  34 + return sprintf('"%s"', $s);
  35 + }
  36 +
  37 + $string = $s;
  38 + $parts = array();
  39 + while (true) {
  40 + if (false !== $pos = strpos($string, "'")) {
  41 + $parts[] = sprintf("'%s'", substr($string, 0, $pos));
  42 + $parts[] = "\"'\"";
  43 + $string = substr($string, $pos + 1);
  44 + } else {
  45 + $parts[] = "'$string'";
  46 + break;
  47 + }
  48 + }
  49 +
  50 + return sprintf('concat(%s)', implode($parts, ','));
  51 + }
  52 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink\Selector\Xpath;
  12 +
  13 +/**
  14 + * XPath manipulation utility.
  15 + *
  16 + * @author Graham Bates
  17 + * @author Christophe Coevoet <stof@notk.org>
  18 + */
  19 +class Manipulator
  20 +{
  21 + /**
  22 + * Regex to find union operators not inside brackets.
  23 + */
  24 + const UNION_PATTERN = '/\|(?![^\[]*\])/';
  25 +
  26 + /**
  27 + * Prepends the XPath prefix to the given XPath.
  28 + *
  29 + * The returned XPath will match elements matching the XPath inside an element
  30 + * matching the prefix.
  31 + *
  32 + * @param string $xpath
  33 + * @param string $prefix
  34 + *
  35 + * @return string
  36 + */
  37 + public function prepend($xpath, $prefix)
  38 + {
  39 + $expressions = array();
  40 +
  41 + // If the xpath prefix contains a union we need to wrap it in parentheses.
  42 + if (preg_match(self::UNION_PATTERN, $prefix)) {
  43 + $prefix = '('.$prefix.')';
  44 + }
  45 +
  46 + // Split any unions into individual expressions.
  47 + foreach ($this->splitUnionParts($xpath) as $expression) {
  48 + $expression = trim($expression);
  49 + $parenthesis = '';
  50 +
  51 + // If the union is inside some braces, we need to preserve the opening braces and apply
  52 + // the prefix only inside it.
  53 + if (preg_match('/^[\(\s*]+/', $expression, $matches)) {
  54 + $parenthesis = $matches[0];
  55 + $expression = substr($expression, strlen($parenthesis));
  56 + }
  57 +
  58 + // add prefix before element selector
  59 + if (0 === strpos($expression, '/')) {
  60 + $expression = $prefix.$expression;
  61 + } else {
  62 + $expression = $prefix.'/'.$expression;
  63 + }
  64 + $expressions[] = $parenthesis.$expression;
  65 + }
  66 +
  67 + return implode(' | ', $expressions);
  68 + }
  69 +
  70 + /**
  71 + * Splits the XPath into parts that are separated by the union operator.
  72 + *
  73 + * @param string $xpath
  74 + *
  75 + * @return string[]
  76 + */
  77 + private function splitUnionParts($xpath)
  78 + {
  79 + if (false === strpos($xpath, '|')) {
  80 + return array($xpath); // If there is no pipe in the string, we know for sure that there is no union
  81 + }
  82 +
  83 + $xpathLen = strlen($xpath);
  84 + $openedBrackets = 0;
  85 + // Consume whitespaces chars at the beginning of the string (this is the list of chars removed by trim() by default)
  86 + $startPosition = strspn($xpath, " \t\n\r\0\x0B");
  87 +
  88 + $unionParts = array();
  89 +
  90 + for ($i = $startPosition; $i <= $xpathLen; ++$i) {
  91 + // Consume all chars until we reach a quote, a bracket or a pipe
  92 + $i += strcspn($xpath, '"\'[]|', $i);
  93 +
  94 + if ($i < $xpathLen) {
  95 + switch ($xpath[$i]) {
  96 + case '"':
  97 + case "'":
  98 + // Move to the end of the string literal
  99 + if (false === $i = strpos($xpath, $xpath[$i], $i + 1)) {
  100 + return array($xpath); // The XPath expression is invalid, don't split it
  101 + }
  102 + continue 2;
  103 + case '[':
  104 + ++$openedBrackets;
  105 + continue 2;
  106 + case ']':
  107 + --$openedBrackets;
  108 + continue 2;
  109 + }
  110 + }
  111 + if ($openedBrackets) {
  112 + continue;
  113 + }
  114 +
  115 + $unionParts[] = substr($xpath, $startPosition, $i - $startPosition);
  116 +
  117 + if ($i === $xpathLen) {
  118 + return $unionParts;
  119 + }
  120 +
  121 + // Consume any whitespace chars after the pipe
  122 + $i += strspn($xpath, " \t\n\r\0\x0B", $i + 1);
  123 + $startPosition = $i + 1;
  124 + }
  125 +
  126 + return array($xpath); // The XPath expression is invalid
  127 + }
  128 +
  129 +}
... ...
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Mink package.
  5 + * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  6 + *
  7 + * For the full copyright and license information, please view the LICENSE
  8 + * file that was distributed with this source code.
  9 + */
  10 +
  11 +namespace Behat\Mink;
  12 +
  13 +use Behat\Mink\Driver\DriverInterface;
  14 +use Behat\Mink\Selector\SelectorsHandler;
  15 +use Behat\Mink\Element\DocumentElement;
  16 +
  17 +/**
  18 + * Mink session.
  19 + *
  20 + * @author Konstantin Kudryashov <ever.zet@gmail.com>
  21 + */
  22 +class Session
  23 +{
  24 + private $driver;
  25 + private $page;
  26 + private $selectorsHandler;
  27 +
  28 + /**
  29 + * Initializes session.
  30 + *
  31 + * @param DriverInterface $driver
  32 + * @param SelectorsHandler $selectorsHandler
  33 + */
  34 + public function __construct(DriverInterface $driver, SelectorsHandler $selectorsHandler = null)
  35 + {
  36 + $driver->setSession($this);
  37 +
  38 + if (null === $selectorsHandler) {
  39 + $selectorsHandler = new SelectorsHandler();
  40 + }
  41 +
  42 + $this->driver = $driver;
  43 + $this->selectorsHandler = $selectorsHandler;
  44 + $this->page = new DocumentElement($this);
  45 + }
  46 +
  47 + /**
  48 + * Checks whether session (driver) was started.
  49 + *
  50 + * @return Boolean
  51 + */
  52 + public function isStarted()
  53 + {
  54 + return $this->driver->isStarted();
  55 + }
  56 +
  57 + /**
  58 + * Starts session driver.
  59 + *
  60 + * Calling any action before visiting a page is an undefined behavior.
  61 + * The only supported method calls on a fresh driver are
  62 + * - visit()
  63 + * - setRequestHeader()
  64 + * - setBasicAuth()
  65 + * - reset()
  66 + * - stop()
  67 + */
  68 + public function start()
  69 + {
  70 + $this->driver->start();
  71 + }
  72 +
  73 + /**
  74 + * Stops session driver.
  75 + */
  76 + public function stop()
  77 + {
  78 + $this->driver->stop();
  79 + }
  80 +
  81 + /**
  82 + * Restart session driver.
  83 + */
  84 + public function restart()
  85 + {
  86 + $this->driver->stop();
  87 + $this->driver->start();
  88 + }
  89 +
  90 + /**
  91 + * Reset session driver state.
  92 + *
  93 + * Calling any action before visiting a page is an undefined behavior.
  94 + * The only supported method calls on a fresh driver are
  95 + * - visit()
  96 + * - setRequestHeader()
  97 + * - setBasicAuth()
  98 + * - reset()
  99 + * - stop()
  100 + */
  101 + public function reset()
  102 + {
  103 + $this->driver->reset();
  104 + }
  105 +
  106 + /**
  107 + * Returns session driver.
  108 + *
  109 + * @return DriverInterface
  110 + */
  111 + public function getDriver()
  112 + {
  113 + return $this->driver;
  114 + }
  115 +
  116 + /**
  117 + * Returns page element.
  118 + *
  119 + * @return DocumentElement
  120 + */
  121 + public function getPage()
  122 + {
  123 + return $this->page;
  124 + }
  125 +
  126 + /**
  127 + * Returns selectors handler.
  128 + *
  129 + * @return SelectorsHandler
  130 + */
  131 + public function getSelectorsHandler()
  132 + {
  133 + return $this->selectorsHandler;
  134 + }
  135 +
  136 + /**
  137 + * Visit specified URL and automatically start session if not already running.
  138 + *
  139 + * @param string $url url of the page
  140 + */
  141 + public function visit($url)
  142 + {
  143 + // start session if needed
  144 + if (!$this->isStarted()) {
  145 + $this->start();
  146 + }
  147 +
  148 + $this->driver->visit($url);
  149 + }
  150 +
  151 + /**
  152 + * Sets HTTP Basic authentication parameters.
  153 + *
  154 + * @param string|Boolean $user user name or false to disable authentication
  155 + * @param string $password password
  156 + */
  157 + public function setBasicAuth($user, $password = '')
  158 + {
  159 + $this->driver->setBasicAuth($user, $password);
  160 + }
  161 +
  162 + /**
  163 + * Sets specific request header.
  164 + *
  165 + * @param string $name
  166 + * @param string $value
  167 + */
  168 + public function setRequestHeader($name, $value)
  169 + {
  170 + $this->driver->setRequestHeader($name, $value);
  171 + }
  172 +
  173 + /**
  174 + * Returns all response headers.
  175 + *
  176 + * @return array
  177 + */
  178 + public function getResponseHeaders()
  179 + {
  180 + return $this->driver->getResponseHeaders();
  181 + }
  182 +
  183 + /**
  184 + * Returns specific response header.
  185 + *
  186 + * @param string $name
  187 + *
  188 + * @return string|null
  189 + */
  190 + public function getResponseHeader($name)
  191 + {
  192 + $headers = $this->driver->getResponseHeaders();
  193 +
  194 + $name = strtolower($name);
  195 + $headers = array_change_key_case($headers, CASE_LOWER);
  196 +
  197 + if (!isset($headers[$name])) {
  198 + return null;
  199 + }
  200 +
  201 + return is_array($headers[$name]) ? $headers[$name][0] : $headers[$name];
  202 + }
  203 +
  204 + /**
  205 + * Sets cookie.
  206 + *
  207 + * @param string $name
  208 + * @param string $value
  209 + */
  210 + public function setCookie($name, $value = null)
  211 + {
  212 + $this->driver->setCookie($name, $value);
  213 + }
  214 +
  215 + /**
  216 + * Returns cookie by name.
  217 + *
  218 + * @param string $name
  219 + *
  220 + * @return string|null
  221 + */
  222 + public function getCookie($name)
  223 + {
  224 + return $this->driver->getCookie($name);
  225 + }
  226 +
  227 + /**
  228 + * Returns response status code.
  229 + *
  230 + * @return int
  231 + */
  232 + public function getStatusCode()
  233 + {
  234 + return $this->driver->getStatusCode();
  235 + }
  236 +
  237 + /**
  238 + * Returns current URL address.
  239 + *
  240 + * @return string
  241 + */
  242 + public function getCurrentUrl()
  243 + {
  244 + return $this->driver->getCurrentUrl();
  245 + }
  246 +
  247 + /**
  248 + * Capture a screenshot of the current window.
  249 + *
  250 + * @return string screenshot of MIME type image/* depending
  251 + * on driver (e.g., image/png, image/jpeg)
  252 + */
  253 + public function getScreenshot()
  254 + {
  255 + return $this->driver->getScreenshot();
  256 + }
  257 +
  258 + /**
  259 + * Return the names of all open windows.
  260 + *
  261 + * @return array Array of all open window's names.
  262 + */
  263 + public function getWindowNames()
  264 + {
  265 + return $this->driver->getWindowNames();
  266 + }
  267 +
  268 + /**
  269 + * Return the name of the currently active window.
  270 + *
  271 + * @return string The name of the current window.
  272 + */
  273 + public function getWindowName()
  274 + {
  275 + return $this->driver->getWindowName();
  276 + }
  277 +
  278 + /**
  279 + * Reloads current session page.
  280 + */
  281 + public function reload()
  282 + {
  283 + $this->driver->reload();
  284 + }
  285 +
  286 + /**
  287 + * Moves backward 1 page in history.
  288 + */
  289 + public function back()
  290 + {
  291 + $this->driver->back();
  292 + }
  293 +
  294 + /**
  295 + * Moves forward 1 page in history.
  296 + */
  297 + public function forward()
  298 + {
  299 + $this->driver->forward();
  300 + }
  301 +
  302 + /**
  303 + * Switches to specific browser window.
  304 + *
  305 + * @param string $name window name (null for switching back to main window)
  306 + */
  307 + public function switchToWindow($name = null)
  308 + {
  309 + $this->driver->switchToWindow($name);
  310 + }
  311 +
  312 + /**
  313 + * Switches to specific iFrame.
  314 + *
  315 + * @param string $name iframe name (null for switching back)
  316 + */
  317 + public function switchToIFrame($name = null)
  318 + {
  319 + $this->driver->switchToIFrame($name);
  320 + }
  321 +
  322 + /**
  323 + * Execute JS in browser.
  324 + *
  325 + * @param string $script javascript
  326 + */
  327 + public function executeScript($script)
  328 + {
  329 + $this->driver->executeScript($script);
  330 + }
  331 +
  332 + /**
  333 + * Execute JS in browser and return it's response.
  334 + *
  335 + * @param string $script javascript
  336 + *
  337 + * @return string
  338 + */
  339 + public function evaluateScript($script)
  340 + {
  341 + return $this->driver->evaluateScript($script);
  342 + }
  343 +
  344 + /**
  345 + * Waits some time or until JS condition turns true.
  346 + *
  347 + * @param int $time time in milliseconds
  348 + * @param string $condition JS condition
  349 + *
  350 + * @return bool
  351 + */
  352 + public function wait($time, $condition = 'false')
  353 + {
  354 + return $this->driver->wait($time, $condition);
  355 + }
  356 +
  357 + /**
  358 + * Set the dimensions of the window.
  359 + *
  360 + * @param int $width set the window width, measured in pixels
  361 + * @param int $height set the window height, measured in pixels
  362 + * @param string $name window name (null for the main window)
  363 + */
  364 + public function resizeWindow($width, $height, $name = null)
  365 + {
  366 + $this->driver->resizeWindow($width, $height, $name);
  367 + }
  368 +
  369 + /**
  370 + * Maximize the window if it is not maximized already.
  371 + *
  372 + * @param string $name window name (null for the main window)
  373 + */
  374 + public function maximizeWindow($name = null)
  375 + {
  376 + $this->driver->maximizeWindow($name);
  377 + }
  378 +}
... ...
Please register or login to post a comment