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.
vendor/behat/mink/.gitattributes
0 → 100644
vendor/behat/mink/.gitignore
0 → 100644
vendor/behat/mink/.travis.yml
0 → 100644
| 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 | ... | ... |
vendor/behat/mink/CHANGES.md
0 → 100644
| 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 | ... | ... |
vendor/behat/mink/CONTRIBUTING.md
0 → 100644
| 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 | +``` | ... | ... |
vendor/behat/mink/LICENSE
0 → 100644
| 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. | ... | ... |
vendor/behat/mink/README.md
0 → 100644
| 1 | +Mink | |
| 2 | +==== | |
| 3 | +[](https://packagist.org/packages/behat/mink) | |
| 4 | +[](https://packagist.org/packages/behat/mink) | |
| 5 | +[](https://packagist.org/packages/behat/mink) | |
| 6 | +[](https://scrutinizer-ci.com/g/minkphp/Mink/?branch=master) | |
| 7 | +[](https://scrutinizer-ci.com/g/minkphp/Mink/) | |
| 8 | +[](https://travis-ci.org/minkphp/Mink) | |
| 9 | +[](https://insight.sensiolabs.com/projects/5bb8fab0-978f-428a-ae23-44ee4e129fbc) | |
| 10 | +[](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) | ... | ... |
vendor/behat/mink/composer.json
0 → 100644
| 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 | +} | ... | ... |
vendor/behat/mink/phpdoc.ini.dist
0 → 100644
| 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 | ... | ... |
vendor/behat/mink/phpunit.xml.dist
0 → 100644
| 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> | ... | ... |
vendor/behat/mink/src/Driver/CoreDriver.php
0 → 100644
| 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 | +} | ... | ... |
vendor/behat/mink/src/Element/Element.php
0 → 100644
| 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 | +} | ... | ... |
vendor/behat/mink/src/Mink.php
0 → 100644
| 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 | +} | ... | ... |
vendor/behat/mink/src/Session.php
0 → 100644
| 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