Completed
Push — Leksat-patch-1 ( 31c1c0...66f278 )
by Jonathan
01:23
created

DrupalContext::iPutABreakpoint()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 18
nc 6
nop 0
1
<?php
2
3
namespace Drupal\DrupalExtension\Context;
4
5
use Behat\Behat\Context\TranslatableContext;
6
use Behat\Mink\Element\Element;
7
8
use Behat\Gherkin\Node\TableNode;
9
10
/**
11
 * Provides pre-built step definitions for interacting with Drupal.
12
 */
13
class DrupalContext extends RawDrupalContext implements TranslatableContext {
14
15
  /**
16
   * Returns list of definition translation resources paths.
17
   *
18
   * @return array
19
   */
20
  public static function getTranslationResources() {
21
    return glob(__DIR__ . '/../../../../i18n/*.xliff');
22
  }
23
24
  /**
25
   * @Given I am an anonymous user
26
   * @Given I am not logged in
27
   */
28
  public function assertAnonymousUser() {
29
    // Verify the user is logged out.
30
    if ($this->loggedIn()) {
31
      $this->logout();
32
    }
33
  }
34
35
  /**
36
   * Creates and authenticates a user with the given role(s).
37
   *
38
   * @Given I am logged in as a user with the :role role(s)
39
   * @Given I am logged in as a/an :role
40
   */
41
  public function assertAuthenticatedByRole($role) {
42
    // Check if a user with this role is already logged in.
43
    if (!$this->loggedInWithRole($role)) {
44
      // Create user (and project)
45
      $user = (object) array(
46
        'name' => $this->getRandom()->name(8),
47
        'pass' => $this->getRandom()->name(16),
48
        'role' => $role,
49
      );
50
      $user->mail = "{$user->name}@example.com";
51
52
      $this->userCreate($user);
53
54
      $roles = explode(',', $role);
55
      $roles = array_map('trim', $roles);
56 View Code Duplication
      foreach ($roles as $role) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
57
        if (!in_array(strtolower($role), array('authenticated', 'authenticated user'))) {
58
          // Only add roles other than 'authenticated user'.
59
          $this->getDriver()->userAddRole($user, $role);
60
        }
61
      }
62
63
      // Login.
64
      $this->login($user);
65
    }
66
  }
67
68
  /**
69
   * Creates and authenticates a user with the given role(s) and given fields.
70
   * | field_user_name     | John  |
71
   * | field_user_surname  | Smith |
72
   * | ...                 | ...   |
73
   *
74
   * @Given I am logged in as a user with the :role role(s) and I have the following fields:
75
   */
76
  public function assertAuthenticatedByRoleWithGivenFields($role, TableNode $fields) {
77
    // Check if a user with this role is already logged in.
78
    if (!$this->loggedInWithRole($role)) {
79
      // Create user (and project)
80
      $user = (object) array(
81
        'name' => $this->getRandom()->name(8),
82
        'pass' => $this->getRandom()->name(16),
83
        'role' => $role,
84
      );
85
      $user->mail = "{$user->name}@example.com";
86
87
      // Assign fields to user before creation.
88
      foreach ($fields->getRowsHash() as $field => $value) {
89
        $user->{$field} = $value;
90
      }
91
92
      $this->userCreate($user);
93
94
      $roles = explode(',', $role);
95
      $roles = array_map('trim', $roles);
96 View Code Duplication
      foreach ($roles as $role) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
97
        if (!in_array(strtolower($role), array('authenticated', 'authenticated user'))) {
98
          // Only add roles other than 'authenticated user'.
99
          $this->getDriver()->userAddRole($user, $role);
100
        }
101
      }
102
103
      // Login.
104
      $this->login($user);
105
    }
106
  }
107
108
109
  /**
110
   * @Given I am logged in as :name
111
   */
