Skip to content

Commit

Permalink
Multiple example tables and tags support Behat#117
Browse files Browse the repository at this point in the history
  • Loading branch information
stukalin committed Dec 11, 2016
1 parent 5c14cff commit cb0290d
Show file tree
Hide file tree
Showing 24 changed files with 881 additions and 239 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
vendor
composer.phar
composer.lock
.idea/*
78 changes: 40 additions & 38 deletions src/Behat/Gherkin/Filter/LineFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,6 @@ public function isFeatureMatch(FeatureNode $feature)
return $this->filterLine === $feature->getLine();
}

/**
* Checks if scenario or outline matches specified filter.
*
* @param ScenarioInterface $scenario Scenario or Outline node instance
*
* @return Boolean
*/
public function isScenarioMatch(ScenarioInterface $scenario)
{
if ($this->filterLine === $scenario->getLine()) {
return true;
}

if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
return $this->filterLine === $scenario->getLine()
|| in_array($this->filterLine, $scenario->getExampleTable()->getLines());
}

return false;
}

/**
* Filters feature according to the filter and returns new one.
*
Expand All @@ -83,24 +62,26 @@ public function filterFeature(FeatureNode $feature)
}

if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
$table = $scenario->getExampleTable()->getTable();
$lines = array_keys($table);

if (in_array($this->filterLine, $lines)) {
$filteredTable = array($lines[0] => $table[$lines[0]]);

if ($lines[0] !== $this->filterLine) {
$filteredTable[$this->filterLine] = $table[$this->filterLine];
foreach ($scenario->getExampleTables() as $exampleTable) {
$table = $exampleTable->getTable();
$lines = array_keys($table);

if (in_array($this->filterLine, $lines)) {
$filteredTable = array($lines[0] => $table[$lines[0]]);

if ($lines[0] !== $this->filterLine) {
$filteredTable[$this->filterLine] = $table[$this->filterLine];
}

$scenario = new OutlineNode(
$scenario->getTitle(),
$scenario->getTags(),
$scenario->getSteps(),
array(new ExampleTableNode($filteredTable, $exampleTable->getKeyword(), $exampleTable->getTags())),
$scenario->getKeyword(),
$scenario->getLine()
);
}

$scenario = new OutlineNode(
$scenario->getTitle(),
$scenario->getTags(),
$scenario->getSteps(),
new ExampleTableNode($filteredTable, $scenario->getExampleTable()->getKeyword()),
$scenario->getKeyword(),
$scenario->getLine()
);
}
}

Expand All @@ -119,4 +100,25 @@ public function filterFeature(FeatureNode $feature)
$feature->getLine()
);
}

/**
* Checks if scenario or outline matches specified filter.
*
* @param ScenarioInterface $scenario Scenario or Outline node instance
*
* @return Boolean
*/
public function isScenarioMatch(ScenarioInterface $scenario)
{
if ($this->filterLine === $scenario->getLine()) {
return true;
}

if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
return $this->filterLine === $scenario->getLine()
|| in_array($this->filterLine, $scenario->getExampleTable()->getLines());
}

return false;
}
}
73 changes: 41 additions & 32 deletions src/Behat/Gherkin/Filter/LineRangeFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,30 +54,6 @@ public function isFeatureMatch(FeatureNode $feature)
&& $this->filterMaxLine >= $feature->getLine();
}

/**
* Checks if scenario or outline matches specified filter.
*
* @param ScenarioInterface $scenario Scenario or Outline node instance
*
* @return Boolean
*/
public function isScenarioMatch(ScenarioInterface $scenario)
{
if ($this->filterMinLine <= $scenario->getLine() && $this->filterMaxLine >= $scenario->getLine()) {
return true;
}

if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
foreach ($scenario->getExampleTable()->getLines() as $line) {
if ($this->filterMinLine <= $line && $this->filterMaxLine >= $line) {
return true;
}
}
}

return false;
}

/**
* Filters feature according to the filter.
*
Expand All @@ -94,23 +70,32 @@ public function filterFeature(FeatureNode $feature)
}

if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
$table = $scenario->getExampleTable()->getTable();
$lines = array_keys($table);
// first accumulate examples and then create scenario
$exampleTableNodes = array();

foreach ($scenario->getExampleTables() as $exampleTable) {
$table = $exampleTable->getTable();
$lines = array_keys($table);

$filteredTable = array($lines[0] => $table[$lines[0]]);
unset($table[$lines[0]]);
$filteredTable = array($lines[0] => $table[$lines[0]]);
unset($table[$lines[0]]);

foreach ($table as $line => $row) {
if ($this->filterMinLine <= $line && $this->filterMaxLine >= $line) {
$filteredTable[$line] = $row;
foreach ($table as $line => $row) {
if ($this->filterMinLine <= $line && $this->filterMaxLine >= $line) {
$filteredTable[$line] = $row;
}
}

if (count($filteredTable) > 1) {
$exampleTableNodes[] = new ExampleTableNode($filteredTable, $exampleTable->getKeyword(), $exampleTable->getTags());
}
}

$scenario = new OutlineNode(
$scenario->getTitle(),
$scenario->getTags(),
$scenario->getSteps(),
new ExampleTableNode($filteredTable, $scenario->getExampleTable()->getKeyword()),
$exampleTableNodes,
$scenario->getKeyword(),
$scenario->getLine()
);
Expand All @@ -131,4 +116,28 @@ public function filterFeature(FeatureNode $feature)
$feature->getLine()
);
}

/**
* Checks if scenario or outline matches specified filter.
*
* @param ScenarioInterface $scenario Scenario or Outline node instance
*
* @return Boolean
*/
public function isScenarioMatch(ScenarioInterface $scenario)
{
if ($this->filterMinLine <= $scenario->getLine() && $this->filterMaxLine >= $scenario->getLine()) {
return true;
}

if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
foreach ($scenario->getExampleTable()->getLines() as $line) {
if ($this->filterMinLine <= $line && $this->filterMaxLine >= $line) {
return true;
}
}
}

