Planet Drupal

Subscribe to Planet Drupal feed
Drupal.org - aggregated feeds in category Planet Drupal
Updated: 52 min 32 sec ago

Anexus: How to load JS and CSS libraries in a Drupal 8 controller

Thu, 11/08/2016 - 16:03
How to load JS and CSS libraries in a Drupal 8 controller

In the blog entry http://www.anexusit.com/blog/how-to-add-reactjs-drupal-8-composer, I show you how to add into Drupal 8 any library globally using composer.

But, that library is just there, because the library isn't used for any module or theme. For that reason, I am going to show you how to use a library in a controller.

In my example, I will include ReactJS inside a controller to be able to create react elements in that controller, to show how to use I will create a simple ReactJS form.

0. Setting your environment

I strongly recommend to set your environment in developer mode; that means to enable all debugs possible and disable all caches, the easy way to do that is using the Drupal Console project with the following command:

$ drupal site:mode dev 1. Create a module

Using the Drupal Console we could create a module using the following instruction:

$ drupal generate:module  --module="MySearch" --machine-name="mysearch" --module-path="/modules/custom" --description="My custom search using react" --core="8.x" --package="Anexus" --module-file --composer -n 2. Create a controller

With our module generated, now we need to create a controller to, later on, add the ReactJS library, again using the Drupal Console commands we will make the controller.

$ drupal generate:controller  --module="mysearch" --class="ReactJSFormController" --routes="title:MySearch name:mysearch.react_j_s_form_controller_form method:form path:/mysearch" 3. Including library in our module


To enable libraries in our module, we need to create a file named mysearch.libraries.yml, below could you find an example

react.min:   version: VERSION   js:     /libraries/reactjs/build/react.min.js: {} react:   version: VERSION   js:     /libraries/reactjs/build/react.js: {} react.dom.min:   version: VERSION   js:     /libraries/reactjs/build/react-dom.min.js: {}

The keys react.min, react and react.dom.min are arbitrary strings; you could change for any identifier do you prefer. 

Maybe you are wondering about the empty curly brackets {}, the idea is like each module could load the same library with different properties, like CSS could have media info, or js could be declared to be minified or report that library is an external file.

I included the minify version of React to being used when you push this module in prod and min version could be utilized in development to facilitate the debugging.

The property version is supposed to be the library version, but if you are not sure about the proper value you could use the "constant" VERSION, this constant contains the Drupal version and is used to generate the URL to include the library resource as you can see below.

In my case, I was using Drupal 8.1.9-dev.

4. Install your module


Using the Drupal Console we could install our module

$ drupal module:install mysearch 5. Updating our controller

The controller that was generated its pretty simple as you could see in the following snippet of code:

<?php namespace Drupal\mysearch\Controller; use Drupal\Core\Controller\ControllerBase; /**  * Class ReactJSFormController.  *  * @package Drupal\mysearch\Controller  */ class ReactJSFormController extends ControllerBase {   /**    * Form.    *    * @return string    *   Return Hello string.    */   public function form() {     return [       '#type' => 'markup',       '#markup' => $this->t('Implement method: form')     ];   } }

 

If you use the module Webprofiler you can validate how many JS were loaded in your controller, in my case 69 JS files as you could appreciate in the following image.

Let me change a little bit, to include our ReactJS library.

/**    * Form.    *    * @return string    *   Return Hello string.    */   public function form() {     return [         '#markup' => $this->t('Implement method: index'),         '#attached' => array(             'library' =>  array(                 'mysearch/react.min',                'mysearch/react.dom.min',              ),         ),     ];   }

If you remember, the library was registered as react.min, but we need to include the module name first, to avoid conflict with other modules that use the same key.

Sometimes you need to clear your cache to see the changes; you can do that with Drupal Console

$ drupal cache:rebuild all

After that, you could verify that you have one extra JS file, only for this particular controller.

6. Including ReactJS form

The objective of this example was to demonstrate how to render a ReactJS form in Drupal 8

The first thing I need to do is register a local library to load JS and CSS for our form, as you can check in the following example:

react.form:   version: VERSION   js:     js/mysearch.form.js: {}   css:     theme:       css/mysearch.form.css: {}

As you could notice the path is a little different, because doesn't start with "/" that means is a relative module path instead of Drupal Root relative.

When this new library has loaded both JS and CSS components are loaded.

