Completed
Pull Request — 3.1 (#290)
by
unknown
09:17
created

MinkContext::assertNotLinkVisible()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 19
Code Lines 9

Duplication

Lines 19
Ratio 100 %

Importance

Changes 0
Metric Value
dl 19
loc 19
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 9
nc 6
nop 1
1
<?php
2
3
namespace Drupal\DrupalExtension\Context;
4
5
use Behat\Behat\Context\TranslatableContext;
6
use Behat\Mink\Exception\UnsupportedDriverActionException;
7
use Behat\MinkExtension\Context\MinkContext as MinkExtension;
8
9
/**
10
 * Extensions to the Mink Extension.
11
 */
12
class MinkContext extends MinkExtension implements TranslatableContext {
13
14
  /**
15
   * Returns list of definition translation resources paths.
16
   *
17
   * @return array
18
   */
19
  public static function getTranslationResources() {
20
    return glob(__DIR__ . '/../../../../i18n/*.xliff');
21
  }
22
23
  /**
24
   * Return a region from the current page.
25
   *
26
   * @throws \Exception
27
   *   If region cannot be found.
28
   *
29
   * @param string $region
30
   *   The machine name of the region to return.
31
   *
32
   * @return \Behat\Mink\Element\NodeElement
33
   */
34 View Code Duplication
  public function getRegion($region) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
35
    $session = $this->getSession();
36
    $regionObj = $session->getPage()->find('region', $region);
37
    if (!$regionObj) {
38
      throw new \Exception(sprintf('No region "%s" found on the page %s.', $region, $session->getCurrentUrl()));
39
    }
40
41
    return $regionObj;
42
  }
43
44
  /**
45
   * Visit a given path, and additionally check for HTTP response code 200.
46
   *
47
   * @Given I am at :path
48
   * @When I visit :path
49
   *
50
   * @throws UnsupportedDriverActionException
51
   */
52
  public function assertAtPath($path) {
53
    $this->getSession()->visit($this->locatePath($path));
54
55
    // If available, add extra validation that this is a 200 response.
56
    try {
57
      $this->getSession()->getStatusCode();
58
      $this->assertHttpResponse('200');
59
    }
60
    catch (UnsupportedDriverActionException $e) {
61
      // Simply continue on, as this driver doesn't support HTTP response codes.
62
    }
63
  }
64
65
  /**
66
   * @When I click :link
67
   */
68
  public function assertClick($link) {
69
    // Use the Mink Extenstion step definition.
70
    $this->clickLink($link);
71
  }
72
73
  /**
74
   * @Given for :field I enter :value
75
   * @Given I enter :value for :field
76
   */
77
  public function assertEnterField($field, $value) {
78
    // Use the Mink Extenstion step definition.
79
    $this->fillField($field, $value);
80
  }
81
82
  /**
83
   * For javascript enabled scenarios, always wait for AJAX before clicking.
84
   *
85
   * @BeforeStep @javascript
86
   */
87
  public function beforeJavascriptStep($event) {
88
    $text = $event->getStep()->getText();
89
    if (preg_match('/(follow|press|click|submit)/i', $text)) {
90
      $this->iWaitForAjaxToFinish();
91
    }
92
  }
93
94
  /**
95
   * For javascript enabled scenarios, always wait for AJAX after clicking.
96
   *
97
   * @AfterStep @javascript
98
   */
99
  public function afterJavascriptStep($event) {
100
    $text = $event->getStep()->getText();
101
    if (preg_match('/(follow|press|click|submit)/i', $text)) {
102
      $this->iWaitForAjaxToFinish();
103
    }
104
  }
105
106
  /**
107
   * Wait for AJAX to finish.
108
   *
109
   * @Given I wait for AJAX to finish
110
   */
111
  public function iWaitForAjaxToFinish() {
112
    $this->getSession()->wait(5000, '(typeof(jQuery)=="undefined" || (0 === jQuery.active && 0 === jQuery(\':animated\').length))');
113
  }
114
115
  /**
116
   * Presses button with specified id|name|title|alt|value.
117
   *
118
   * @When I press the :button button
119
   */
120
  public function pressButton($button) {
121
    // Wait for any open autocomplete boxes to finish closing.  They block
122
    // form-submission if they are still open.
123
    // Use a step 'I press the "Esc" key in the "LABEL" field' to close
124
    // autocomplete suggestion boxes with Mink.  "Click" events on the
125
    // autocomplete suggestion do not work.
126
    try {
127
      $this->getSession()->wait(1000, 'typeof(jQuery)=="undefined" || jQuery("#autocomplete").length === 0');
128
    }
129
    catch (UnsupportedDriverActionException $e) {
130
      // The jQuery probably failed because the driver does not support
131
      // javascript.  That is okay, because if the driver does not support
132
      // javascript, it does not support autocomplete boxes either.
133
    }
134
135
    // Use the Mink Extension step definition.
136
    return parent::pressButton($button);
137
  }
138
139
  /**
140
   * @Given I press the :char key in the :field field
141
   *
142
   * @param mixed $char could be either char ('b') or char-code (98)
143
   * @throws \Exception
144
   */
145
  public function pressKey($char, $field) {
146
    static $keys = array(
147
      'backspace' => 8,
148
      'tab' => 9,
149
      'enter' => 13,
150
      'shift' => 16,
151
      'ctrl' =>  17,
152
      'alt' => 18,
153
      'pause' => 19,
154
      'break' => 19,
155
      'escape' =>  27,
156
      'esc' =>  27,
157
      'end' => 35,
158
      'home' =>  36,
159
      'left' => 37,
160
      'up' => 38,
161
      'right' =>39,
162
      'down' => 40,
163
      'insert' =>  45,
164
      'delete' =>  46,
165
      'pageup' => 33,
166
      'pagedown' => 34,
167
      'capslock' => 20,
168
    );
169
170
    if (is_string($char)) {
171
      if (strlen($char) < 1) {
172
        throw new \Exception('FeatureContext->keyPress($char, $field) was invoked but the $char parameter was empty.');
173
      }
174
      elseif (strlen($char) > 1) {
175
        // Support for all variations, e.g. ESC, Esc, page up, pageup.
176
        $char = $keys[strtolower(str_replace(' ', '', $char))];
177
      }
178
    }
179
180
    $element = $this->getSession()->getPage()->findField($field);
181
    if (!$element) {
182
      throw new \Exception("Field '$field' not found");
183
    }
184
185
    $driver = $this->getSession()->getDriver();
186
    // $driver->keyPress($element->getXpath(), $char);
187
    // This alternative to Driver->keyPress() handles cases that depend on
188
    // javascript which binds to key down/up events directly, such as Drupal's
189
    // autocomplete.js.
190
    $driver->keyDown($element->getXpath(), $char);
191
    $driver->keyUp($element->getXpath(), $char);
192
  }
193
194
  /**
195
   * @Then I should see the link :link
196
   */
197 View Code Duplication
  public function assertLinkVisible($link) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
198
    $element = $this->getSession()->getPage();
199
    $result = $element->findLink($link);
200
201
    try {
202
      if ($result && !$result->isVisible()) {
203
        throw new \Exception(sprintf("No link to '%s' on the page %s", $link, $this->getSession()->getCurrentUrl()));
204
      }
205
    }
206
    catch (UnsupportedDriverActionException $e) {
207
      // We catch the UnsupportedDriverActionException exception in case
208
      // this step is not being performed by a driver that supports javascript.
209
      // All other exceptions are valid.
210
    }
211
212
    if (empty($result)) {
213
      throw new \Exception(sprintf("No link to '%s' on the page %s", $link, $this->getSession()->getCurrentUrl()));
214
    }
215
  }