return false;
}
}
57 changes: 56 additions & 1 deletion src/Behat/Gherkin/Filter/TagFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
namespace Behat\Gherkin\Filter;

use Behat\Gherkin\Node\FeatureNode;
use Behat\Gherkin\Node\OutlineNode;
use Behat\Gherkin\Node\ScenarioInterface;

/**
Expand All @@ -32,6 +33,50 @@ public function __construct($filterString)
$this->filterString = trim($filterString);
}

public function filterFeature(FeatureNode $feature)
{
$scenarios = array();
foreach ($feature->getScenarios() as $scenario) {
if (!$this->isScenarioMatch($feature, $scenario)) {
continue;
}

if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {

$exampleTables = array();

foreach ($scenario->getExampleTables() as $exampleTable) {
if ($this->isTagsMatchCondition(array_merge($feature->getTags(), $scenario->getTags(), $exampleTable->getTags()))) {
$exampleTables[] = $exampleTable;
}
}

$scenario = new OutlineNode(
$scenario->getTitle(),
$scenario->getTags(),
$scenario->getSteps(),
$exampleTables,
$scenario->getKeyword(),
$scenario->getLine()
);
}

$scenarios[] = $scenario;
}

return new FeatureNode(
$feature->getTitle(),
$feature->getDescription(),
$feature->getTags(),
$feature->getBackground(),
$scenarios,
$feature->getKeyword(),
$feature->getLanguage(),
$feature->getFile(),
$feature->getLine()
);
}

/**
* Checks if Feature matches specified filter.
*
Expand All @@ -47,13 +92,23 @@ public function isFeatureMatch(FeatureNode $feature)
/**
* Checks if scenario or outline matches specified filter.
*
* @param FeatureNode $feature Feature node instance
* @param FeatureNode $feature Feature node instance
* @param ScenarioInterface $scenario Scenario or Outline node instance
*
* @return Boolean
*/
public function isScenarioMatch(FeatureNode $feature, ScenarioInterface $scenario)
{
if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
foreach ($scenario->getExampleTables() as $example) {
if ($this->isTagsMatchCondition(array_merge($feature->getTags(), $scenario->getTags(), $example->getTags()))) {
return true;
}
}

return false;
}

return $this->isTagsMatchCondition(array_merge($feature->getTags(), $scenario->getTags()));
}

Expand Down
38 changes: 37 additions & 1 deletion src/Behat/Gherkin/Loader/ArrayLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,43 @@ protected function loadOutlineHash(array $hash, $line = 0)
$examplesKeyword = 'Examples';
}

$examples = new ExampleTableNode($hash['examples'], $examplesKeyword);
$exHash = $hash['examples'];
$examples = array();

// there are 3 cases
// first is examples as a single table - we create an array with the only one element
// examples
// 11: abc
// 12: cde
//
// second is array of arrays
// examples
// -
// 11: abc
// 12: cde
//
// and the 3rd is array of objects
// examples
// -
// tags: []
// table:
// 11: abc
// 12: cde

if (isset($exHash[0])) {
// cases #2 & 3
for ($i = 0; $i < count($exHash); $i++) {
if (isset($exHash[$i]['table'])) {
// we have examples as objects
$exHashTags = isset($exHash[$i]['tags']) ? $exHash[$i]['tags'] : array();
$examples[] = new ExampleTableNode($exHash[$i]['table'], $examplesKeyword, $exHashTags);
} else {
$examples[] = new ExampleTableNode($exHash[$i], $examplesKeyword);
}
}
} else {
$examples[] = new ExampleTableNode($exHash, $examplesKeyword);;
}

return new OutlineNode($hash['title'], $hash['tags'], $steps, $examples, $hash['keyword'], $hash['line']);
}
Expand Down
20 changes: 18 additions & 2 deletions src/Behat/Gherkin/Node/ExampleTableNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
*/
class ExampleTableNode extends TableNode
{
/**
* @var string[]
*/
private $tags;

/**
* @var string
*/
Expand All @@ -25,12 +30,14 @@ class ExampleTableNode extends TableNode
/**
* Initializes example table.
*
* @param array $table Table in form of [$rowLineNumber => [$val1, $val2, $val3]]
* @param array $table Table in form of [$rowLineNumber => [$val1, $val2, $val3]]
* @param string $keyword
* @param string[] $tags
*/
public function __construct(array $table, $keyword)
public function __construct(array $table, $keyword, array $tags = array())
{
$this->keyword = $keyword;
$this->tags = $tags;

parent::__construct($table);
}
Expand All @@ -45,6 +52,15 @@ public function getNodeType()
return 'ExampleTable';
}

/**
* Returns attached tags
* @return \string[]
*/
public function getTags()
{
return $this->tags;
}

/**
* Returns example table keyword.
*
Expand Down
Loading

0 comments on commit cb0290d

Please sign in to comment.