The content of mysearch.form.css is listed below:

.SearchForm {     padding: 8px 24px; } .SearchForm > input, .SearchForm > textarea, .SearchForm > select {     display: block;     width: 240px;     padding: 4px 8px;     margin-bottom: 8px;     border-radius: 3px;     border: 1px solid #888;     font-size: 14px; } .ContactForm > input.ContactForm-error {     border-color: #b30e2f; }

And the JS for our ReactJS form 

var Search = React.createClass({     render: function(){         return (             React.createElement('form', {onSubmit: this.onSubmit, className: 'SearchForm', noValidate: true},                 React.createElement('input', {                     type: 'text',                     placeholder: 'Search'                 }),                 React.createElement("select", { placeholder: 'Category', value: '', onChange: this.changeHandler },                     React.createElement("option", { value: 1 }, "Software"),                     React.createElement("option", { value: 2 }, "Movie")                 ),                 React.createElement('button', {type: 'submit'}, "Go")             )         );     }, }); ReactDOM.render(React.createElement(Search),  document.getElementById("content"));

The result will be a simple form, but with a lot of possibilities to implemented.

This form doesn't process anything, handle submits and request results via an API will be explaining in a further blog entry.

You can download a full and functional copy of this example from http://github.com/enzolutions/drupal-8-reactjs-form

enzo Thu, 08/11/2016 - 08:03
Categories: Elsewhere

Jeff Geerling's Blog: Register and Submit Sessions for DrupalCamp St. Louis - Sep 10-11 2016

Thu, 11/08/2016 - 05:29

The time is here! The rest of the DrupalCamp St. Louis 2016 organizers and I were working feverishly this week to get all our ducks in a row, and we now have online registration opened up for DrupalCamp St. Louis 2016! Here are the relevant details:

You'll get a snazzy T-Shirt, a catered lunch, and the fuzzy warm feeling of being part of the great Drupal open source community! Plus I'll be there!

Categories: Elsewhere

Acquia Developer Center Blog: Debugging Drupal 8 in PhpStorm

Wed, 10/08/2016 - 19:19
Introduction

Welcome to my series of blogs about debugging in Drupal 8.

The reason why I decided to create this series is that a lot of Drupalists use ”legacy” ways of non-interactive debugging based on php-native commands like print_r(), var_dump(), debug_print_backtrace() or commands provided by contributed modules or themes like dpm() or dump() inside of twig templates.

Tags: acquia drupal planet
Categories: Elsewhere

Miloš Bovan: Where can I use Mailhandler?

Wed, 10/08/2016 - 19:01
Where can I use Mailhandler?

This year’s Google Summer of Code is slowly coming to an end. I am working on latest steps to complete the project as planned. In the previous blog post, I was writing about the final code polishing of Mailhandler, while the focus of last week (#11) was to improve the overall project documentation. Before the project wrap-up blog post, I am going to write about the real use-cases for Mailhandler.

5 steps to create secured user-content-driven Drupal website

One of the best use-cases for Mailhandler would be for media publishing Drupal-based websites. Those websites usually have different user roles for content creators, publishers, editors, administrators… That means a very different set of permissions for each role. For instance, one website could allow its users to create site content. Users could submit it either through a website or by sending a signed email using Mailhandler.

In order to enable users to create content by sending an email, an administrator would need to follow these simple 5 steps:

  1. Enable authenticated users to post nodes for a specific content type (e.g. Users posts).

  2. Set-up an email address that users will send content to.

  3. Enable Mailhandler module and make sure gnu_pg PHP extension is enabled on the web server.

  4. Create a new deliverer in Inmail to fetch new emails. This can be done by using an IMAP deliverer.

  5. Set a content type in the (MailhandlerNode) handler configuration that will be used to create content in.

By completing all the steps, a Drupal website is ready to accept users submissions. Since we are going to use PGP-signed emails which add an additional layer of security, the following steps are needed on the user side:

  1. Log in to the account and update your GPG public key. PGP-signed messages are signed with a private key of a user and verified on the Drupal website with the corresponding public key. PGP method of authentication is briefly explained in this blog post.

  2. The email address in the user account needs to match to the address user wants to send emails from.

  3. The subject needs to begin with [node] part. This is a technical term and tells our plugins about the referenced entity type.

  4. The final step is to write your article and send the email!

Voila! The user created content is available on the website. Since it was digitally signed, it is guaranteed the message was not changed in transmission and the user can not deny sending and signing the message.

Some web hosting services don’t support gnu_pg PHP extension by default. However, you can still benefit from Mailhandler by using a less secure From email address method of user identification. In order to use it, you will need to enable Message Sender Analyzer.

The above use-case represents one part of the Mailhandler features. The module can be used in a similar way to post comments via email, create ads or to make any other email integration with “node” entities out-of-the-box.

To allow end-users and developers an easy start with the module, we have been improving project documentation a lot. A Github pull request has been submitted and passed for the review to my mentors. All Inmail analyzers and handler plugins provided by Mailhandler will be documented and described in details. Also, the project will get a ReadMe.MD file that will consist of the module description, installation, configuration and how-to sections.

Also, I would like to inform you that lead maintainer of the Mailhandler, Dane Powell recognized the efforts we made this summer and gave us write access to the original repository. Thanks to him, we will be able to merge our Github repository and a sandbox project to the main module. This is one step forward to releasing a stable version of Mailhandler and a duty to keep contributing to Mailhandler in the future too.

The plan for the following week is to merge the documentation pull request and work on remaining Inmail issues that we started earlier. Additionally, the final project evaluation starts in less than a week and I will spend some time to prepare for it as well.

 

 

 

Milos Wed, 08/10/2016 - 19:01 Tags Open source Google Summer of Code Drupal Drupal Planet Add new comment
Categories: Elsewhere

myDropWizard.com: Drupal 6 security updates for Google Analytics and Piwik!

Wed, 10/08/2016 - 18:21

As you may know, Drupal 6 has reached End-of-Life (EOL) which means the Drupal Security Team is no longer doing Security Advisories or working on security patches for Drupal 6 core or contrib modules - but the Drupal 6 LTS vendors are and we're one of them!

Today, there are two Moderately Critical security releases for the Google Analytics and Piwik modules to fix a Cross-Site Scripting (XSS) vulnerability.

Users who have permission to configure these modules have the ability to add unrestricted, custom JavaScript to the page, however, it's not commonly known that this permission presents a security risk (and there was previously no way to seperate the ability to configure the modules from the ability to add JavaScript).

The new versions create a new permission for adding JavaScript code, which users will need to have in addition to just the permission necessary to configure the modules.

You can download one the of three patches for Google Analytics for 6.x-2.x, 6.x-3.x and 6.x-4.x.

And you can download this one patch for Piwik.

If you have a Drupal 6 site using the Google Analytics or Piwik modules, we recommend you update immediately! We have already deployed the patch for all of our Drupal 6 Long-Term Support clients. :-)

If you'd like all your Drupal 6 modules to receive security updates and have the fixes deployed the same day they're released, please check out our D6LTS plans.

Note: if you use the myDropWizard module (totally free!), you'll be alerted to these and any future security updates, and will be able to use drush to install them (even though they won't necessarily have a release on Drupal.org).