216
217
  /**
218
   * Links are not loaded on the page.
219
   *
220
   * @Then I should not see the link :link
221
   */
222 View Code Duplication
  public function assertNotLinkVisible($link) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
223
    $element = $this->getSession()->getPage();
224
    $result = $element->findLink($link);
225
226
    try {
227
      if ($result && $result->isVisible()) {
228
        throw new \Exception(sprintf("The link '%s' was present on the page %s and was not supposed to be", $link, $this->getSession()->getCurrentUrl()));
229
      }
230
    }
231
    catch (UnsupportedDriverActionException $e) {
232
      // We catch the UnsupportedDriverActionException exception in case
233
      // this step is not being performed by a driver that supports javascript.
234
      // All other exceptions are valid.
235
    }
236
237
    if ($result) {
238
      throw new \Exception(sprintf("The link '%s' was present on the page %s and was not supposed to be", $link, $this->getSession()->getCurrentUrl()));
239
    }
240
  }
241
242
  /**
243
   * Links are loaded but not visually visible (e.g they have display: hidden applied).
244
   *
245
   * @Then I should not visibly see the link :link
246
   */
247 View Code Duplication
  public function assertNotLinkVisuallyVisible($link) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
248
    $element = $this->getSession()->getPage();
249
    $result = $element->findLink($link);
