Completed
Push — 3.2 ( 917a38 )
by Jonathan
10s
created

DrupalContext::createTerm()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 12
Ratio 100 %

Importance

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