Categories: Elsewhere

Rakesh's DSoC 16 blog: Solving Merge Conflicts in Drupal -GS0C16 - Week 11

Wed, 10/08/2016 - 17:15
Solving Merge Conflicts in Drupal -GS0C16 - Week 11 rakesh Wed, 08/10/2016 - 20:45
Categories: Elsewhere

Acquia Developer Center Blog: Acquia Pipelines: Build, Test, and Deployment Automation for Acquia Cloud

Wed, 10/08/2016 - 17:08

tl;dr: Acquia Pipelines lets you automate building, testing, and deploying sites on Acquia Cloud using tools like Composer, Sass, and Behat. Request an invitation to the private beta now.

Tags: acquia drupal planet
Categories: Elsewhere

Anexus: How to apply patches in Drupal 8 with Composer

Wed, 10/08/2016 - 14:57
How to apply patches in Drupal 8 with Composer

How I mentioned in my previous post How to add ReactJS in Drupal 8 with Composer, Composer is a fundamental part of Drupal 8 development workflow.

Like any open source projects, contributions are the core of Drupal, and those contributions are included in Drupal modules and themes and event Drupal core via Patches.

1. Drupal Installation.

In this example I will assume that did you install Drupal using *Drupal Composer* project, using an instruction similar to the following:

$ composer create-project drupal-composer/drupal-project:8.x-dev some-dir --stability dev --no-interact 2. Installing module to patch.

I will use the module Address to demonstrate how to patch a module.

Using the following module we could install the Address module in our Drupal 8 project.

$ composer require "drupal/address ~8.1" 3. Patching the module.


The Address module works pretty well, but there is an issue related to full configuration import in a site, this issue was reported and fixed in https://www.drupal.org/node/2663412. But at the moment of this article that solution wasn't included in the stable release of Address module.

Including composer lingua, we could say module and themes are packages and their difference remains in package type. To patch a package is need to edit put composer.json file to provide the patch instructions as you can see in the following snippet of code.

"extra": { "installer-paths": { "web/core": ["type:drupal-core"], "web/libraries/{$name}": ["type:drupal-library"], "web/modules/contrib/{$name}": ["type:drupal-module"], "web/profiles/contrib/{$name}": ["type:drupal-profile"], "web/themes/contrib/{$name}": ["type:drupal-theme"], "drush/contrib/{$name}": ["type:drupal-drush"] }, "patches": { "drupal/address": { "Drupal Addess fix default syncing": "https://www.drupal.org/files/issues/address_syncing.patch" } } }

As you could see, the format is a straightforward entry in patches group, providing the package to patch and the URL of the patch to be download with a human comment.

4. Applying your patches.

The next time do you run *composer install* or *composer update*; your patches will be applied, and you will get an output similar to the next image.

I recommend checking the slides Improving your Drupal 8 development workflow http://weknowinc.com/talks/2016/drupalgov-workflow for more references about how to use Composer in Drupal 8 projects

enzo Wed, 08/10/2016 - 06:57
Categories: Elsewhere

GVSO Blog: [GSoC 2016: Social API] Week 11: Documentation

Wed, 10/08/2016 - 14:43
[GSoC 2016: Social API] Week 11: Documentation

We are getting closer to Google Summer of Code final evaluation. Students must start submitting their project in 5 days. During these months, I have been working on a project to harmonize social networking functionality in Drupal. So, it was time to start creating documentation about it. This week, I focus on documentation for site builders.

gvso Wed, 08/10/2016 - 08:43 Tags Drupal Drupal Planet GSoC 2016
Categories: Elsewhere

KnackForge: How to create Queue woker in Drupal 8

Wed, 10/08/2016 - 13:04
Categories: Elsewhere

KnackForge: Regenerate a missing form #token

Wed, 10/08/2016 - 09:17
Categories: Elsewhere

LevelTen Interactive: Adventures from the Road: The Journey Begins

Wed, 10/08/2016 - 07:00

On Sunday, I trucked out of Dallas in a 38’ RV with a mess of AV equipment, a Jeep named Daisy and a pair of mountain bikes in tow. So without further ado, I'm excited to announce that LevelTen has officially kicked off its four thousand mile journey through twenty-plus cities across the United States. I know what you're thinking: What would possess me to leave my home and business for three months?

The Reason for R.O.W. Season 

I believe we are at a pivotal time for the Web. We are...Read more

Categories: Elsewhere

Talha Paracha: GSoC'16 – Pubkey Encrypt – Week 11 Report

Wed, 10/08/2016 - 02:00

As you might’ve already guessed, Pubkey Encrypt is a Google Summer of Code’2016 sponsored project. As a part of the GSoC program, I’ve spent the last 2.5 months building this module for Drupal 8. The journey so far has been amazing for me and now we’re approaching the end of the program. So I spent this week in finalizing the module. For those who don’t know, Pubkey Encrypt is a security-related module which provides a way for encrypting data with users’ login credentials. But the way the module is designed, it delegates the task of actual data encryption/decryption to some other module. Previously, we were using Encrypt Test for this purpose, which was just a test sub-module within the Encrypt module, and were waiting for Real AES module to get in a stable state. A few weeks ago, I posted a patch to fix the module but its maintainers haven’t responded yet, and its HEAD is still broken. Thus we decided to use the PHPSecLib Encryption module which in turn uses the external PHP Secure Communications Library and is hence expected to be pretty secure. The task seemed quite simple but the relevant changes simply broke all the tests for Pubkey Encrypt.

Categories: Elsewhere

Cocomore: Starting small: Why websites should get designed for small screens first

Wed, 10/08/2016 - 00:00

