Skip to content

Commit

Permalink
Added Message context
Browse files Browse the repository at this point in the history
  • Loading branch information
BR0kEN- committed Feb 10, 2016
1 parent 7cc79d0 commit 664609b
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 47 deletions.
30 changes: 26 additions & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,6 @@ Then I select the following in "Categories" hierarchical select:
Then should see the thumbnail
```

```gherkin
And should see no errors
```

```gherkin
And pick "Kiyv" from "City"
```
Expand Down Expand Up @@ -301,3 +297,29 @@ Then I should not see "vulnerability" in "Presentation" WYSIWYG editor
Then I fill in following WYSIWYG editors
| Editor locator | Value |
```

### [MessageContext](examples/MESSAGES.md)

```gherkin
And (I )should see no errors( on the page)
```

```gherkin
# The <TYPE> could be ommited or one of the following:
# - error
# - warning
# - success
And (I )should( not) see the (<TYPE> )message "An error occured."
```

```gherkin
# Similar to previous, but with placeholders replacing.
And (I )should( not) see the (<TYPE> )message "!name field is required."
| !name | E-mail address |
```

```gherkin
# Similar to previous, but placeholder should be formatted in another way.
And (I )should( not) see the following (<TYPE> )messages:
| !name field is required. | !name => E-mail address |
```
30 changes: 30 additions & 0 deletions docs/examples/MESSAGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Find messages on the page

Every message could be on English language. In this case they will be processed by `t()` function and translated. If some complex strings required then placeholders could be used.

```gherkin
Then should see the error message "!name field is required."
| !name | E-mail address |
```

or this can be easily replaced by message, for example, on German language:

```gherkin
Then Then should see the error message "Das Feld „E-Mail-Adresse” ist erforderlich."
```

Multiple messages also could be handled:

```gherkin
Then should see the following error messages:
| !name field is required. | !name => E-mail address |
| !name field is required. | !name => Site name |
```

## Other examples

```gherkin
And should not see the success message "The configuration options have been saved."
# Uncomment the next line and comment previous to use only German locale:
# And should not see the success message "Die Konfigurationsoptionen wurden gespeichert."
```
43 changes: 0 additions & 43 deletions src/Context/Form/FormContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -345,49 +345,6 @@ public function shouldSeeThumbnail()
}
}

/**
* Check that the page have no error messages and fields - error classes.
*
* @throws \InvalidArgumentException
* @throws \RuntimeException
* @throws \Exception
*
* @Then /^(?:|I )should see no errors$/
*/
public function shouldSeeNoErrors()
{
$selector = $this->getDrupalSelector('error_message_selector');

if (empty($selector)) {
throw new \InvalidArgumentException('The "error_message_selector" in behat.yml is not configured.');
}

$session = $this->getSession();
$page = $session->getPage();
$errors = $page->find('css', $selector);

// Some modules are inserted an empty container for errors before
// they are arise. The "Clientside Validation" - one of them.
if (null !== $errors) {
$text = $errors->getText();

if (!empty($text)) {
throw new \RuntimeException(sprintf(
'The page "%s" contains following error messages: "%s"',
$session->getCurrentUrl(),
$text
));
}
}

/** @var NodeElement $formElement */
foreach ($page->findAll('css', 'input, select, textarea') as $formElement) {
if ($formElement->hasClass('error')) {
throw new \Exception(sprintf('Element "#%s" has an error class.', $formElement->getAttribute('id')));
}
}
}

/**
* @param string $option
* @param string $selector
Expand Down
130 changes: 130 additions & 0 deletions src/Context/Message/MessageContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php
/**
* @author Sergii Bondarenko, <sb@firstvector.org>
*/
namespace Drupal\TqExtension\Context\Message;

// Helpers.
use Behat\Gherkin\Node\TableNode;
use Behat\Mink\Element\NodeElement;