112
  public function assertLoggedInByName($name) {
113
    $manager = $this->getUserManager();
114
115
    // Change internal current user.
116
    $manager->setCurrentUser($manager->getUser($name));
117
118
    // Login.
119
    $this->login($manager->getUser($name));
120
  }
121
122
  /**
123
   * @Given I am logged in as a user with the :permissions permission(s)
124
   */
125
  public function assertLoggedInWithPermissions($permissions) {
126
    // Create user.
127
    $user = (object) array(
128
      'name' => $this->getRandom()->name(8),
129
      'pass' => $this->getRandom()->name(16),
130
    );
131
    $user->mail = "{$user->name}@example.com";
132
    $this->userCreate($user);
133
134
    // Create and assign a temporary role with given permissions.
135
    $permissions = array_map('trim', explode(',', $permissions));
136
    $rid = $this->getDriver()->roleCreate($permissions);
137
    $this->getDriver()->userAddRole($user, $rid);
138
    $this->roles[] = $rid;
139
140
    // Login.
141
    $this->login($user);
142
  }
143
144
  /**
145
   * Retrieve a table row containing specified text from a given element.
146
   *
147
   * @param \Behat\Mink\Element\Element
148
   * @param string
149
   *   The text to search for in the table row.
150
   *
151
   * @return \Behat\Mink\Element\NodeElement
152
   *
153
   * @throws \Exception
154
   */
155
  public function getTableRow(Element $element, $search) {
156
    $rows = $element->findAll('css', 'tr');
157
    if (empty($rows)) {
158
      throw new \Exception(sprintf('No rows found on the page %s', $this->getSession()->getCurrentUrl()));
159
    }
160
    foreach ($rows as $row) {
161
      if (strpos($row->getText(), $search) !== FALSE) {
162
        return $row;
163
      }
164
    }
165
    throw new \Exception(sprintf('Failed to find a row containing "%s" on the page %s', $search, $this->getSession()->getCurrentUrl()));
166
  }
167
168
  /**
169
   * Find text in a table row containing given text.
170
   *
171
   * @Then I should see (the text ):text in the :rowText row
172
   */
173
  public function assertTextInTableRow($text, $rowText) {
174
    $row = $this->getTableRow($this->getSession()->getPage(), $rowText);
175 View Code Duplication
    if (strpos($row->getText(), $text) === FALSE) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
176
      throw new \Exception(sprintf('Found a row containing "%s", but it did not contain the text "%s".', $rowText, $text));
177
    }
178
  }
179
180
  /**
181
   * Asset text not in a table row containing given text.
182
   *
183
   * @Then I should not see (the text ):text in the :rowText row
184
   */
185
  public function assertTextNotInTableRow($text, $rowText) {
186
    $row = $this->getTableRow($this->getSession()->getPage(), $rowText);
187 View Code Duplication
    if (strpos($row->getText(), $text) !== FALSE) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
188
      throw new \Exception(sprintf('Found a row containing "%s", but it contained the text "%s".', $rowText, $text));
189
    }
190
  }
191
192
  /**
193
   * Attempts to find a link in a table row containing giving text. This is for
194
   * administrative pages such as the administer content types screen found at
195
   * `admin/structure/types`.
196
   *
197
   * @Given I click :link in the :rowText row
198
   * @Then I (should )see the :link in the :rowText row
199
   */
200
  public function assertClickInTableRow($link, $rowText) {
201
    $page = $this->getSession()->getPage();
202
    if ($link_element = $this->getTableRow($page, $rowText)->findLink($link)) {
203
      // Click the link and return.
204
      $link_element->click();
205
      return;
206
    }
207
    throw new \Exception(sprintf('Found a row containing "%s", but no "%s" link on the page %s', $rowText, $link, $this->getSession()->getCurrentUrl()));
208
  }
209
210
  /**
211
   * @Given the cache has been cleared
212
   */
213
  public function assertCacheClear() {
214
    $this->getDriver()->clearCache();
215
  }
216
217
  /**
218
   * @Given I run cron
219
   */