Search engines like Google prefer mobile optimized websites for their ranking. No surprise, after all websites are mainly accessed from devices like smartphones nowadays. If you can’t offer a responsive design you will lose traffic and therefore customers. For this reason, mobile optimized websites are crucial and “mobile first” the best way to get there.

Categories: Elsewhere

FFW Agency: Mastering the Basics: The Content Plan

Tue, 09/08/2016 - 21:26
Mastering the Basics: The Content Plan Ray Saltini Tue, 08/09/2016 - 19:26

It is amazing how often the content equation is underestimated or misunderstood whether building new properties or renewing existing sites.

The essence of any web project is the content or message to be conveyed. Understandably organizations will engage terrific creative agencies that will put tremendous effort into strategy and design. Unfortunately this often has the unintended effect of de-emphasizing existing content that may, or may not, need to be migrated to your new project. A thorough content audit early on in your planning process will help streamline your project and your budget.

Rarely is content brought over to a project wholesale without some important changes. This can be obvious like making PDF content more search engine friendly or less obvious like adding or changing metadata and reforming its underlying data structure. An audit will help determine if content migration should be included in your web development scope or handled as a separate component.

But unlike planning for strategy and design, resources are often scarce when it comes to content planning and conducting a content audit. It is likely the content planning process will be reduced to task level milestones and allocated to support staff or subject matter experts with little accommodation for the importance, difficulty or breadth of the requirements. This can lead to unforeseen and unwanted surprises during the development and user acceptance cycles of your project. 

Here are a few quick resources to get you started understanding the content planning process is Drupal.

A topic central strategy from a blog post that has only gotten more important: Understanding Content Planning: Why Taxonomy is Your New Best Friend

A great book from an accomplished Drupalist that will answer a lot of basic questions around content planning: The Drupal User's Guide by Emma Jane Hogbin Westby.

And a new series of articles about distributed content management by our very own Hank VanZile Director of Pre Sales Consulting starting with 'What is Distributed Content Management'

Tagged with Comments
Categories: Elsewhere

FFW Agency: Breaking New Ground - Tapping Free Open Source Drupal to Achieve Big Gains in the Energy Sector

Tue, 09/08/2016 - 21:10
Breaking New Ground - Tapping Free Open Source Drupal to Achieve Big Gains in the Energy Sector Ray Saltini Tue, 08/09/2016 - 19:10

Upheavals in the energy sector in recent years are driving a new Texas-sized need for efficiencies in all facets of business operations and are leading companies to begin mining new areas for streamlining and savings.

Houston, we have a solution.

The good news is open source technologies are opening up areas for exploration previously overlooked by many in the energy sector. In this multi-part series we’ll begin to look at how energy companies use the web and how open source internet technologies can drastically reduce acquisition costs, enable rapid prototyping, and create a potential for windfall profits.

Here’s a preview of our upcoming series on Drupal for the Energy Sector. Use the form below to sign up for our newsletter to get notified when we post new articles or sign up for our free training session on September 16 in Houston.

Acquisition Cost

Ever test drive a Lamborghini? Me neither. How about a proprietary web experience platform by one of the venders in Gartner’s Quadrants? Not happening. You wouldn’t buy a car you couldn’t test drive. Why consider purchasing a software platform you couldn’t pilot? Unless it’s open source you’re going to have to pay dearly for the privilege of any kind of test drive. Among the platforms listed in Gartner’s magic platform, Drupal is the only system you can freely pilot around your business needs.

Rapid Prototyping

Just because its free doesn’t mean you know what to do with it. Many open source systems have a huge transparent install base. You can install a simple plugin in your web browser that will tell you what Content Management System, technology or platform is being used. Drupal takes it even further with free custom developed distributions for different functional needs like ERP, localization and translation, publishing, ecommerce, event organizing, and networking. Agencies can build in various front end technologies and connect them to a Drupal backend with minimal customization.

Windfall Profits

How large is your IT department? Chances are the answer is something like, ‘Not big enough to do the job we have ahead of us.’ The nature of an open source project means you can tap more personnel than you could ever achieve a return on with a proprietary system. Drupal alone has over 3,000 developers that contributed to their latest version, Drupal 8. All of them are writing code that is highly secure and available for you to try and use for free.

Stay tuned for more on each of these and other topics in the coming days.
 

Tagged with Comments
Categories: Elsewhere

jmolivas.com: The DrupalConsole RC-1 release is close with a lot of changes.