250
251
    try {
252
      if ($result && $result->isVisible()) {
253
        throw new \Exception(sprintf("The link '%s' was visually visible on the page %s and was not supposed to be", $link, $this->getSession()->getCurrentUrl()));
254
      }
255
    }
256
    catch (UnsupportedDriverActionException $e) {
257
      // We catch the UnsupportedDriverActionException exception in case
258
      // this step is not being performed by a driver that supports javascript.
259
      // All other exceptions are valid.
260
    }
261
262
    if (!$result) {
263
      throw new \Exception(sprintf("The link '%s' was not loaded on the page %s at all", $link, $this->getSession()->getCurrentUrl()));
264
    }
265
266
  }
267
268
  /**
269
   * @Then I (should )see the heading :heading
270
   */
271 View Code Duplication
  public function assertHeading($heading) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
272
    $element = $this->getSession()->getPage();
273
    foreach (array('h1', 'h2', 'h3', 'h4', 'h5', 'h6') as $tag) {
274
      $results = $element->findAll('css', $tag);
275
      foreach ($results as $result) {
276
        if ($result->getText() == $heading) {
277
          return;
278
        }
279
      }
280
    }
281
    throw new \Exception(sprintf("The text '%s' was not found in any heading on the page %s", $heading, $this->getSession()->getCurrentUrl()));
282
  }
283
284
  /**
285
   * @Then I (should )not see the heading :heading
286
   */
287 View Code Duplication
  public function assertNotHeading($heading) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
288
    $element = $this->getSession()->getPage();
289
    foreach (array('h1', 'h2', 'h3', 'h4', 'h5', 'h6') as $tag) {
290
      $results = $element->findAll('css', $tag);
291
      foreach ($results as $result) {
292
        if ($result->getText() == $heading) {
293
          throw new \Exception(sprintf("The text '%s' was found in a heading on the page %s", $heading, $this->getSession()->getCurrentUrl()));
294
        }
295
      }
296
    }
297
  }
298
299
  /**
300
   * @Then I (should ) see the button :button
301
   * @Then I (should ) see the :button button
302
   */
303 View Code Duplication
  public function assertButton($button) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
304
    $element = $this->getSession()->getPage();
305
    $buttonObj = $element->findButton($button);
306
    if (empty($buttonObj)) {
307
      throw new \Exception(sprintf("The button '%s' was not found on the page %s", $button, $this->getSession()->getCurrentUrl()));
308
    }
309
  }
310
311
  /**
312
   * @When I follow/click :link in the :region( region)
313
   *
314
   * @throws \Exception
315
   *   If region or link within it cannot be found.
316
   */
317 View Code Duplication
  public function assertRegionLinkFollow($link, $region) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
318
    $regionObj = $this->getRegion($region);
319
320
    // Find the link within the region
321
    $linkObj = $regionObj->findLink($link);
