|
| 1 | +# Mink Extension |
| 2 | + |
| 3 | +You can use Behat to describe anything, that you can describe in business |
| 4 | +logic. It's tools, gui applications, web applications. The most interesting part |
| 5 | +is web applications. First, behavioral testing already exists in the web world - |
| 6 | +it's called functional or acceptance testing. Almost all popular frameworks |
| 7 | +and languages provide functional testing tools. Today we'll talk about how to |
| 8 | +use Behat for functional testing of web applications. [Mink](http://mink.behat.org) |
| 9 | +is a tool exactly for that and this extension provides integration for it. |
| 10 | + |
| 11 | +Basically, MinkExtension is an integration layer between Behat 3.0+ and Mink 1.4+ |
| 12 | +and it provides: |
| 13 | + |
| 14 | +* Additional services for Behat (`Mink`, `Sessions`, `Drivers`). |
| 15 | +* `Behat\MinkExtension\Context\MinkAwareContext` which provides a `Mink` |
| 16 | + instance for your contexts. |
| 17 | +* Base `Behat\MinkExtension\Context\MinkContext` context which provides base |
| 18 | + step definitions and hooks for your contexts or subcontexts. Or it could be |
| 19 | + even used as context on its own. |
| 20 | + |
| 21 | +## Installation |
| 22 | + |
| 23 | +This extension requires: |
| 24 | + |
| 25 | +* Behat 3.0+ |
| 26 | +* Mink 1.4+ |
| 27 | + |
| 28 | +### Through Composer |
| 29 | + |
| 30 | +The easiest way to keep your suite updated is to use [Composer](http://getcomposer.org): |
| 31 | + |
| 32 | +1. Install with composer: |
| 33 | + |
| 34 | + ```bash |
| 35 | + $ composer require --dev behat/mink-extension |
| 36 | + ``` |
| 37 | + |
| 38 | +2. Activate the extension by specifying its class in your `behat.yml`: |
| 39 | + |
| 40 | + ```yaml |
| 41 | + # behat.yml |
| 42 | + default: |
| 43 | + # ... |
| 44 | + extensions: |
| 45 | + Behat\MinkExtension: |
| 46 | + base_url: 'http://example.com' |
| 47 | + sessions: |
| 48 | + default: |
| 49 | + goutte: ~ |
| 50 | + ``` |
| 51 | + |
| 52 | +## Usage |
| 53 | + |
| 54 | +After installing the extension, there are 4 usage options available: |
| 55 | + |
| 56 | +1. Extending `Behat\MinkExtension\Context\RawMinkContext` in your feature suite. |
| 57 | + This will give you the ability to use a preconfigured `Mink` instance with some |
| 58 | + convenience methods: |
| 59 | + |
| 60 | + * `getSession($name = null)` |
| 61 | + * `assertSession($name = null)` |
| 62 | + |
| 63 | + `RawMinkContext` doesn't provide any hooks or definitions, so you can inherit from it |
| 64 | + in as many contexts as you want - you'll never get `RedundantStepException`. |
| 65 | + |
| 66 | +2. Extending `Behat\MinkExtension\Context\MinkContext` with one of your contexts. |
| 67 | + Exactly like the previous option, but also provides lots of predefined step definitions out |
| 68 | + of the box. As this context provides step definitions and hooks, you can use it **only once** |
| 69 | + inside your feature context tree. |
| 70 | + |
| 71 | + ```php |
| 72 | + <?php |
| 73 | +
|
| 74 | + use Behat\MinkExtension\Context\MinkContext; |
| 75 | +
|
| 76 | + class FeatureContext extends MinkContext |
| 77 | + { |
| 78 | + /** |
| 79 | + * @Then /^I wait for the suggestion box to appear$/ |
| 80 | + */ |
| 81 | + public function iWaitForTheSuggestionBoxToAppear() |
| 82 | + { |
| 83 | + $this->getSession()->wait(5000, "$('.suggestions-results').children().length > 0"); |
| 84 | + } |
| 85 | + } |
| 86 | + ``` |
| 87 | + |
| 88 | +> [!NOTE] |
| 89 | +> Keep in mind, that you can not have multiple step definitions with the same regex. |
| 90 | +> It will cause a `RedundantException`. So, you can inherit from `MinkContext` |
| 91 | +> only with one of your context/subcontext classes. |
| 92 | + |
| 93 | +3. Adding `Behat\MinkExtension\Context\MinkContext` as a context in your suite. |
| 94 | + Exactly like the previous option, but gives you the ability to keep your main context |
| 95 | + class clean. |
| 96 | + |
| 97 | + ```yaml |
| 98 | + default: |
| 99 | + suites: |
| 100 | + my_suite: |
| 101 | + contexts: |
| 102 | + - FeatureContext |
| 103 | + - Behat\MinkExtension\Context\MinkContext |
| 104 | + ``` |
| 105 | + |
| 106 | +> [!NOTE] |
| 107 | +> Keep in mind, that you can not have multiple step definitions with the same regex. |
| 108 | +> It will cause a `RedundantException`. So, you can inherit from `MinkContext` |
| 109 | +> only with one of your context/subcontext classes. |
| 110 | + |
| 111 | +4. Implementing `Behat\MinkExtension\Context\MinkAwareContext` with your context. |
| 112 | + |
| 113 | +There are common things between these methods. In each of those, the target context will implement |
| 114 | +`setMink(Mink $mink)` and `setMinkParameters(array $parameters)` methods. Those methods would |
| 115 | +be automatically called *immediately after* each context creation before each scenario. And |
| 116 | +this `$mink` instance will be preconfigured based on the settings you've provided in your |
| 117 | +`behat.yml`. |
| 118 | +
|
| 119 | +## Configuration |
| 120 | +
|
| 121 | +MinkExtension comes with a flexible configuration system, that gives you |
| 122 | +the ability to configure Mink inside Behat to fulfil all your needs. |
| 123 | +
|
| 124 | +### Sessions |
| 125 | +
|
| 126 | +You can register as many Mink sessions as you want. For each session, you |
| 127 | +will need to choose the driver you want to use. |
| 128 | +
|
| 129 | +```yaml |
| 130 | +default: |
| 131 | + extensions: |
| 132 | + Behat\MinkExtension: |
| 133 | + sessions: |
| 134 | + first_session: |
| 135 | + selenium2: ~ |
| 136 | + second_session: |
| 137 | + goutte: ~ |
| 138 | + third_session: |
| 139 | + selenium2: ~ |
| 140 | +``` |
| 141 | +
|
| 142 | +MinkExtension will set the default Mink session for each scenario based on |
| 143 | +the configuration settings `default_session` and `javascript_session` |
| 144 | +and on scenario tags: |
| 145 | +
|
| 146 | +* A scenario tagged with `@mink:foo` will use `foo` as its default session; |
| 147 | +* A scenario tagged with `@javascript` will use the `javascript` session as its default session; |
| 148 | +* Other scenarios will use the default session. |
| 149 | +
|
| 150 | +The default session and the default `javascript` session can also be configured for |
| 151 | +each suite: |
| 152 | +
|
| 153 | +```yaml |
| 154 | +default: |
| 155 | + suites: |
| 156 | + first: |
| 157 | + mink_session: foo |
| 158 | + mink_javascript_session: sahi |
| 159 | +``` |
| 160 | +
|
| 161 | +If it is not configured explicitly, the `javascript` session is set to the first |
| 162 | +session using a javascript driver in the order of the configuration (it would |
| 163 | +be `first_session` in the example above as `selenium2` supports Javascript). |
| 164 | +If it is not configured explicitly, the default session is set to the first |
| 165 | +session using a non-javascript driver if any, or to the first javascript session |
| 166 | +otherwise (it would be `second_session` above as `goutte` does not support |
| 167 | +javascript). |
| 168 | +
|
| 169 | +### Drivers |
| 170 | +
|
| 171 | +First of all, there are drivers enabling configuration. MinkExtension comes |
| 172 | +with support for 7 drivers out of the box: |
| 173 | +
|
| 174 | +* `GoutteDriver` - headless driver without JavaScript support. In order to use |
| 175 | + it, modify your `behat.yml` profile: |
| 176 | +
|
| 177 | + ```yaml |
| 178 | + default: |
| 179 | + extensions: |
| 180 | + Behat\MinkExtension: |
| 181 | + sessions: |
| 182 | + my_session: |
| 183 | + goutte: ~ |
| 184 | + ``` |
| 185 | +
|
| 186 | + **Tips: HTTPS and self-signed certificate** |
| 187 | +
|
| 188 | + If you use Behat/Mink/Goutte to test your application, and want to test an |
| 189 | + application secured with HTTPS, but with a self-signed certificate, you can use |
| 190 | + the following parameters to avoid the validation error triggered by Guzzle: |
| 191 | +
|
| 192 | + * For `Guzzle 4` or later: |
| 193 | +
|
| 194 | + ```yaml |
| 195 | + default: |
| 196 | + extensions: |
| 197 | + Behat\MinkExtension: |
| 198 | + sessions: |
| 199 | + my_session: |
| 200 | + goutte: |
| 201 | + guzzle_parameters: |
| 202 | + verify: false |
| 203 | + ``` |
| 204 | +
|
| 205 | + * For `Guzzle 3` or earlier: |
| 206 | +
|
| 207 | + ```yaml |
| 208 | + default: |
| 209 | + extensions: |
| 210 | + Behat\MinkExtension: |
| 211 | + sessions: |
| 212 | + my_session: |
| 213 | + goutte: |
| 214 | + guzzle_parameters: |
| 215 | + ssl.certificate_authority: false |
| 216 | + ``` |
| 217 | +
|
| 218 | +* `Selenium2Driver` - javascript driver. In order to use it, modify your |
| 219 | + `behat.yml` profile: |
| 220 | +
|
| 221 | + ```yaml |
| 222 | + default: |
| 223 | + extensions: |
| 224 | + Behat\MinkExtension: |
| 225 | + sessions: |
| 226 | + my_session: |
| 227 | + selenium2: ~ |
| 228 | + ``` |
| 229 | +
|
| 230 | +* `SauceLabsDriver` - special flavor of the Selenium2Driver configured to use the |
| 231 | + selenium2 hosted installation of saucelabs.com. In order to use it, modify your |
| 232 | + `behat.yml` profile: |
| 233 | +
|
| 234 | + ```yaml |
| 235 | + default: |
| 236 | + extensions: |
| 237 | + Behat\MinkExtension: |
| 238 | + sessions: |
| 239 | + my_session: |
| 240 | + sauce_labs: ~ |
| 241 | + ``` |
| 242 | +
|
| 243 | +* `BrowserStackDriver` - special flavor of the Selenium2Driver configured to use the |
| 244 | + selenium2 hosted installation of browserstack.com. In order to use it, modify your |
| 245 | + `behat.yml` profile: |
| 246 | +
|
| 247 | + ```yaml |
| 248 | + default: |
| 249 | + extensions: |
| 250 | + Behat\MinkExtension: |
| 251 | + sessions: |
| 252 | + my_session: |
| 253 | + browser_stack: ~ |
| 254 | + ``` |
| 255 | +
|
| 256 | +* `SeleniumDriver` - javascript driver. In order to use it, modify your `behat.yml` |
| 257 | + profile: |
| 258 | +
|
| 259 | + ```yaml |
| 260 | + default: |
| 261 | + extensions: |
| 262 | + Behat\MinkExtension: |
| 263 | + sessions: |
| 264 | + my_session: |
| 265 | + selenium: ~ |
| 266 | + ``` |
| 267 | +
|
| 268 | +* `SahiDriver` - javascript driver. In order to use it, modify your `behat.yml` |
| 269 | + profile: |
| 270 | +
|
| 271 | + ```yaml |
| 272 | + default: |
| 273 | + extensions: |
| 274 | + Behat\MinkExtension: |
| 275 | + sessions: |
| 276 | + my_session: |
| 277 | + sahi: ~ |
| 278 | + ``` |
| 279 | +
|
| 280 | +* `ZombieDriver` - zombie.js javascript headless driver. In order to use it, modify |
| 281 | + your `behat.yml` profile: |
| 282 | +
|
| 283 | + ```yaml |
| 284 | + default: |
| 285 | + extensions: |
| 286 | + Behat\MinkExtension: |
| 287 | + sessions: |
| 288 | + default: |
| 289 | + zombie: |
| 290 | + # Specify the path to the node_modules directory. |
| 291 | + node_modules_path: /usr/local/lib/node_modules/ |
| 292 | + ``` |
| 293 | +
|
| 294 | +> [!NOTE] |
| 295 | +> The phar version of Mink comes bundled with all 5 drivers and you don't need to do |
| 296 | +> anything except enabling them in order to use them. |
| 297 | + |
| 298 | +But if you're using Composer, you need to install drivers that you need first: |
| 299 | +
|
| 300 | +- GoutteDriver - `behat/mink-goutte-driver` |
| 301 | +- SeleniumDriver - `behat/mink-selenium-driver` |
| 302 | +- Selenium2Driver (also used for SauceLabs and BrowserStack) - `behat/mink-selenium2-driver` |
| 303 | +- SahiDriver - `behat/mink-sahi-driver` |
| 304 | +- ZombieDriver - `behat/mink-zombie-driver` |
| 305 | +
|
| 306 | +> [!NOTE] |
| 307 | +> All drivers share the same API, which means that you could use multiple drivers |
| 308 | +> for the same suite - whichever one fits your needs for concrete scenarios. Don't |
| 309 | +> try to stick to a single driver as there's simply no universal solution - every |
| 310 | +> driver has its pros and cons. |
| 311 | +
|
| 312 | +### Additional Parameters |
| 313 | +
|
| 314 | +There's other useful parameters, that you can use to configure your suite: |
| 315 | + |
| 316 | +* `base_url` - if you're using relative paths in your `*.feature` files |
| 317 | + (and you should), then this option will define which url to use as a basename |
| 318 | + for them. |
| 319 | +* `files_path` - there's a special step definition for file upload inputs |
| 320 | + usage. You can use relative paths in those steps. `files_path` defines |
| 321 | + the base path in which Mink should search for those relative files. |
| 322 | +* `show_cmd` - there's a special definition in MinkExtension, that saves |
| 323 | + the currently opened page into a temporary file and opens it with some browser |
| 324 | + utility (for debugging). This option defines the command to be used for opening. |
| 325 | + For example: `show_cmd: 'firefox %s'`. |
| 326 | +* `show_tmp_dir` - the temporary folder used to show the opened page (defaults |
| 327 | + to the system temp dir) |
| 328 | +* `show_auto` - Whether the opened page should be shown automatically when |
| 329 | + a step fails. |
| 330 | +* `browser_name` - meta-option, that defines which browser to use for Sahi, |
| 331 | + Selenium and Selenium2 drivers. |
| 332 | +* `default_session` - defines the default session (driver) to be used for all |
| 333 | + untagged scenarios. This could be any enabled session name. |
| 334 | +* `javascript_session` - defines the javascript session (driver) (the one, which |
| 335 | + will be used for `@javascript` tagged scenarios). This could be any enabled session |
| 336 | + name. |
| 337 | +* `mink_loader` - path to a file loaded to make Mink available (useful when |
| 338 | + using the PHAR archive for Mink, useless when using Composer) |
0 commit comments