Tue, 09/08/2016 - 20:27
The DrupalConsole RC-1 release is close with a lot of changes.

To make the DrupalConsole project more modular and easy to maintain, we are decoupling into separated projects.

jmolivas Tue, 08/09/2016 - 18:27
Categories: Elsewhere

Gábor Hojtsy: There will be a Drupal 9, and here is why

Tue, 09/08/2016 - 20:20

Earlier this week Steve Burge posted the intriguingly titled There Will Never be a Drupal 9. While that sure makes you click on the article, it is not quite true.

Drupal 8.0.0 made several big changes but among the biggest is the adoption of semantic versioning with scheduled releases.

Scheduled releases were decided to happen around twice a year. And indeed, Drupal 8.1.0 was released on time, Drupal 8.2.0 is in beta and Drupal 8.3.x is already open for development and got some changes committed that Drupal 8.2.x will never have. So this works pretty well so far.

As for semantic versioning, that is not a Drupalism either, see http://semver.org/. It basically means that we have three levels of version numbers now with clearly defined roles. We increment the last number when we make backwards compatible bug fixes. We increment the middle number when we add new functionality in a backwards compatible way. We did that with 8.1.0 and are about to do it with 8.2.0 later this year. And we would increment the first number (go from 8.x.x to 9.0.0) when we make backwards incompatible changes.

So long as you are on some version of Drupal 8, things need to be backwards compatible, so we can just add new things. This still allows us to modernize APIs by extending an old one in a backwards compatible way or introducing a new modern API alongside an old one and deprecate (but not remove!) the old one. This means that after a while there may be multiple parallel APIs to send emails, create routes, migrate content, expose web services and so on, and it will be an increasingly bigger mess.

There must be a balance between increasing that mess in the interest of backwards compatibility and cleaning it up to make developer's lives easier, software faster, tests easier to write and faster to run and so on. Given that the new APIs deprecate the old ones, developers are informed about upcoming changes ahead of time, and should have plenty of time to adapt their modules, themes, distributions. There may even be changes that are not possible in Drupal 8 with parallel APIs, but we don't yet have an example of that.

After that Drupal 9 could just be about removing the bad old ways and keeping the good new ways of doing things and the first Drupal 9 release could be the same as the last Drupal 8 release with the cruft removed. What would make you move to Drupal 9 then? Well, new Drupal 8 improvements would stop happening and Drupal 9.1 will have new features again.

While this is not a policy set in stone, Dries Buytaert had this to say about the topic right after his DrupalCon Barcelona keynote in the Q&A almost a year ago:

Read more about and discuss when Drupal 9 may be open at https://www.drupal.org/node/2608062

Categories: Elsewhere

php[architect]: Testing Your Drupal Site with Behat

Tue, 09/08/2016 - 20:05

If automated testing is not already part of your development workflow, then it’s time to get started. Testing helps reduce uncertainty by ensuring that new features you add to your application do not break older features. Having confidence that your not breaking existing functionality reduces time spent hunting bugs or getting reports from clients by catching them earlier.

Unfortunately, testing still does not get the time and attention it needs when you’re under pressure to make a deadline or release a feature your clients have been asking for. But—like using a version control system and having proper development, staging, and production environments—it should be a routine part of how you do your work. We are professionals, after all. After reading all the theory, I only recently took the plunge myself. In this post, I’ll show you how to use Behat to test that your Drupal site is working properly.

Before we dive in, the Behat documentation describes the project as:

[…] an open source Behavior Driven Development framework for PHP 5.3+. What’s behavior driven development, you ask? It’s a way to develop software through a constant communication with stakeholders in form of examples; examples of how this software should help them, and you, to achieve your goals.

Basically, it helps developers, clients, and others communicate and document how an application should behave. We’ll see shortly how Behat tests are very easy to read and how you can extend them for your own needs.

Mink is an extension that allows testing a web site by simulating interacting with it through a browser to fill out form fields, click on links, and so forth. Mink lets you test via Goutte, which makes requests and parses the contents but can’t execute JavaScript. It can also use Selenium, which controls a real browser and can thus test JS and Ajax interactions, but Selenium requires more configuration.

Requirements

To get started, you’ll need to have Composer on your machine. If you don’t already, head over to the Composer Website. Once installed, you can add Behat, Mink, and Mink drivers to your project by running the following in your project root:

composer require behat/behat composer require behat/mink composer require behat/mink-selenium2-driver composer require behat/mink-extension

Once eveything runs, you’ll have a composer.json file with:

"require": { "behat/behat": "^3.1", "behat/mink": "^1.7", "behat/mink-selenium2-driver": "^1.3", "behat/mink-extension": "^2.2" },

This will download Behat and it’s dependencies into your vendor/ folder. To check that it works do:

vendor/bin/behat -V

There are other ways to install Behat, outlined in the quick introduction.

The Drupal community has a contrib project, Behat Drupal Extension, that is an integration for Behat, Mink, and Drupal. You can install it with the requre command below. I had to specify the ~3.0 version, otherwise composer couldn’t satisfy dependencies.

composer require drupal/drupal-extension:~3.0

And you’ll have the following in your composer.json:

"drupal/drupal-extension": "~3.0", Configuring Behat

When you run Behat, it’ll look for a file named behat.yml. Like Drupal 8, Behat uses YAML for configuration. The file tells Behat what contexts to use. Contexts provide the tests that you can run to validate behavior. The file configures the web drivers for Mink. You can also configure a region_map which the Drupal extension uses to map identifiers (left of the :) to CSS selectors to identify theme regions. These come in very handy when testing Drupal theme output.

The one I use looks like:

default: suites: default: contexts: - Drupal\DrupalExtension\Context\DrupalContext - Drupal\DrupalExtension\Context\MarkupContext - Drupal\DrupalExtension\Context\MessageContext - FeatureContext extensions: Behat\MinkExtension: goutte: ~ javascript_session: selenium2 selenium2: wd_host: http://local.dev:4444/wd/hub capabilities: {"browser": "firefox", "version": "44"} base_url: http://local.dev Drupal\DrupalExtension: blackbox: ~ region_map: breadcrumb: '#breadcrumb' branding: '#region-branding' branding_second: '#region-branding-second' content: '#region-content' content_zone: '#zone-content' footer_first: '#region-footer-first' footer_second: '#region-footer-second' footer_fourth: '#region-footer-fourth' menu: '#region-menu' page_bottom: '#region-page-bottom' page_top: '#region-page-top' sidebar_first: '#region-sidebar-first' sidebar_second: '#region-sidebar-second' Writing a Simple Feature

Now comes the fun part. Let’s look at writing a feature and how to test that what we expect is on the page. The first time we run it, we need to initialize Behat to generate a FeatureContext class. Do so with:

vendor/bin/behat --init

That should also create a features/ directory, where we will save the features that we write. To behat, a feature is test suite. Each test in a feature evaluates specific functionality on your site. A feature is a text file that ends in .feature. You can have more than one: for example, you might have a blog.feature, members.feature, and resources.feature if your site has those areas available.

Of course, don’t confuse what Behat calls a feature—a set of tests—with the Features module that bundles and exports related functionality into a Drupal module.

For my current project, I created a global.feature file that checks if the blocks I expect to have in my header and footer are present. The contents of that file are:

Feature: Global Elements Scenario: Homepage Contact Us Link Given I am on the homepage Then I should see the link "Contact Us" in the "branding_second" region Then I should see the "Search" button in the "branding_second" region Then I should see the "div#block-system-main-menu" element in the "menu" region

As you can see, the tests is very readable even though it isn’t purely parsing natural language. Indents help organize Scenarios (a group of tests) and the conditions needed for each scenario to pass.

You can set up some conditions for the test, starting with “Given”. In this case, given that we’re on the homepage. The Drupal Extension adds ways to specify that you are a specific user, or have a specific role, and more.

Next, we list what we expect to see on the webpage. You can also tell Behat to interact with the page by specifying a link to click, form field to fill out, or a button to press. Again here, the Drupal extension (by extending the MinkExtension), provides ways to test if a link or button are in one of our configured regions. The third test above uses a CSS selector, like in jQuery, to check that the main menu block is in the menu region.

Testing user authentication