322
    if (empty($linkObj)) {
323
      throw new \Exception(sprintf('The link "%s" was not found in the region "%s" on the page %s', $link, $region, $this->getSession()->getCurrentUrl()));
324
    }
325
    $linkObj->click();
326
  }
327
328
  /**
329
   * Checks, if a button with id|name|title|alt|value exists or not and pressess the same
330
   *
331
   * @Given I press :button in the :region( region)
332
   *
333
   * @param $button
334
   *   string The id|name|title|alt|value of the button to be pressed
335
   * @param $region
336
   *   string The region in which the button should be pressed
337
   *
338
   * @throws \Exception
339
   *   If region or button within it cannot be found.
340
   */
341 View Code Duplication
  public function assertRegionPressButton($button, $region) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
342
    $regionObj = $this->getRegion($region);
343
344
    $buttonObj = $regionObj->findButton($button);
345
    if (empty($buttonObj)) {
346
      throw new \Exception(sprintf("The button '%s' was not found in the region '%s' on the page %s", $button, $region, $this->getSession()->getCurrentUrl()));
347
    }
348
    $regionObj->pressButton($button);
349
  }
350
351
  /**
352
   * Fills in a form field with id|name|title|alt|value in the specified region.
353
   *
354
   * @Given I fill in :value for :field in the :region( region)
355
   * @Given I fill in :field with :value in the :region( region)
356
   *
357
   * @throws \Exception
358
   *   If region cannot be found.
359
   */
360
  public function regionFillField($field, $value, $region) {
361
    $field = $this->fixStepArgument($field);
362
    $value = $this->fixStepArgument($value);
363
    $regionObj = $this->getRegion($region);
364
    $regionObj->fillField($field, $value);
365
  }
366
367
  /**
368
   * Find a heading in a specific region.
369
   *
370
   * @Then I should see the heading :heading in the :region( region)
371
   * @Then I should see the :heading heading in the :region( region)
372
   *
373
   * @throws \Exception
374
   *   If region or header within it cannot be found.
375
   */
376
  public function assertRegionHeading($heading, $region) {
377
    $regionObj = $this->getRegion($region);
378
379
    foreach (array('h1', 'h2', 'h3', 'h4', 'h5', 'h6') as $tag) {
380
      $elements = $regionObj->findAll('css', $tag);
381
      if (!empty($elements)) {
382
        foreach ($elements as $element) {
383
          if (trim($element->getText()) === $heading) {
384
            return;
385
          }
386
        }
387
      }
388
    }
389
390
    throw new \Exception(sprintf('The heading "%s" was not found in the "%s" region on the page %s', $heading, $region, $this->getSession()->getCurrentUrl()));
391
  }
392
393
  /**
394
   * @Then I should see the link :link in the :region( region)
395
   *
396
   * @throws \Exception
397
   *   If region or link within it cannot be found.
398
   */
399 View Code Duplication
  public function assertLinkRegion($link, $region) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
400
    $regionObj = $this->getRegion($region);
401
402
    $result = $regionObj->findLink($link);
403
    if (empty($result)) {
404
      throw new \Exception(sprintf('No link to "%s" in the "%s" region on the page %s', $link, $region, $this->getSession()->getCurrentUrl()));
405
    }
406
  }
407
408
  /**
409
   * @Then I should not see the link :link in the :region( region)
410
   *
411
   * @throws \Exception
412
   *   If region or link within it cannot be found.
413
   */
414 View Code Duplication
  public function assertNotLinkRegion($link, $region) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
415
    $regionObj = $this->getRegion($region);
416
417
    $result = $regionObj->findLink($link);
418
    if (!empty($result)) {
419
      throw new \Exception(sprintf('Link to "%s" in the "%s" region on the page %s', $link, $region, $this->getSession()->getCurrentUrl()));
420
    }
421
  }
422
423
  /**
424
   * @Then I should see( the text) :text in the :region( region)
425
   *
426
   * @throws \Exception
427
   *   If region or text within it cannot be found.
428
   */