class MessageContext extends RawMessageContext
{
/**
* Check that the page have no error messages and fields - error classes.
*
* @throws \RuntimeException
* @throws \Exception
*
* @Then /^(?:|I )should see no errors(?:| on the page)$/
*/
public function assertNoErrorMessages()
{
foreach ($this->getMessagesContainers('error') as $element) {
// Some modules are inserted an empty container for errors before
// they are arise. The "Clientside Validation" - one of them.
$text = trim($element->getText());

if ('' !== $text) {
throw new \RuntimeException(sprintf(
'The page "%s" contains following error messages: "%s".',
self::$pageUrl,
$text
));
}
}

/** @var NodeElement $formElement */
foreach ($this->getSession()->getPage()->findAll('css', 'input, select, textarea') as $formElement) {
if ($formElement->hasClass('error')) {
throw new \Exception(sprintf(
'Element "#%s" has an error class.',
$formElement->getAttribute('id')
));
}
}
}

/**
* @example
* I should see the message "Hello, user."
* I should see the error message "An error occured."
* I should not see the success message "Everything fine."
* I should not see the error message "!name field is required."
* | !name | E-mail address |
*
* @param string $negate
* Indicates that user should or should not see message on the page.
* @param string $type
* Message type: error, warning, success. Could be empty.
* @param string $message
* Message to found. Placeholders allowed.
* @param TableNode|array $args
* Placeholders conformity.
*
* @Then /^(?:|I )should(| not) see the (.* )message "([^"]*)"$/
*/
public function assertMessage($negate, $type, $message, $args = [])
{
$type = trim($type);
$negate = (bool) $negate;
$elements = $this->getMessagesContainers($type);

if (empty($elements) && !$negate) {
throw new \UnexpectedValueException(sprintf("No $type messages on the page (%s).", self::$pageUrl));
}

if ($args instanceof TableNode) {
$args = $args->getRowsHash();
}

$translated = t($message, $args);
$this->debug(['Input: %s', 'Translated: %s'], $message, $translated);

/** @var NodeElement $element */
foreach ($elements as $element) {
$text = trim($element->getText());
$result = strpos($text, $message) !== false || strpos($text, $translated) !== false;

if ($negate ? $result : !$result) {
throw new \RuntimeException(sprintf(
"The $type message %s found on the page (%s).",
$negate ? 'not' : '',
self::$pageUrl
));
}
}
}

/**
* @example
* Then should see the following error messages:
* | !name field is required. | !name => E-mail address |
*
* @param string $negate
* Indicates that user should or should not see message on the page.
* @param string $type
* Message type: error, warning, success. Could be empty.
* @param TableNode $messages
* Messages to found. Placeholders allowed.
*
* @Then /^(?:|I )should(| not) see the following (.* )messages:$/
*/
public function assertMessages($negate, $type, TableNode $messages)
{
foreach ($messages->getRowsHash() as $message => $placeholders) {
$args = [];

foreach ((array) $placeholders as $placeholder) {
// Group values: !name => Text.
$data = array_map('trim', explode('=>', $placeholder, 2));

if (count($data) === 2) {
$args[$data[0]] = $data[1];
}
}

$this->assertMessage($negate, $type, $message, $args);
}
}
}
31 changes: 31 additions & 0 deletions src/Context/Message/RawMessageContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/**
* @author Sergii Bondarenko, <sb@firstvector.org>
*/
namespace Drupal\TqExtension\Context\Message;

// Helpers.
use Behat\Mink\Element\NodeElement;

// Contexts.
use Drupal\TqExtension\Context\RawTqContext;

class RawMessageContext extends RawTqContext
{
/**
* @param string $type
* Message type: "error", "warning", "success" or nothing.
*
* @return NodeElement[]
*/
protected function getMessagesContainers($type = '')
{
if ('' !== $type) {
$type .= '_';
}

return $this->getSession()
->getPage()
->findAll('css', $selector = $this->getDrupalSelector($type . 'message_selector'));
}
}

0 comments on commit 664609b

Please sign in to comment.