Skip to content
Snippets Groups Projects
Commit 74ef0499 authored by jurgenhaas's avatar jurgenhaas
Browse files

Initial implementation

parent f7a97b43
No related branches found
No related tags found
No related merge requests found
# Behat for Drupal
This is a composer plugin which prepares your local development environment for Docker using the framework from [Docker4Drupal](https://github.com/wodby/docker4drupal) by [Wodby](https://wodby.com).
This composer plugin prepares your Drupal project for Behat tests.
## Requirements
......
......@@ -2,7 +2,12 @@
"name": "lakedrops/behat4drupal",
"description": "Composer Plugin to prepare Drupal project for Behat tests.",
"type": "composer-plugin",
"keywords": ["Drupal", "Development", "Docker", "Behat"],
"keywords": [
"Drupal",
"Development",
"Docker",
"Behat"
],
"homepage": "https://gitlab.lakedrops.com/composer/plugin/behat4drupal",
"license": "GPL-2.0-or-later",
"authors": [
......@@ -24,10 +29,19 @@
"source": "https://gitlab.lakedrops.com/composer/plugin/behat4drupal/tree/master"
},
"require": {
"php": ">=5.6",
"behat/behat": "^3.5",
"behat/mink": "^1.7",
"behat/mink-goutte-driver": "^1.2",
"behat/mink-selenium2-driver": "^1.3",
"behat/web-api-extension": "^1.0@dev",
"composer-plugin-api": "^1.0.0",
"drupal/drupal-extension": "^3.4",
"jcalderonzumba/gastonjs": "^1.2",
"jcalderonzumba/mink-phantomjs-driver": "^0.3",
"lakedrops/composer-scripts": "^1.0.0",
"lakedrops/docker4drupal": "^1.0.0",
"lakedrops/dotenv": "^1.0.0",
"php": ">=5.6",
"twig/twig": "^1.23.1"
},
"require-dev": {
......@@ -50,6 +64,14 @@
"description": "(Re-)Configure Behat for this project."
}
}
},
"scripts-description": {
"lakedrops-composer-scripts": "Scan LakeDrops plugins for scripts.",
"d4d": "(Re-)Configure docker for this project."
}
},
"scripts": {
"lakedrops-composer-scripts": "LakeDrops\\ComposerScripts\\Plugin::scripts",
"d4d": "LakeDrops\\Docker4Drupal\\Plugin::config"
}
}
<?php
namespace LakeDrops\Behat4Drupal;
use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Script\Event;
use LakeDrops\Component\Dotenv\Dotenv;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Yaml\Yaml;
/**
* Class Handler.
*
* @package LakeDrops\Behat4Drupal
*/
class Handler {
/**
* The composer object running this session.
*
* @var \Composer\Composer
*/
protected $composer;
/**
* The input-output object for the composer session.
*
* @var \Composer\IO\IOInterface
*/
protected $io;
/**
* Handler constructor.
*
* @param \Composer\Composer $composer
* The composer object.
* @param \Composer\IO\IOInterface $io
* The input-output object.
*/
public function __construct(Composer $composer, IOInterface $io) {
$this->composer = $composer;
$this->io = $io;
}
/**
* Post project create event to execute the scaffolding.
*
* @param \Composer\Script\Event $event
* The event that triggered the plugin.
* @param bool $overwrite
* Whether to overwrite existing config files.
*/
public function configureProject(Event $event, $overwrite = FALSE) {
// We only do the fancy stuff for developers.
if (!$event->isDevMode()) {
return;
}
$options = $this->getOptions();
$fs = new Filesystem();
$installationManager = $this->composer->getInstallationManager();
// Directory where the root project is being created.
$projectRoot = getcwd();
// Directory where this plugin is being installed.
$pluginRoot = $installationManager->getInstallPath($this->getPackage('lakedrops/behat4drupal'));
// Provide all the required files.
$twig_loader = new \Twig_Loader_Array([]);
$twig = new \Twig_Environment($twig_loader);
foreach ($this->getFiles($projectRoot) as $template => $def) {
if (!$fs->exists($def['dest'])) {
$fs->mkdir($def['dest']);
}
$twig_loader->setTemplate($template, $template);
$filename = $twig->render($template, $options);
$file = $def['dest'] . '/' . $filename;
if (($overwrite && empty($def['custom'])) || !$fs->exists($file)) {
$twig_loader->setTemplate($filename, file_get_contents($pluginRoot . '/templates/' . $template . '.twig'));
$rendered = $twig->render($filename, $options);
if (!empty($def['add2yaml']) && isset($options[$filename])) {
$yaml = Yaml::parse($rendered);
$yaml = array_merge_recursive($yaml, $options[$filename]);
$rendered = Yaml::dump($yaml, 9, 2);
}
if ($fs->exists($file)) {
if (md5_file($file) == md5($rendered)) {
continue;
}
$orig_file = $file . '.orig';
if ($fs->exists($orig_file)) {
$fs->remove($orig_file);
}
$fs->rename($file, $orig_file);
}
file_put_contents($file, $rendered);
}
$fs->chmod($file, 0664);
}
}
/**
* List of files and settings on how to handle them.
*
* @param string $projectRoot
* Name of the project's root directory.
*
* @return array
* List of files.
*/
protected function getFiles($projectRoot) {
return [
'behat.yml' => [
'dest' => $projectRoot . '/tests/behat',
'add2yaml' => TRUE,
],
'anonymous.feature' => [
'dest' => $projectRoot . '/tests/behat/features/basic',
],
'FeatureContext.php' => [
'dest' => $projectRoot . '/tests/behat/bootstrap/context',
'custom' => TRUE,
],
];
}
/**
* Retrieve configuration for this package.
*
* @return array
* The settings from the extra configuration.
*/
protected function getOptions() {
$projectname = str_replace([' ', '-', '_', '.'], '', basename(getcwd()));
$env = new Dotenv('behat4drupal', $this->io);
$env->put('COMPOSE_PROJECT_NAME', $projectname);
$extra = $this->composer->getPackage()->getExtra() + ['behat4drupal' => []];
return $extra['behat4drupal'] + [
'projectname' => $projectname,
];
}
}
<?php
namespace LakeDrops\Behat4Drupal;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
/**
* Composer plugin for handling drupal scaffold.
*/
class Plugin implements PluginInterface, EventSubscriberInterface {
/**
* The handler object for events.
*
* @var \LakeDrops\Behat4Drupal\Handler
*/
protected $handler;
/**
* {@inheritdoc}
*/
public function activate(Composer $composer, IOInterface $io) {
$this->handler = new Handler($composer, $io);
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return array(
ScriptEvents::POST_CREATE_PROJECT_CMD => 'postCreateProject',
);
}
/**
* Post create project event callback.
*
* @param \Composer\Script\Event $event
* The event that triggered the plugin.
*/
public function postCreateProject(Event $event) {
$this->handler->configureProject($event);
}
/**
* Script callback for putting in composer scripts to configure the project.
*
* @param \Composer\Script\Event $event
* The event that triggered the call of this function.
*/
public static function config(Event $event) {
$handler = new Handler($event->getComposer(), $event->getIO());
$handler->configureProject($event, TRUE);
}
}
<?php
use Behat\WebApiExtension\Context\WebApiContext;
class FeatureContext extends WebApiContext {
}
Feature: Anonymous User Tests
In order to protect data of the company and its customers
As an anonymous user
I want to make sure that no data is available to anonymous visitors
Background:
Given I am not logged in
Scenario: Check general availability of the site and the anonymous user site
When I am on "user"
Then I should see the text "Enter your Drupal username."
And I should not see the text "Access denied"
When I press "Log in"
Then I should see the following error messages:
| error messages |
| Username or e-mail address field is required |
| Password field is required |
And I should not see the following error messages:
| error messages |
| Sorry, unrecognized username or password |
| Unable to send e-mail. Contact the site administrator if the problem persists |
Scenario Outline: Make sure certain urls are not available
When I am on "<url>"
Then I should see the text "Access denied"
Examples:
| url |
| admin |
| node/add |
| user/1 |
default:
extensions:
Drupal\DrupalExtension:
blackbox: ~
api_driver: "drush"
region_map:
First sidebar: "#sidebar-first"
Main content: ".main-container"
selectors:
message_selector: ".messages, #absolute-messages-messages"
error_message_selector: "#absolute-messages-messages .absolute-messages-error, .alert.alert-danger"
success_message_selector: "#absolute-messages-messages .absolute-messages-status .content, #status-message-container .messages.status, .alert.alert-success"
text:
log_out: "Log out"
log_in: "Log in"
password_field: "Password"
username_field: "Username or e-mail address"
drush:
alias: default.dev
Behat\MinkExtension:
base_url: http://{{ projectname }}.docker.localhost:8000
goutte: ~
default_session: goutte
javascript_session: MyLocalChrome
browser_name: chrome
sessions:
MyLocalChrome:
selenium2:
browser: chrome
wd_host: http://hub:4444/wd/hub
capabilities:
marionette: null
locationContextEnabled: false
Behat\WebApiExtension:
base_url: http://{{ projectname }}.docker.localhost:8000
autoload:
'': "%paths.base%/bootstrap/context/"
suites:
default:
contexts:
- FeatureContext
- Drupal\DrupalExtension\Context\RawDrupalContext
- Drupal\DrupalExtension\Context\DrupalContext
- Drupal\DrupalExtension\Context\MinkContext
- Drupal\DrupalExtension\Context\MarkupContext
- Drupal\DrupalExtension\Context\MessageContext
- Drupal\DrupalExtension\Context\DrushContext
paths:
- features
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment