3 namespace Drupal\DrupalExtension\Context;
5 use Behat\Behat\Context\TranslatableContext;
6 use Behat\Mink\Element\Element;
8 use Behat\Gherkin\Node\TableNode;
11 * Provides pre-built step definitions for interacting with Drupal.
13 class DrupalContext extends RawDrupalContext implements TranslatableContext {
16 * Returns list of definition translation resources paths.
20 public static function getTranslationResources() {
21 return glob(__DIR__ . '/../../../../i18n/*.xliff');
25 * @Given I am an anonymous user
26 * @Given I am not logged in
28 public function assertAnonymousUser() {
29 // Verify the user is logged out.
30 if ($this->loggedIn()) {
36 * Creates and authenticates a user with the given role(s).
38 * @Given I am logged in as a user with the :role role(s)
39 * @Given I am logged in as a/an :role
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),
50 $user->mail = "{$user->name}@example.com";
52 $this->userCreate($user);
54 $roles = explode(',', $role);
55 $roles = array_map('trim', $roles);
56 foreach ($roles as $role) {
57 if (!in_array(strtolower($role), array('authenticated', 'authenticated user'))) {
58 // Only add roles other than 'authenticated user'.
59 $this->getDriver()->userAddRole($user, $role);
69 * Creates and authenticates a user with the given role(s) and given fields.
70 * | field_user_name | John |
71 * | field_user_surname | Smith |
74 * @Given I am logged in as a user with the :role role(s) and I have the following fields:
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),
85 $user->mail = "{$user->name}@example.com";
87 // Assign fields to user before creation.
88 foreach ($fields->getRowsHash() as $field => $value) {
89 $user->{$field} = $value;
92 $this->userCreate($user);
94 $roles = explode(',', $role);
95 $roles = array_map('trim', $roles);
96 foreach ($roles as $role) {
97 if (!in_array(strtolower($role), array('authenticated', 'authenticated user'))) {
98 // Only add roles other than 'authenticated user'.
99 $this->getDriver()->userAddRole($user, $role);
110 * @Given I am logged in as :name
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));
117 // Change internal current user.
118 $this->user = $this->users[$name];
125 * @Given I am logged in as a user with the :permissions permission(s)
127 public function assertLoggedInWithPermissions($permissions) {
129 $user = (object) array(
130 'name' => $this->getRandom()->name(8),
131 'pass' => $this->getRandom()->name(16),
133 $user->mail = "{$user->name}@example.com";
134 $this->userCreate($user);
136 // Create and assign a temporary role with given permissions.
137 $permissions = array_map('trim', explode(',', $permissions));
138 $rid = $this->getDriver()->roleCreate($permissions);
139 $this->getDriver()->userAddRole($user, $rid);
140 $this->roles[] = $rid;
147 * Retrieve a table row containing specified text from a given element.
149 * @param \Behat\Mink\Element\Element
151 * The text to search for in the table row.
153 * @return \Behat\Mink\Element\NodeElement
157 public function getTableRow(Element $element, $search) {
158 $rows = $element->findAll('css', 'tr');
160 throw new \Exception(sprintf('No rows found on the page %s', $this->getSession()->getCurrentUrl()));
162 foreach ($rows as $row) {
163 if (strpos($row->getText(), $search) !== FALSE) {
167 throw new \Exception(sprintf('Failed to find a row containing "%s" on the page %s', $search, $this->getSession()->getCurrentUrl()));
171 * Find text in a table row containing given text.
173 * @Then I should see (the text ):text in the :rowText row
175 public function assertTextInTableRow($text, $rowText) {
176 $row = $this->getTableRow($this->getSession()->getPage(), $rowText);
177 if (strpos($row->getText(), $text) === FALSE) {
178 throw new \Exception(sprintf('Found a row containing "%s", but it did not contain the text "%s".', $rowText, $text));
183 * Asset text not in a table row containing given text.
185 * @Then I should not see (the text ):text in the :rowText row
187 public function assertTextNotInTableRow($text, $rowText) {
188 $row = $this->getTableRow($this->getSession()->getPage(), $rowText);
189 if (strpos($row->getText(), $text) !== FALSE) {
190 throw new \Exception(sprintf('Found a row containing "%s", but it contained the text "%s".', $rowText, $text));
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`.
199 * @Given I click :link in the :rowText row
200 * @Then I (should )see the :link in the :rowText row
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();
209 throw new \Exception(sprintf('Found a row containing "%s", but no "%s" link on the page %s', $rowText, $link, $this->getSession()->getCurrentUrl()));
213 * @Given the cache has been cleared
215 public function assertCacheClear() {
216 $this->getDriver()->clearCache();
222 public function assertCron() {
223 $this->getDriver()->runCron();
227 * Creates content of the given type.
229 * @Given I am viewing a/an :type (content )with the title :title
230 * @Given a/an :type (content )with the title :title
232 public function createNode($type, $title) {
233 // @todo make this easily extensible.
234 $node = (object) array(
238 $saved = $this->nodeCreate($node);
239 // Set internal page on the new node.
240 $this->getSession()->visit($this->locatePath('/node/' . $saved->nid));
244 * Creates content authored by the current user.
246 * @Given I am viewing my :type (content )with the title :title
248 public function createMyNode($type, $title) {
249 if (!isset($this->user->uid)) {
250 throw new \Exception(sprintf('There is no current logged in user to create a node for.'));
253 $node = (object) array(
256 'body' => $this->getRandom()->name(255),
257 'uid' => $this->user->uid,
259 $saved = $this->nodeCreate($node);
261 // Set internal page on the new node.
262 $this->getSession()->visit($this->locatePath('/node/' . $saved->nid));
266 * Creates content of a given type provided in the form:
267 * | title | author | status | created |
268 * | My title | Joe Editor | 1 | 2014-10-17 8:00am |
269 * | ... | ... | ... | ... |
271 * @Given :type content:
273 public function createNodes($type, TableNode $nodesTable) {
274 foreach ($nodesTable->getHash() as $nodeHash) {
275 $node = (object) $nodeHash;
277 $this->nodeCreate($node);
282 * Creates content of the given type, provided in the form:
283 * | title | My node |
284 * | Field One | My field value |
285 * | author | Joe Editor |
289 * @Given I am viewing a/an :type( content):
291 public function assertViewingNode($type, TableNode $fields) {
292 $node = (object) array(
295 foreach ($fields->getRowsHash() as $field => $value) {
296 $node->{$field} = $value;
299 $saved = $this->nodeCreate($node);
301 // Set internal browser on the node.
302 $this->getSession()->visit($this->locatePath('/node/' . $saved->nid));
306 * Asserts that a given content type is editable.
308 * @Then I should be able to edit a/an :type( content)
310 public function assertEditNodeOfType($type) {
311 $node = (object) array(
313 'title' => "Test $type",
315 $saved = $this->nodeCreate($node);
317 // Set internal browser on the node edit page.
318 $this->getSession()->visit($this->locatePath('/node/' . $saved->nid . '/edit'));
321 $this->assertSession()->statusCodeEquals('200');
326 * Creates a term on an existing vocabulary.
328 * @Given I am viewing a/an :vocabulary term with the name :name
329 * @Given a/an :vocabulary term with the name :name
331 public function createTerm($vocabulary, $name) {
332 // @todo make this easily extensible.
333 $term = (object) array(
335 'vocabulary_machine_name' => $vocabulary,
336 'description' => $this->getRandom()->name(255),
338 $saved = $this->termCreate($term);
340 // Set internal page on the term.
341 $this->getSession()->visit($this->locatePath('/taxonomy/term/' . $saved->tid));
345 * Creates multiple users.
347 * Provide user data in the following format:
349 * | name | mail | roles |
350 * | user foo | foo@bar.com | role1, role2 |
354 public function createUsers(TableNode $usersTable) {
355 foreach ($usersTable->getHash() as $userHash) {
357 // Split out roles to process after user is created.
359 if (isset($userHash['roles'])) {
360 $roles = explode(',', $userHash['roles']);
361 $roles = array_filter(array_map('trim', $roles));
362 unset($userHash['roles']);
365 $user = (object) $userHash;
367 if (!isset($user->pass)) {
368 $user->pass = $this->getRandom()->name();
370 $this->userCreate($user);
373 foreach ($roles as $role) {
374 $this->getDriver()->userAddRole($user, $role);
380 * Creates one or more terms on an existing vocabulary.
382 * Provide term data in the following format:
384 * | name | parent | description | weight | taxonomy_field_image |
385 * | Snook | Fish | Marine fish | 10 | snook-123.jpg |
386 * | ... | ... | ... | ... | ... |
388 * Only the 'name' field is required.
390 * @Given :vocabulary terms:
392 public function createTerms($vocabulary, TableNode $termsTable) {
393 foreach ($termsTable->getHash() as $termsHash) {
394 $term = (object) $termsHash;
395 $term->vocabulary_machine_name = $vocabulary;
396 $this->termCreate($term);
401 * Creates one or more languages.
403 * @Given the/these (following )languages are available:
405 * Provide language data in the following format:
411 * @param TableNode $langcodesTable
412 * The table listing languages by their ISO code.
414 public function createLanguages(TableNode $langcodesTable) {
415 foreach ($langcodesTable->getHash() as $row) {
416 $language = (object) array(
417 'langcode' => $row['languages'],
419 $this->languageCreate($language);
424 * Pauses the scenario until the user presses a key. Useful when debugging a scenario.
428 public function iPutABreakpoint()
430 fwrite(STDOUT, "\033[s \033[93m[Breakpoint] Press \033[1;93m[RETURN]\033[0;93m to continue, or 'q' to quit...\033[0m");
432 $line = trim(fgets(STDIN, 1024));
433 //Note: this assumes ASCII encoding. Should probably be revamped to
434 //handle other character sets.
435 $charCode = ord($line);
445 throw new \Exception("Exiting test intentionally.");
447 fwrite(STDOUT, sprintf("\nInvalid entry '%s'. Please enter 'y', 'q', or the enter key.\n", $line));
451 fwrite(STDOUT, "\033[u");