Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #27 - Add basic CRUD operation step definitions #28

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@
}
},
"initial": {
"sites/default/default.services.yml": "[web-root]/sites/default/services.yml",
"sites/default/default.settings.php": "[web-root]/sites/default/settings.php"
"[web-root]/sites/default/default.services.yml": "[web-root]/sites/default/services.yml",
"[web-root]/sites/default/default.settings.php": "[web-root]/sites/default/settings.php"
}
}
},
Expand Down
14 changes: 13 additions & 1 deletion src-dev/Composer/Scripts.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,18 @@ protected function drupalInstallDoIt(): int
$cmdPattern[] = "$drushBase php:eval %s";
$cmdArgs[] = escapeshellarg($createMenuLinkContent);

$cmdPattern[] = '&&';
$cmdPattern[] = "$drushBase cache:rebuild";

$command = vsprintf(implode(' ', $cmdPattern), $cmdArgs);
$this->event->getIO()->write($command);

$process = new Process(
$command,
[
getenv('SHELL') ?: '/bin/bash',
'-c',
$command,
],
$this->projectRoot,
null,
null,
Expand Down Expand Up @@ -164,6 +171,11 @@ protected function prepareDrupal()
protected function prepareDrupalSettingsPhp()
{
$sitesDirPath = static::getSitesDirPath();
$this->fs->copy(
"{$sitesDirPath}/default.settings.php",
"{$sitesDirPath}/settings.php",
);

$fileName = "$sitesDirPath/settings.php";

$replacePairs = [];
Expand Down
31 changes: 28 additions & 3 deletions src/Component/Drupal/CoreContentEntityContextTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Cheppers\DrupalExtension\Component\Drupal;

use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\field\Entity\FieldStorageConfig;

trait CoreContentEntityContextTrait
Expand All @@ -23,9 +24,7 @@ protected function getContentEntityByLabel(
break;

default:
$fieldName = $etm
->getDefinition($entityTypeId)
->getKey('label');
$fieldName = $entityType->getKey('label');
break;
}
}
Expand Down Expand Up @@ -66,6 +65,32 @@ protected function getContentEntityUrlByLabel(
->toString();
}

protected function getContentEntityOperationLink(
EntityInterface $entity,
$operation
) {
/** @var \Behat\Mink\Element\DocumentElement $element */
$element = $this->getSession()->getPage();
$locator = ($operation ? ['link', sprintf("'%s'", $operation)] : ['link', "."]);

$replacementPairs = [
'edit' => 'edit-form',
'delete' => 'delete-form',
];
$op = strtr($operation, $replacementPairs);
/** @var \Behat\Mink\Element\NodeElement[] $links */
$links = $element->findAll('named', $locator);
// Loop over all the links on the page and check for the entity
// operation path.
foreach ($links as $result) {
$target = $result->getAttribute('href');
if (strpos($target, $entity->toUrl($op)->setAbsolute(FALSE)->toString()) !== FALSE) {
return $result;
}
}
return NULL;
}

protected function createContentEntity(
string $entityTypeId,
array $fieldValues
Expand Down
229 changes: 229 additions & 0 deletions src/Context/Drupal/CoreBlockContent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
<?php

namespace Cheppers\DrupalExtension\Context\Drupal;

use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;
use Behat\Mink\Exception\ExpectationException;
use Cheppers\DrupalExtension\Component\Drupal\CoreContentEntityContextTrait;
use Cheppers\DrupalExtension\Context\Base;
use Symfony\Component\Yaml\Yaml;

class CoreBlockContent extends Base
{

use CoreContentEntityContextTrait;

/**
* Creates block content of a given type provided in the form:
* | type | my_bundle_01 |
* | info | My block label |
*
* @Given block_content:
*/
public function doCreateBlockContents(TableNode $fieldValues)
{
$entityTypeId = 'block_content';
$fieldValues = $fieldValues->getRowsHash();
$fieldValues = $this->keyValuePairsToNestedArray($fieldValues);

$this->createContentEntity($entityTypeId, $fieldValues);
}

/**
* Assert editing block content given its type and title.
*
* @param string $info
* Block content info.
*
* @Given I am editing the block content :info
* @Given I edit the block content :info
*/
public function doEditTheBlockContent(string $info)
{
$url = $this->getContentEntityUrlByLabel(
'block_content',
$info,
'edit-form'
);
$this->visitPath($url);
}

/**
* Assert deleting block content given its type and info.
*
* @param string $info
* Block content info.
*
* @Given I am deleting the block content :info
* @Given I delete the block content :info
*/
public function doDeleteTheBlockContent(string $info)
{

$url = $this->getContentEntityUrlByLabel(
'block_content',
$info,
'delete-form'
);
$this->visitPath($url);
}

/**
* Assert that given user can perform given operation on block content.
*
* @param string $name
* User name.
* @param string $op
* Operation: view, edit or delete.
* @param string $info
* Block content info.
*
* @throws \Exception
* If user cannot perform given operation on given block content.
*
* @Then :name can :op block content :info
* @Then :name can :op :info block content
*/
public function doUserCanBlockContent(
string $name,
string $op,
string $info
) {
$op = strtr($op, ['edit' => 'update']);
$block = $this->getContentEntityByLabel('block_content', $info);
$access = $this->assertBlockContentAccess($op, $name, $block);
if (!$access) {
throw new \Exception("{$name} cannot {$op} '{$info}' but it is supposed to.");
}
}

/**
* Assert that given user cannot perform given operation on block content.
*
* @param string $name
* User name.
* @param string $op
* Operation: view, edit or delete.
* @param string $info
* Block content info.
*
* @throws \Exception
* If user can perform given operation on given block content.
*
* @Then :name can not :op block content :info
* @Then :name cannot :op block content :info
* @Then :name cannot :op :info block content
*/
public function doUserCanNotBlockContent(
string $name,
string $op,
string $info
) {
$op = strtr($op, ['edit' => 'update']);
$block = $this->getContentEntityByLabel('block_content', $info);
$access = $this->assertBlockContentAccess($op, $name, $block);
if ($access) {
throw new \Exception("{$name} can {$op} '{$info}' but it is not supposed to.");
}
}

/**
* Assert presence of block content operation links.
*
* @param string $operation
* The operation.
* @param string $info
* Block content info.
*
* @throws \Behat\Mink\Exception\ExpectationException
* If no link for operation has been found.
*
* @Then I should see the :operation link to block content :info
* @Then I should see a :operation link to block content :info
*/
public function doShouldSeeBlockContentOperationLink(
string $operation,
string $info
) {
$block = $this->getContentEntityByLabel('block_content', $info);
$url = $this->getContentEntityOperationLink($block, $op);
if (!$url) {
throw new ExpectationException(
"No link to '$operation' '$info' has been found.",
$this->getSession()
);
}
}

/**
* Assert absence of block content operation links.
*
* @param string $info
* Block content info.
* @param string $operation
* The operation.
*
* @throws \Behat\Mink\Exception\ExpectationException|\Exception
* If link for operation has been found.
*
* @Then I should not see the :operation link to block content :info
* @Then I should not see a :operation link to block content :info
*/
public function doShouldNotSeeBlockContentOperationLink(
string $info,
string $operation
) {
$block = $this->getContentEntityByLabel('block_content', $info);
$url = $this->getContentEntityOperationLink($block, $op);
if ($url) {
throw new ExpectationException("link to '$operation' '$info' has been found.", $this->getSession());
}
}

/**
* Sanitize then parse a string.
*
* @param \Behat\Gherkin\Node\PyStringNode $node
* The string to be sanitized.
*
* @return mixed
* The YAML converted to a PHP value.
*/
public function doSanitizeYaml(PyStringNode $node)
{
// Sanitize PyString test by removing initial indentation spaces.
$strings = $node->getStrings();
if ($strings) {
preg_match('/^(\s+)/', $strings[0], $matches);
$indentationSize = isset($matches[1]) ? strlen($matches[1]) : 0;
foreach ($strings as $key => $string) {
$strings[$key] = substr($string, $indentationSize);
}
}
$raw = implode("\n", $strings);
return Yaml::parse($raw);
}

/**
* Check whereas a user can perform and operation on a given block content.
*
* @param string $op
* Operation: view, update or delete.
* @param string $name
* Username.
* @param object $block
* Block content object.
*
* @return bool
* TRUE if user can perform operation, FALSE otherwise.
*/
public function assertBlockContentAccess(
string $op,
string $name,
object $block
): bool {
$account = $this->getCore()->loadUserByName($name);
return $block->access($op, $account);
}
}
36 changes: 19 additions & 17 deletions tests/behat/config/suite.default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@ default:
suites:
default:
contexts:
# - '\Cheppers\DrupalExtensionDev\Context\CodeCoverageContext'
# - '\Cheppers\DrupalExtensionDev\Context\FeatureContext'
- '\Cheppers\DrupalExtensionDev\Context\CodeCoverageContext'
- '\Cheppers\DrupalExtensionDev\Context\FeatureContext'
- '\Cheppers\DrupalExtensionDev\Context\CodeCoverageContext'
- '\Drupal\DrupalExtension\Context\MinkContext'
- '\Drupal\DrupalExtension\Context\DrupalContext'
- '\NuvoleWeb\Drupal\DrupalExtension\Context\DrupalContext'
# - '\Drupal\DrupalExtension\Context\MessageContext'
# - '\NuvoleWeb\Drupal\DrupalExtension\Context\VisibilityContext'
# - '\Cheppers\DrupalExtension\Context\Drupal\AppContentEntitySetupTearDown'
# - '\Cheppers\DrupalExtension\Context\Drupal\Core'
# - '\Cheppers\DrupalExtension\Context\Drupal\CoreAjax'
# - '\Cheppers\DrupalExtension\Context\Drupal\CoreCache'
# - '\Cheppers\DrupalExtension\Context\Drupal\CoreCkeditor'
# - '\Cheppers\DrupalExtension\Context\Drupal\CoreFormCheckboxes'
# - '\Cheppers\DrupalExtension\Context\Drupal\CoreFormSelect'
# - '\Cheppers\DrupalExtension\Context\Drupal\CoreMenu'
# - '\Cheppers\DrupalExtension\Context\Drupal\CoreSystem'
# - '\Cheppers\DrupalExtension\Context\Drupal\CoreTabs'
# - '\Cheppers\DrupalExtension\Context\Drupal\CoreUser'
# - '\Cheppers\DrupalExtension\Context\Drupal\CoreVerticalTabs'
# - '\Cheppers\DrupalExtension\Context\Table'
- '\Drupal\DrupalExtension\Context\MessageContext'
- '\NuvoleWeb\Drupal\DrupalExtension\Context\VisibilityContext'
- '\Cheppers\DrupalExtension\Context\Drupal\AppContentEntitySetupTearDown'
- '\Cheppers\DrupalExtension\Context\Drupal\Core'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreAjax'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreBlockContent'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreCache'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreCkeditor'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreFormCheckboxes'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreFormSelect'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreMenu'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreSystem'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreTabs'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreUser'
- '\Cheppers\DrupalExtension\Context\Drupal\CoreVerticalTabs'
- '\Cheppers\DrupalExtension\Context\Table'
paths:
features: '%paths.base%/features'
filters:
Expand Down
14 changes: 14 additions & 0 deletions tests/behat/features/Drupal/Core/core.block_content.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@api
@javascript
Feature: Some helpful description.

Scenario: Some helpful description.
Given block_content:
| type | basic |
| info | my label |
And I am logged in as a user with the "Administrator" role
When I go to "/admin/structure/block/block-content"
Then I should see the text "my label"

Given I am editing the block content "my label"
Then the "Block description" field should contain "my label"
Loading