220
  public function assertCron() {
221
    $this->getDriver()->runCron();
222
  }
223
224
  /**
225
   * Creates content of the given type.
226
   *
227
   * @Given I am viewing a/an :type (content )with the title :title
228
   * @Given a/an :type (content )with the title :title
229
   */
230
  public function createNode($type, $title) {
231
    // @todo make this easily extensible.
232
    $node = (object) array(
233
      'title' => $title,
234
      'type' => $type,
235
    );
236
    $saved = $this->nodeCreate($node);
237
    // Set internal page on the new node.
238
    $this->getSession()->visit($this->locatePath('/node/' . $saved->nid));
239
  }
240
241
  /**
242
   * Creates content authored by the current user.
243
   *
244
   * @Given I am viewing my :type (content )with the title :title
245
   */
246
  public function createMyNode($type, $title) {
247
    if ($this->getUserManager()->currentUserIsAnonymous()) {
248
      throw new \Exception(sprintf('There is no current logged in user to create a node for.'));
249
    }
250
251
    $node = (object) array(
252
      'title' => $title,
253
      'type' => $type,
254
      'body' => $this->getRandom()->name(255),
255
      'uid' => $this->getUserManager()->getCurrentUser()->uid,
256
    );
257
    $saved = $this->nodeCreate($node);
258
259
    // Set internal page on the new node.
260
    $this->getSession()->visit($this->locatePath('/node/' . $saved->nid));
261
  }
262
263
  /**
264
   * Creates content of a given type provided in the form:
265
   * | title    | author     | status | created           |
266
   * | My title | Joe Editor | 1      | 2014-10-17 8:00am |
267
   * | ...      | ...        | ...    | ...               |
268
   *
269
   * @Given :type content:
270
   */
271
  public function createNodes($type, TableNode $nodesTable) {
272
    foreach ($nodesTable->getHash() as $nodeHash) {
273
      $node = (object) $nodeHash;
274
      $node->type = $type;
275
      $this->nodeCreate($node);
276
    }
277
  }
278
279
  /**
280
   * Creates content of the given type, provided in the form:
281
   * | title     | My node        |
282
   * | Field One | My field value |
283
   * | author    | Joe Editor     |
284
   * | status    | 1              |
285
   * | ...       | ...            |
286
   *
287
   * @Given I am viewing a/an :type( content):
288
   */
289
  public function assertViewingNode($type, TableNode $fields) {
290
    $node = (object) array(
291
      'type' => $type,
292
    );
293
    foreach ($fields->getRowsHash() as $field => $value) {
294
      $node->{$field} = $value;
295
    }
296
297
    $saved = $this->nodeCreate($node);
298
299
    // Set internal browser on the node.
300
    $this->getSession()->visit($this->locatePath('/node/' . $saved->nid));
301
  }
302
303
  /**
304
   * Asserts that a given content type is editable.
305
   *
306
   * @Then I should be able to edit a/an :type( content)
307
   */
308
  public function assertEditNodeOfType($type) {
309
    $node = (object) array(
310
      'type' => $type,
311
      'title' => "Test $type",
312
    );
313
    $saved = $this->nodeCreate($node);
314
315
    // Set internal browser on the node edit page.
316
    $this->getSession()->visit($this->locatePath('/node/' . $saved->nid . '/edit'));
317
318
    // Test status.
319
    $this->assertSession()->statusCodeEquals('200');
320
  }
321
322
323
  /**
324
   * Creates a term on an existing vocabulary.
325
   *
326
   * @Given I am viewing a/an :vocabulary term with the name :name
327
   * @Given a/an :vocabulary term with the name :name
328
   */
329
  public function createTerm($vocabulary, $name) {
330
    // @todo make this easily extensible.
331
    $term = (object) array(
332
      'name' => $name,
333
      'vocabulary_machine_name' => $vocabulary,
334
      'description' => $this->getRandom()->name(255),
335
    );
336
    $saved = $this->termCreate($term);
337
338
    // Set internal page on the term.
339
    $this->getSession()->visit($this->locatePath('/taxonomy/term/' . $saved->tid));
340
  }
