Skip to content

Commit

Permalink
Added menu and menu link traits. (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
richardgaunt authored Mar 19, 2021
1 parent 8612677 commit 672d09b
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 3 deletions.
171 changes: 168 additions & 3 deletions src/D8/MenuTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace IntegratedExperts\BehatSteps\D8;

use Behat\Behat\Hook\Scope\AfterScenarioScope;
use Behat\Gherkin\Node\TableNode;
use Drupal\menu_link_content\Entity\MenuLinkContent;
use Drupal\system\Entity\Menu;

/**
Expand All @@ -13,17 +15,180 @@
trait MenuTrait {

/**
* Remove menu.
* Menus.
*
* @var \Drupal\system\Entity\Menu[]
*/
protected $menus = [];

/**
* Menu links.
*
* @var \Drupal\menu_link_content\Entity\MenuLinkContent[]
*/
protected $menuLinks = [];

/**
* Remove menu by menu name.
*
* Provide menu labels in the following format:
* | Fish Menu |
* | ... |
*
* @Given no menus:
*/
public function menuDelete(TableNode $table) {
foreach ($table->getColumn(0) as $name) {
$menu = Menu::load($name);
foreach ($table->getColumn(0) as $label) {
$menu = $this->loadMenuByLabel($label);
if ($menu) {
$menu->delete();
}
}
}

/**
* Create a menu if one does not exist.
*
* Provide menu data in the following format:
*
* | label | description |
* | Fish Menu | Menu of fish |
* | ... | ... |
*
* @Given menus:
*/
public function menuCreate(TableNode $table) {
foreach ($table->getHash() as $menu_hash) {
if (empty($menu_hash['id'])) {
// Create menu id if one not provided.
$menu_id = strtolower($menu_hash['label']);
$menu_id = preg_replace('/[^a-z0-9_]+/', '_', $menu_id);
$menu_id = preg_replace('/_+/', '_', $menu_id);
$menu_hash['id'] = $menu_id;
}
$menu = Menu::create($menu_hash);
$menu->save();
$this->menus[] = $menu;
}
}

/**
* Remove menu links by title.
*
* Provide menu link titles in the following format:
* | Test Menu |
* | ... |
*
* @Given no :menu_name menu_links:
*/
public function menuLinksDelete($menu_name, TableNode $table) {
foreach ($table->getColumn(0) as $title) {
$menu_link = $this->loadMenuLinkByTitle($title, $menu_name);
if ($menu_link) {
$menu_link->delete();
}
}
}

/**
* Create menu links.
*
* Provide menu link data in the following format:
*
* | title | enabled | uri | parent |
* | Parent Link | 1 | https://www.example.com | |
* | Child Link | 1 | https://www.example.com | Parent Link |
* | ... | ... | ... | ... |
*
* @Given :menu_name menu_links:
*/
public function menuLinksCreate($menu_name, TableNode $table) {
$menu = $this->loadMenuByLabel($menu_name);
foreach ($table->getHash() as $menu_link_hash) {
$menu_link_hash['menu_name'] = $menu->id();
// Add uri to correct property.
$menu_link_hash['link']['uri'] = $menu_link_hash['uri'];
unset($menu_link_hash['uri']);
// Create parent property in format required.
if (!empty($menu_link_hash['parent'])) {
$parent_link = $this->loadMenuLinkByTitle($menu_link_hash['parent'], $menu_name);
$menu_link_hash['parent'] = 'menu_link_content:' . $parent_link->uuid();
}
else {
unset($menu_link_hash['parent']);
}
$menu_link = MenuLinkContent::create($menu_link_hash);
$menu_link->save();
$this->menuLinks[] = $menu_link;
}
}

/**
* @AfterScenario
*/
public function menuCleanAll(AfterScenarioScope $scope) {
// Allow to skip this by adding a tag.
if ($scope->getScenario()->hasTag('behat-steps-skip:' . __FUNCTION__)) {
return;
}
// Clean up created menus.
foreach ($this->menus as $menu) {
try {
$menu->delete();
}
catch (\Exception $exception) {
// Ignore the exception and move on.
continue;
}
}
// Clean up menu links.
foreach ($this->menuLinks as $menu_link) {
try {
$menu_link->delete();
}
catch (\Exception $exception) {
// Ignore the exception and move on.
continue;
}
}

$this->menuLinks = [];

$this->menus = [];
}

/**
* Gets a menu by label.
*/
protected function loadMenuByLabel($label) {
/** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
$entity_type_manager = \Drupal::getContainer()->get('entity_type.manager');
$query = $entity_type_manager->getStorage('menu')->getQuery();
$query->condition('label', $label);
$menu_ids = $query->execute();
$menu_id = reset($menu_ids);
if ($menu_id === FALSE) {
throw new \Exception(sprintf('Could not find the %s menu.', $label));
}

return Menu::load($menu_id);
}

/**
* Gets a menu link by title and menu name.
*/
protected function loadMenuLinkByTitle($title, $menu_name) {
$menu = $this->loadMenuByLabel($menu_name);
/** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
$entity_type_manager = \Drupal::getContainer()->get('entity_type.manager');
$query = $entity_type_manager->getStorage('menu_link_content')->getQuery();
$menu_link_ids = $query->condition('menu_name', $menu->id())->condition('title', $title)->execute();
$menu_link_id = reset($menu_link_ids);
if ($menu_link_id === FALSE) {
throw new \Exception(sprintf('Could not find the %s menu link in %s menu.', $title, $menu_name));
}

return MenuLinkContent::load($menu_link_id);
}

}
22 changes: 22 additions & 0 deletions src/SelectTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public function selectShouldHaveOption($select, $option) {
if (is_null($optionElement)) {
throw new \InvalidArgumentException(sprintf('Option "%s" is not found in select "%s".', $option, $select));
}

return $optionElement;
}

/**
Expand All @@ -39,4 +41,24 @@ public function selectShouldNotHaveOption($select, $option) {
}
}

/**
* @Then select :select should have option :option selected
*/
public function selectShouldHaveOptionSelected($select, $option) {
$optionElement = $this->selectShouldHaveOption($select, $option);
if ($optionElement->getAttribute('selected') !== 'selected') {
throw new \InvalidArgumentException(sprintf('Option "%s" in select "%s" is not selected.', $option, $select));
}
}

/**
* @Then select :select should not have option :option selected
*/
public function selectShouldHaveNotOptionSelected($select, $option) {
$optionElement = $this->selectShouldHaveOption($select, $option);
if ($optionElement->getAttribute('selected') === 'selected') {
throw new \InvalidArgumentException(sprintf('Option "%s" in select "%s" is selected, but should not.', $option, $select));
}
}

}
2 changes: 2 additions & 0 deletions tests/behat/bootstrap/FeatureContextD8.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
use IntegratedExperts\BehatSteps\LinkTrait;
use IntegratedExperts\BehatSteps\PathTrait;
use IntegratedExperts\BehatSteps\ResponseTrait;
use IntegratedExperts\BehatSteps\SelectTrait;

/**
* Defines application features from the specific context.
Expand All @@ -60,6 +61,7 @@ class FeatureContextD8 extends DrupalContext {
use PathTrait;
use ResponseTrait;
use RoleTrait;
use SelectTrait;
use TaxonomyTrait;
use TestmodeTrait;
use UserTrait;
Expand Down
45 changes: 45 additions & 0 deletions tests/behat/features/d8.menu.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
@d8
Feature: Check that MenuTrait works for D8

@api
Scenario: Assert "Given menus:"
Given menus:
| label | description |
| [TEST] menu 1 title | Test menu 1 description |
| [TEST] menu 2 title | Test menu 2 description |
And I am logged in as a user with the "administrator" role
When I visit "/admin/structure/menu"
Then I should see the text "[TEST] menu 1 title"
And I should see the text "[TEST] menu 2 title"
And I should see the text "Test menu 1 description"
And I should see the text "Test menu 2 description"

@api
Scenario: Assert "Given no menus:"
Given menus:
| label | description |
| [TEST] menu 1 title | Test menu 1 description |
| [TEST] menu 2 title | Test menu 2 description |
Given no menus:
| [TEST] menu 1 title |
| [TEST] menu 2 title |
And I am logged in as a user with the "administrator" role
When I visit "/admin/structure/menu"
Then I should not see the text "[TEST] menu 1 title"
And I should not see the text "[TEST] menu 2 title"
And I should not see the text "Test menu 1 description"
And I should not see the text "Test menu 2 description"

@api
Scenario: Assert "Given menu_links:"
Given menus:
| label | description |
| [TEST] menu 1 title | Test menu 1 description |
Given "[TEST] menu 1 title" menu_links:
| title | enabled | uri | parent |
| Parent Link Title | 1 | https://www.example.com | |
| Child Link Title | 1 | https://www.example.com | Parent Link Title |
And I am logged in as a user with the "administrator" role
When I visit "/admin/structure/menu/manage/_test_menu_1_title"
And I should see "Parent Link Title"
And I should see "Child Link Title"

0 comments on commit 672d09b

Please sign in to comment.