Skip to content

Commit

Permalink
Merge pull request #481 from jhedstrom/293-random-generator
Browse files Browse the repository at this point in the history
Adds a RandomContext for generating random strings in steps.
  • Loading branch information
jhedstrom committed Apr 17, 2018
2 parents bd90c35 + 61a8259 commit f3164de
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 0 deletions.
1 change: 1 addition & 0 deletions behat.yml.dist
Expand Up @@ -115,6 +115,7 @@ drupal8:
- Drupal\DrupalExtension\Context\MarkupContext
- Drupal\DrupalExtension\Context\MessageContext
- Drupal\DrupalExtension\Context\MailContext
- Drupal\DrupalExtension\Context\RandomContext
filters:
tags: "@d8&&~@d8wip"
extensions:
Expand Down
5 changes: 5 additions & 0 deletions doc/contexts.rst
Expand Up @@ -31,6 +31,11 @@ following contexts:
Step-definitions that are specific to Drupal messages that get displayed
(notice, warning, and error).

*RandomContext*
Contains transforms that allow for use of placeholders such as `<?title>` that will be replaced with a random string
when the scenario is run: `Given I am viewing an "Article" with the title "<?title>"`


*DrushContext*
Allows steps to directly call drush commands.

Expand Down
20 changes: 20 additions & 0 deletions features/random.feature
@@ -0,0 +1,20 @@
@api @d8 @random
Feature: RandomContext functionality
In order to prove the RandomContext is functional at transforming variables
As a developer
I need to use random variables in scenarios

# This will fail on the second scenario if random transforms are not functional.
Scenario: Create a first user
Given I am at "/user/register"
And I fill in "Email address" with "<?user>@example.com"
And I fill in "Username" with "<?user>"
When I press "Create new account"
Then an email has been sent to "<?user>@example.com" with the subject "Account details for <?user>"

Scenario: Create the second user
Given I am at "/user/register"
And I fill in "Email address" with "<?user>@example.com"
And I fill in "Username" with "<?user>"
When I press "Create new account"
Then an email has been sent to "<?user>@example.com" with the subject "Account details for <?user>"
15 changes: 15 additions & 0 deletions spec/Drupal/DrupalExtension/Context/RandomContextSpec.php
@@ -0,0 +1,15 @@
<?php

namespace spec\Drupal\DrupalExtension\Context;

use Drupal\DrupalExtension\Context\RandomContext;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class RandomContextSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType(RandomContext::class);
}
}
90 changes: 90 additions & 0 deletions src/Drupal/DrupalExtension/Context/RandomContext.php
@@ -0,0 +1,90 @@
<?php

namespace Drupal\DrupalExtension\Context;

use Behat\Behat\Hook\Scope\AfterScenarioScope;
use Behat\Behat\Hook\Scope\BeforeScenarioScope;

/**
* Class RandomContext
* @package Drupal\DrupalExtension\Context
*
* Transform tokens into random variables.
*/
class RandomContext extends RawDrupalContext
{
/**
* Tracks variable names for consistent replacement during a given scenario.
*
* @var array
*/
protected $values = [];

/**
* The regex to use for variable replacement.
*
* This matches placeholders in steps of the form `Given a string <?random>`.
*/
const VARIABLE_REGEX = '#(\<\?.*?\>)#';

/**
* Transform random variables.
*
* @Transform #([^<]*\<\?.*\>[^>]*)#
*/
public function transformVariables($message)
{
$patterns = [];
$replacements = [];

preg_match_all(static::VARIABLE_REGEX, $message, $matches);
foreach ($matches[0] as $variable) {
$replacements[] = $this->values[$variable];
$patterns[] = '#' . preg_quote($variable) . '#';
}
$message = preg_replace($patterns, $replacements, $message);

return $message;
}

/**
* Set values for each random variable found in the current scenario.
*
* @BeforeScenario
*/
public function beforeScenarioSetVariables(BeforeScenarioScope $scope)
{
$steps = [];
if ($scope->getFeature()->hasBackground()) {
$steps = $scope->getFeature()->getBackground()->getSteps();
}
$steps = array_merge($steps, $scope->getScenario()->getSteps());
foreach ($steps as $step) {
preg_match_all(static::VARIABLE_REGEX, $step->getText(), $matches);
$variables_found = $matches[0];
// Find variables in are TableNodes or PyStringNodes.
$step_argument = $step->getArguments();
if (!empty($step_argument) && $step_argument[0] instanceof TableNode) {
preg_match_all(static::VARIABLE_REGEX, $step_argument[0]->getTableAsString(), $matches);
$variables_found = array_filter(array_merge($variables_found, $matches[0]));
}
foreach ($variables_found as $variable_name) {
if (!isset($this->values[$variable_name])) {
$value = $this->getDriver()->getRandom()->name(10);
// Value forced to lowercase to ensure it is machine-readable.
$this->values[$variable_name] = strtolower($value);
}
}
}
}

/**
* Reset variables after the scenario.
*
* @AfterScenario
*/
public function afterScenarioResetVariables(AfterScenarioScope $scope)
{
$this->values = [];
}
}

0 comments on commit f3164de

Please sign in to comment.