If you’re testing a site that is not local, you can use the drush api driver to test user authentication, node creation, and more. First, setup a drush alias for your site (in this example, I’m using local.dev. Then add the following are in your behat.yml:

api_driver: 'drush' drush: alias: "local.dev"

You can then create a scenario to test the user login’s work without having to specify a test username or password by tagging them with @api

@api Scenario: Admin login Given I am on the homepage Given I am logged in as a user with the "admin" role Then I should see the heading "Welcome" in the "content" region

If you’ve customized the username text for login, your test will fail. Don’t worry! Just add the following to your behat.yml file so that the test knows what text to look for. In this case, the username field label is just E-mail.

text: username_field: "E-mail" Custom Testing by Extending Contexts

When you initialized Behat, it created a features/bootstraps/FeatureContext.php file. This can be a handy class for writing custom tests for unique features on your site. You can add custom tests by using the Drupal Extension’s own sub-contexts. I changed my Feature Context to extend the Mink Context like this:

class FeatureContext extends MinkContext implements SnippetAcceptingContext {

Note that if you do that, you’ll need to remove MinkContext from the explicit list of default context in behat.yml.

No matter how you organize them, you can then write custom tests as methods. For example, the following will test that a link appears in the breadcrumb trail of a page. You can use CSS selectors to find items on the page, such as the ‘#breadcrumb’ div in a theme. You can also re-use other tests defined by the MinkContext like findLink.

/** * @Then I should see the breadcrumb link :arg1 */ public function iShouldSeeTheBreadcrumbLink($arg1) { // get the breadcrumb /** * @var Behat\Mink\Element\NodeElement $breadcrumb */ $breadcrumb = $this->getSession()->getPage()->find('css', 'div#breadcrumb'); // this does not work for URLs $link = $breadcrumb->findLink($arg1); if ($link) { return; } // filter by url $link = $breadcrumb->findAll('css', "a[href=\"{$arg1}\"]"); if ($link) { return; } throw new \Exception( sprintf("Expected link %s not found in breadcrumb on page %s", $arg1, $this->getSession()->getCurrentUrl()) ); }

If your context implements the SnippetAwareContext, behat will generate the Docblock and method signature when it encounters an unknown test. If you’re feature has the following:

Then I should see "foo-logo.png" as the header logo.

When you run your tests, behat will output the error message below that you can copy and paste to your context. Anything in quotes becomes a parameter. The DocBlock contains the annotation Behat uses to find your test when it’s used in a scenario.

/** * @Then I should see :arg1 as the header logo. */ public function iShouldSeeAsTheHeaderLogo($arg1) { throw new PendingException(); } Selenium

Follow the Behat docs to install selenium: http://mink.behat.org/en/latest/drivers/selenium2.html. When you’re testing you’ll need to have it running via:

java -jar /path/to/selenium-server-standalone-2.53.0.jar

To tell Behat how to use selenium your behat.yml file should have:

selenium2: wd_host: http://local.dev:4444/wd/hub capabilities: {"browser": "firefox"}

You’ll also need to have Firefox installed. OF course, at the time of this writing, Firefox is asking people to transition from use Webdriver to Marionette for automating browser usage. I have Firefox 47 and it’s still working with Webdriver as far as I can tell. I have not found clear, concise instructions for using Marionette with Selenium. Another option is to use Phantom.JS instead of Selenium for any features that need a real browser.

Once everything is working—you’ll know it locally because a Firefox instance will pop up—you can create a scenario like the following one. Use the @javascript tag to tell Behat to use Selenium to test it.

@javascript Scenario: Modal Popup on click Given I am at "/some/page" When I click "View More Details" Then I wait for AJAX to finish Then I should see an "#modal-content" element Then I should see text matching "This is a Modal" Conclusion

If you don’t have tests for your site, I urge you to push for adding them as part of your ongoing work. I’ve slowly added them to my main Drupal client project over the last few months and it’s really started to pay off. For one, I’ve captured many requirements and expectations about how pages on the site work that were only in my or the project manager’s heads, if not lost in a closed ticket somewhere. Second, whenever I merge new work in and before any deploy I can run tests. If they are all green, I can be confident that new code and bug fixes haven’t caused a regression. At the same time, I now have a way to test the site that makes it less risky to re-factor or reorganize code. I didn’t spend a lot of time building tests, but as I work on a new feature or fix a bug, writing a test is now just part of confirming that everything works as expected. For complicated features, it’s also become a time saver to have a test that automates a complicated interactions—like testing a 3-page web form, since Behat can run that scenario much faster than I can manually.

The benefits from investing in automated testing outweigh any initial cost in time and effort to set them up. What are you waiting for?

Categories: Elsewhere

Pages