429 View Code Duplication
  public function assertRegionText($text, $region) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
430
    $regionObj = $this->getRegion($region);
431
432
    // Find the text within the region
433
    $regionText = $regionObj->getText();
434
    if (strpos($regionText, $text) === FALSE) {
435
      throw new \Exception(sprintf("The text '%s' was not found in the region '%s' on the page %s", $text, $region, $this->getSession()->getCurrentUrl()));
436
    }
437
  }
438
439
  /**
440
   * @Then I should not see( the text) :text in the :region( region)
441
   *
442
   * @throws \Exception
443
   *   If region or text within it cannot be found.
444
   */
445 View Code Duplication
  public function assertNotRegionText($text, $region) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
446
    $regionObj = $this->getRegion($region);
447
448
    // Find the text within the region.
449
    $regionText = $regionObj->getText();
450
    if (strpos($regionText, $text) !== FALSE) {
451
      throw new \Exception(sprintf('The text "%s" was found in the region "%s" on the page %s', $text, $region, $this->getSession()->getCurrentUrl()));
452
    }
453
  }
454
455
  /**
456
   * @Then I (should )see the text :text
457
   */
458
  public function assertTextVisible($text) {
459
    // Use the Mink Extension step definition.
460
    $this->assertPageContainsText($text);
461
  }
462
463
  /**
464
   * @Then I should not see the text :text
465
   */
466
  public function assertNotTextVisible($text) {
467
    // Use the Mink Extension step definition.
468
    $this->assertPageNotContainsText($text);
469
  }
470
471
  /**
472
   * @Then I should get a :code HTTP response
473
   */
474
  public function assertHttpResponse($code) {
475
    // Use the Mink Extension step definition.
476
    $this->assertResponseStatus($code);
477
  }
478
479
  /**
480
   * @Then I should not get a :code HTTP response
481
   */
482
  public function assertNotHttpResponse($code) {
483
    // Use the Mink Extension step definition.
484
    $this->assertResponseStatusIsNot($code);
485
  }
486
487
  /**
488
   * @Given I check the box :checkbox
489
   */
490
  public function assertCheckBox($checkbox) {
491
    // Use the Mink Extension step definition.
492
    $this->checkOption($checkbox);
493
  }
494
495
  /**
496
   * @Given I uncheck the box :checkbox
497
   */
498
  public function assertUncheckBox($checkbox) {
499
    // Use the Mink Extension step definition.
500
    $this->uncheckOption($checkbox);
501
  }
502
503
  /**
504
   * @When I select the radio button :label with the id :id
505
   * @When I select the radio button :label
506
   *
507
   * @TODO convert to mink extension.
508
   */
509
  public function assertSelectRadioById($label, $id = '') {
510
    $element = $this->getSession()->getPage();
511
    $radiobutton = $id ? $element->findById($id) : $element->find('named', array('radio', $this->getSession()->getSelectorsHandler()->xpathLiteral($label)));
0 ignored issues
show
Deprecated Code introduced by
The method Behat\Mink\Selector\Sele...Handler::xpathLiteral() has been deprecated with message: since Mink 1.7. Use \Behat\Mink\Selector\Xpath\Escaper::escapeLiteral when building Xpath or pass the unescaped value when using the named selector.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
512
    if ($radiobutton === NULL) {
513
      throw new \Exception(sprintf('The radio button with "%s" was not found on the page %s', $id ? $id : $label, $this->getSession()->getCurrentUrl()));
514
    }
515
    $value = $radiobutton->getAttribute('value');
516
    $labelonpage = $radiobutton->getParent()->getText();
517
    if ($label != $labelonpage) {
518
      throw new \Exception(sprintf("Button with id '%s' has label '%s' instead of '%s' on the page %s", $id, $labelonpage, $label, $this->getSession()->getCurrentUrl()));
519
    }
520
    $radiobutton->selectOption($value, FALSE);
521
  }
522
523
  /**
524
   * @} End of defgroup "mink extensions"
525
   */
526
527
528
}
529