341
342
  /**
343
   * Creates multiple users.
344
   *
345
   * Provide user data in the following format:
346
   *
347
   * | name     | mail         | roles        |
348
   * | user foo | [email protected]  | role1, role2 |
349
   *
350
   * @Given users:
351
   */
352
  public function createUsers(TableNode $usersTable) {
353
    foreach ($usersTable->getHash() as $userHash) {
354
355
      // Split out roles to process after user is created.
356
      $roles = array();
357
      if (isset($userHash['roles'])) {
358
        $roles = explode(',', $userHash['roles']);
359
        $roles = array_filter(array_map('trim', $roles));
360
        unset($userHash['roles']);
361
      }
362
363
      $user = (object) $userHash;
364
      // Set a password.
365
      if (!isset($user->pass)) {
366
        $user->pass = $this->getRandom()->name();
367
      }
368
      $this->userCreate($user);
369
370
      // Assign roles.
371
      foreach ($roles as $role) {
372
        $this->getDriver()->userAddRole($user, $role);
373
      }
374
    }
375
  }
376
377
  /**
378
   * Creates one or more terms on an existing vocabulary.
379
   *
380
   * Provide term data in the following format:
381
   *
382
   * | name  | parent | description | weight | taxonomy_field_image |
383
   * | Snook | Fish   | Marine fish | 10     | snook-123.jpg        |
384
   * | ...   | ...    | ...         | ...    | ...                  |
385
   *
386
   * Only the 'name' field is required.
387
   *
388
   * @Given :vocabulary terms:
389
   */
390
  public function createTerms($vocabulary, TableNode $termsTable) {
391
    foreach ($termsTable->getHash() as $termsHash) {
392
      $term = (object) $termsHash;
393
      $term->vocabulary_machine_name = $vocabulary;
394
      $this->termCreate($term);
395
    }
396
  }
397
398
  /**
399
   * Creates one or more languages.
400
   *
401
   * @Given the/these (following )languages are available:
402
   *
403
   * Provide language data in the following format:
404
   *
405
   * | langcode |
406
   * | en       |
407
   * | fr       |
408
   *
409
   * @param TableNode $langcodesTable
410
   *   The table listing languages by their ISO code.
411
   */
412
  public function createLanguages(TableNode $langcodesTable) {
413
    foreach ($langcodesTable->getHash() as $row) {
414
      $language = (object) array(
415
        'langcode' => $row['languages'],
416
      );
417
      $this->languageCreate($language);
418
    }
419
  }
420
421
  /**
422
   * Pauses the scenario until the user presses a key. Useful when debugging a scenario.
423
   *
424
   * @Then (I )break
425
   */
426
    public function iPutABreakpoint()
427
    {
428
      fwrite(STDOUT, "\033[s \033[93m[Breakpoint] Press \033[1;93m[RETURN]\033[0;93m to continue, or 'q' to quit...\033[0m");
429
      do {
430
        $line = trim(fgets(STDIN, 1024));
431
        //Note: this assumes ASCII encoding.  Should probably be revamped to
432
        //handle other character sets.
433
        $charCode = ord($line);
434
        switch($charCode){
435
          case 0: //CR
436
          case 121: //y
437
          case 89: //Y
438
            break 2;
439
          // case 78: //N
440
          // case 110: //n
441
          case 113: //q
442
          case 81: //Q
443
            throw new \Exception("Exiting test intentionally.");
444
          default:
445
            fwrite(STDOUT, sprintf("\nInvalid entry '%s'.  Please enter 'y', 'q', or the enter key.\n", $line));
446
          break;
447
        }
448
      } while (true);
449
      fwrite(STDOUT, "\033[u");
450
    }
451
452
}
453