Getting started testing Javascript interactions with Drupal 7, Behat 3, Selenium2 - selenium

I have been stuck on how to configure my Drupal 7 site to work with Behat to test Javascript interactions.
This is the setup I am starting with. If someone could help me modify my configuration to support testing Javascript I would greatly appreciate it.
Vagrant 1.8.1 running:
- Ubuntu 14.04.2 LTS
- PHP 5.6.22-1+donate.sury.org~trusty+1 (cli)
- Drupal 7.41
- Selenium: selenium-server-standalone-2.46.0.jar
I started Selenium using the following commands:
java -jar /opt/selenium/selenium-server-standalone.jar -role hub -port 4444
java -jar /opt/selenium/selenium-server-standalone.jar -role node -hub http://localhost:4444/grid/register
It looks like Selenium is running: lsof -i -n -P | grep 4444
php 2428 vagrant 6u IPv6 22327 0t0 TCP [::1]:46489->[::1]:4444 (CLOSE_WAIT)
composer.json
{
"require-dev": {
"drush/drush": "7.1.0",
"drupal/coder": "7.2.5",
"phpunit/php-timer": "dev-master",
"pear/Console_Color2": "0.1.2",
"behat/behat": "3.1.0",
"behat/mink": "1.7.1",
"behat/mink-extension": "2.2",
"behat/mink-goutte-driver": "1.2.1",
"behat/mink-selenium2-driver": "1.3.1",
"drupal/drupal-extension": "3.2.1"
},
"config": {
"bin-dir": "bin/"
}
}
behat.yml
# behat.yml
default:
autoload: [ %paths.base%/contexts ]
extensions:
Behat\MinkExtension:
goutte: ~
selenium2: ~
base_url: http://test.dev
Drupal\DrupalExtension:
blackbox: ~
suites:
default:
paths: [ %paths.base%/features ]
filters:
contexts:
- FeatureContext
- Drupal\DrupalExtension\Context\DrupalContext
- Drupal\DrupalExtension\Context\MinkContext
- Drupal\DrupalExtension\Context\MessageContext
- Drupal\DrupalExtension\Context\DrushContext
contexts/FeatureContext.php
<?php
use Behat\Behat\Context\Context;
use Behat\Behat\Context\SnippetAcceptingContext;
use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;
/**
* Defines application features from the specific context.
*/
class FeatureContext implements Context, SnippetAcceptingContext
{
/**
* Initializes context.
*
* Every scenario gets its own context instance.
* You can also pass arbitrary arguments to the
* context constructor through behat.yml.
*/
public function __construct()
{
}
}
features/test.feature
Feature: Test DrupalContext
In order to prove the Drupal context using the blackbox driver is working properly
As a developer
I need to use the step definitions of this context
#javascript
Scenario: Test the ability to find a heading in a region
Given I am on the homepage
When I click "some link"
Then I should see the heading "Some heading"
When I run test.feature behat features/test.feature I get the following output. I do not know how to get the stack trace to output. If you can tell me how I will add that information to my post.
Feature: Test DrupalContext
In order to prove the Drupal context using the blackbox driver is working properly
As a developer
I need to use the step definitions of this context
#javascript
Scenario: Test the ability to find a heading in a region # features/test.feature:7
Given I am on the homepage # Drupal\DrupalExtension\Context\MinkContext::iAmOnHomepage()
Could not open connection (Behat\Mink\Exception\DriverException)
When I click "some link" # Drupal\DrupalExtension\Context\MinkContext::assertClick()
Then I should see the heading "Some heading" # Drupal\DrupalExtension\Context\MinkContext::assertHeading()

Since you are testing a Drupal 7 site, I would recommend you to use the Drupal Extension that is provided by Behat. Looks like you have already required the necessary extension in your composer file. So no need to update the composer in this case.
However, you can use the 'drupal' driver or 'drush' driver here instead of 'blackbox', since they are much more powerful. If you have a local setup of the site, go ahead with the 'Drupal' driver. 'Drupal' driver is the strongest of the available API drivers.
Please follow the steps below to get your first scenario running:
Modify your behat.yml file as below:
Drupal\DrupalExtension:
api_driver: 'drupal'
drupal:
drupal_root: /path/to/docroot/
2. Modify your FeatureContext file, class file should extend DrupalContext, so that you can use all the ready-made step definitions that Drupal extension provides.
class FeatureContext extends DrupalContext implements SnippetAcceptingContext, Context {
In the command prompt, in your Behat parent directory, type the command:
bin/behat --dl
Don't forget to tag your scenarios or the entire feature file with #api
This would give you a list of all in-built Drupal based step definitions. Let me know how it goes.

Related

Running selenium tests using Behat Drupal Extension inside DDEV containers

Problem: Get Behat Drupal Extension based testing working inside of ddev containers. This includes adding a separate selenium container to the existing configuration, being able to run Behat tests, and having the be able to reference the web host container.
Prerequisites: have a working ddev instance hosting Drupal. There are examples already to set that up, so I won't repeat that here.
The above task required the following additions:
selenium container: The container running selenium. I used the chrome standalone version. Add the following to your .ddev folder:
File: docker-compose.selenium.yml
version: '3.6'
services:
selenium:
container_name: ddev-${DDEV_SITENAME}-selenium
image: selenium/standalone-chrome-debug:3.13.0-argon
networks:
default:
aliases:
- web
The last bit is critical; the selenium container needs to know about the web container running the drupal instance to connect to it, but as it is a dependency of the web container, you can't use 'links'. You have to use the aliases approach, using the default network.
compose override: A file overriding the defaults for the web container to link the selenium container to it.
File: docker-compose.override.yml
version: '3.6'
services:
web:
depends_on:
- db
- selenium
links:
- db:db
- selenium:selenium
Behat configuration: The following Behat configuration for MinkExtension worked for me:
(modify file behat.yml)
default:
extensions:
"Behat\\MinkExtension":
goutte: null
base_url: 'http://web'
javascript_session: selenium2
selenium2:
browser: "chrome"
wd_host: http://selenium:4444/wd/hub
capabilities:
extra_capabilities:
idle-timeout: 50
base_url and wd_host entries were critical in getting this to work.
For more information on the last, see step 5 in the Behat Drupal Extension docs:
Configure your testing environment by creating a file called behat.yml with the following. Be sure that you point the base_url at the web site YOU intend to test. Do not include a trailing slash:
default:
suites:
default:
contexts:
- FeatureContext
- Drupal\DrupalExtension\Context\DrupalContext
- Drupal\DrupalExtension\Context\MinkContext
- Drupal\DrupalExtension\Context\MessageContext
- Drupal\DrupalExtension\Context\DrushContext
extensions:
Drupal\MinkExtension:
goutte: ~
selenium2: ~
base_url: http://seven.l
Drupal\DrupalExtension:
blackbox: ~

I can't connect to my site using Behat (but a browser is fine)

I've just started playing around with Behat, and I was loving it. Then I shut down my computer and went home for the day and when I came back, nothing worked for me any more. I've been trying to trouble-shoot this, but looks like the configurations vary so widely, I can't find anything that works for me. I'm getting the following error
Given I am on the homepage # Drupal\DrupalExtension\Context\MinkContext::iAmOnHomepage()
Could not open connection: Curl error thrown for http POST to http://localhost:4444/wd/hub/session with params: {"desiredCapabilities":{"tags":["rio","PHP 5.5.9-1ubuntu4.9"],"browser":"firefox","version":"14","ignoreZoomSetting":false,"name":"Behat feature suite","browserName":"firefox"}}
The requested URL returned error: 500 Server Error (Behat\Mink\Exception\DriverException)
I've got my behat.yml file setup as such:
default:
default:
suites:
default:
contexts:
- FeatureContext
- Drupal\DrupalExtension\Context\DrupalContext
- Drupal\DrupalExtension\Context\MinkContext
extensions:
Behat\MinkExtension:
base_url: http://localhost:80/vic
goutte: ~
default_session: selenium2
browser_name: 'firefox'
selenium2:
capabilities: { "browser": "firefox", "version": "14"}
javascript_session: selenium2
Drupal\DrupalExtension:
blackbox: ~
drush:
root: /var/www/html/vic
api_driver: 'drupal'
drupal:
drupal_root: '/var/www/html/vic'
Like I said, this was previously working just fine. Now I don't know why it stopped. The error is weird to me too. the base url doesn't seem to be registering and I have no idea why it's pulling up port 4444 or going to the folder structure wd/hub/session.
Some background. I'm running this on my local machine on a local environment. I'm on a Linux box. The base url works for me in my browser, but Behat can't seem to reach it, and it's adding a weird port (should be 80), and path. It worked the other day, and nothing has changed other than a reboot (so I need to start up a service or something)?
Found the answer. Make sure selenium is running first.
java -jar selenium-server-standalone-2.45.0.jar (make sure your version is right)
Once it's running it'll give you connection info, make sure that matches in your behat.yml
extensions:
Behat\MinkExtension:
base_url: http://localhost:80
goutte: ~
javascript_session: selenium2
default_session: selenium2
browser_name: 'firefox'
selenium2:
capabilities: { "browser": "firefox", "version": "14"}
wd_host: http://127.0.0.1:4444/wd/hub
^^ do that by pointing the wd_host to the selenium instance

Installing behat on a Symfony 2.0 project using deps - what versions?

I have a legacy Symfony 2.0 project (version 2.0.11 to be precise) to which I'd like to add behat tests. As it's Symfony 2.0, it uses the deps vendor system rather than composer. I'm not in a position to upgrade the Symfony version or switch to composer at the moment.
I attempted to install behat using the following deps settings:
[Mink]
target=/Behat/Mink
git=git://github.com/Behat/Mink.git
version=v1.3.3
[MinkBundle]
target=/Behat/MinkBundle
git=git://github.com/Behat/MinkBundle.git
[BehatBundle]
target=/Behat/BehatBundle
git=git://github.com/Behat/BehatBundle.git
[Gherkin]
target=/Behat/Gherkin
git=git://github.com/Behat/Gherkin.git
version=v2.1.1
[Behat]
target=/Behat/Behat
git=git://github.com/Behat/Behat.git
version=v2.3.5
[Goutte]
target=/Goutte
git=git://github.com/fabpot/Goutte.git
(Yes, I know that the BehatBundle etc are outdated, but it looked like I'd need these outdated versions given that I'm using deps and sf2.0.)
When I run vendor/Behat/Behat/bin/behat, I then get the issue described here:
PHP Warning: require_once(behat/autoload.php): failed to open stream: No such file or directory in /home/sam/wo-code/PersonaBubble/vendor/Behat/Behat/bin/behat on line 23
PHP Fatal error: require_once(): Failed opening required 'behat/autoload.php' (include_path='.:/usr/share/php:/usr/share/pear') in /home/sam/wo-code/PersonaBubble/vendor/Behat/Behat/bin/behat on line 23
I realised that behat 2.3.5 doesn't actually have an autoload.php file. I looked through Behat's tags on Github and realised that 2.1.3 was the latest version which had an autoload.php (actually autoload.php.dist, though every earlier version also had autoload.php.dist rather than autoload.php, so I assumed that this was it).
I therefore changed my behat version number in deps to v2.1.3, deleted my vendors and re-installed. The behat command had then changed, so I ran:
php vendor/Behat/Behat/bin/behat.php
I now saw this error:
PHP Fatal error: Class 'Symfony\Component\Console\Application' not found in /home/sam/wo-code/PersonaBubble/vendor/Behat/Behat/src/Behat/Behat/Console/BehatApplication.php on line 26
Does anyone know what the correct versions of behat etc are that I should use to get it working with Symfony 2.0 and deps? Or is there some other step that I'm missing.
PS I ended up running behat via PHAR (although this had other problems so I abandoned it as not worth it). However, I really want to know how to do it via standard vendors install, hence this post.
I'm not in a position to upgrade the Symfony version or switch to
composer at the moment.
I understand what you say but example below might give you a bit of hint I hope! I hope it helps a bit.
I'm sharing what I have been using for all my Symfony2 projects. Behat+Mink+Selenium
CONPOSER:
You need certain versions so that eveyone use same versions of everthing.
mySymfonyProject/composer.json:
"require": {
"behat/behat": "2.5.*#stable",
"behat/behat-bundle": "1.0.0",
"behat/symfony2-extension": "1.1.2",
"behat/mink": "1.5.0",
"behat/mink-extension": "~1.3",
"behat/mink-selenium2-driver": "1.1.1",
"behat/mink-goutte-driver": "1.0.9"
},
"config": {
"bin-dir": "bin"
},
"minimum-stability": "dev",
BEHAT
mySymfonyProject/behat.yml:
default:
context:
class: FeatureContext
extensions:
Behat\Symfony2Extension\Extension:
mink_driver: true
kernel:
env: test
debug: true
Behat\MinkExtension\Extension:
base_url: 'http://mysymfonyproject.local/app_test.php/'
javascript_session: selenium2
browser_name: firefox
goutte: ~
selenium2: ~
paths:
features: %behat.paths.base%/src
bootstrap: %behat.paths.features%/Context
SELENIUM
Download into your project. It is here, make sure you download 2.43.1 version which is in the middle of the page.
Run it: java -jar selenium-server-standalone-2.43.1.jar
CONTEXT FEATURE
mySymfonyProject/src/Site/CommonBundle/Features/Context/FeatureContext.php
<?php
namespace Site\CommonBundle\Features\Context;
use Behat\MinkExtension\Context\MinkContext;
use Behat\Symfony2Extension\Context\KernelAwareInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class FeatureContext extends MinkContext implements KernelAwareInterface
{
/**
* Hold Symfony kernel object.
*
* #var object Kernel Object.
*/
protected $kernel;
/**
* Helps to use doctrine and entity manager.
*
* #param KernelInterface $kernelInterface Interface for getting Kernel.
*/
public function setKernel(KernelInterface $kernelInterface)
{
$this->kernel = $kernelInterface;
}
//And your own methods
}
TESTS
When you have feature files you can run them like this (this runs all in one go. for more info read behat doc):
bin/behat #SiteCommonBundle

Test browser code with Intern through Grunt and Phantomjs

I have been playing with Intern and made my tests work in the browser. To better integrate with my current workflow I'm trying to run my tests through grunt with phantomjs. However all my attempts have failed. I've been looking at this question as a reference Intern WebDriver and PhantomJS but can't figure out all of the steps to make it work.
First of all: Is it even possible to run the tests through grunt and phantomjs?
A little bit of info:
I don't want/can't connect to Sauce Labs or a Selenium testing environment.
I want to test browser code while having jQuery as a shimmed dependency
I have Grunt 0.4.1 and phantomjs 1.9.1 installed
I'm not testing any ajax request (as the linked question is having problem with)
I'm not familiar with neither Selenium nor Sauce Lab
If it is possible to test through grunt and phanomjs, how would I go about doing it?
I guess that I have to start the GhostDriver
phantomjs --webdriver=8910
But then what are the important pieces of info in the Intern config to make this work?
define({
proxyPort: 9000,
proxyUrl: 'http://localhost:9000/',
environments: [
{
browserName: 'phantom',
version: '1.9.0',
platform: 'Linux'
}
],
webdriver: {
host: 'localhost',
port: 8910
},
maxConcurrency: 3,
useSauceConnect: false,
// ...
});
How does the environments browserName map to phantomjs? I've tried the browserNames 'phantom' as well as 'phanomjs' with different versions and platforms (running Mac 10.7)
My Gruntfile section for intern looks like:
intern: {
phantom: {
options: {
config: 'tests/intern',
reporters: ['webdriver']
}
}
}
Running this setup without any test-suite that includes browser code outputs
'ReferenceError: document is not defined' in 'node_modules/intern/lib/reporters/webdriver.js:41:19'
Adding browser tests gives 'ReferenceError: window is not defined' in 'src/vendor/jquery/jquery-1.9.1.js:9597:5'
Running it through node gives the same 'window is not defined' error.
node node_modules/intern/client.js config=tests/intern
What am I doing wrong/missing here?
There are two problems with your Gruntfile configuration:
The default run type for the Grunt task is 'client', which means it runs the Node.js client by default, not the test runner. You need to set runType: 'runner' in your Gruntfile options to run tests against your specified environments.
The webdriver reporter is for use in a browser client only and is specified automatically by the test runner when it is needed. You should typically never use it directly. The reporter you specify in the Gruntfile should be the one you want the test runner to use; the console default is usually appropriate.
These two things in combination mean that you’ve configured Intern to try to use a reporter that only works in a browser in conjunction with the test runner inside the Node.js client, hence the error. Once corrected, the remaining configuration should work properly to run on PhantomJS, assuming it is already running on localhost at port 8910.

Behat 2.4 upgrade issues, or Unrecognized options "extensions" under "behat" - error when attempting to activate sahi extension via behat.yml

Fairly new to this Behat stuff, and I've run into a roadblock I can't seem to get around. I've been staring at the docs, googling like it's my job, and doing my best to refrain from tossing my computer off the fire escape.
I'm working with a fairly complex project, and I'm not the one who set it up. So I'm a little lost in some areas.
Currently, I'm trying to use the Sahi driver, because selenium isn't cutting it for some dynamic forms I need to test. I can run the tests fine with the default selenium driver, but the tests fail because it doesn't adequately trigger JavaScript events on form input. Specifically, it'll work with the workarounds covered in that link, but only if I have the browser in focus. Which means it fails when the tests are run in sauce or via jenkins with xvfb.
I'm explaining all this only because this is my larger issue, which I'm attempting to address by using the Sahi driver. Which brings me to:
[Symfony\Component\Config\Definition\Exception\InvalidConfigurationException]
Unrecognized options "extensions" under "behat"
That's what I get when I try to activate the Sahi driver for a particular profile in my bahat.yml the way the documentation says to.
Here's the default profile and the profile I'm currently working with in my behat.yml (slightly modifies for public consumption):
default:
paths:
features: 'features'
bootstrap: '%behat.paths.features%/bootstrap'
sahi:
extensions:
Behat\MinkExtension\Extension:
sahi: ~
context:
class: 'FeatureContext'
parameters:
environment: 'staging'
mink: 'sahi'
Fwiw, the tests are on a vm, which I ssh -X into, then run the test using
$ behat --tags #test_name_tag --profile=sahi
When I'm using the default selenium driver and the #javascript tag, the browser pops up and the tests run and pass (assuming I keep the browser in focus, of course).
I installed the additional drivers using composer:
{
"require": {
"behat/behat": "2.4.*#stable",
"behat/mink": "1.4#stable",
"behat/mink-extension": "*",
"behat/mink-selenium2-driver": "*",
"behat/mink-sahi-driver": "*"
}
}
I've added use Behat\Mink\Driver\SahiDriver; to my MinkContext.php, EnvironmentContext.php and FeatureContext.php, though I'm guessing that's probably either overkill or not necessary. It doesn't seem to be making a difference at this point, though. I get the same error with or without it.
I also added a sahi.php which lives in features/bootstrap/mink:
<?php
return
array(
'default_session' => 'sahi',
'sahi' => array(
'capabilities' => array(
'browserName' => 'firefox',
'browserVersion' => 7,
),
),
);
I thought maybe adding a directory in features/bootstrap called exensions might help for some reason. Even stuck a file in there called sahi.php. That didn't help much.
I think that covers everything. Thanks in advance for any help, and if this is covered elsewhere, please direct me to it, because I've spent countless hours looking and haven't found anything that helps me.
Update:
I uninstalled the old versions of behat, mink and gherkin, and installed 2.4, et al as per this https://lestbddphp.wordpress.com/2012/08/31/behatcomposer/
I've been making my way through "Migrating from Behat 2.3 to 2.4" in the docs. (Sorry, SO won't let me post any more links, but it's in the official Behat docs.)
My composer.json:
{
"require": {
"behat/behat": "2.4.*#stable",
"behat/mink": "1.4#stable",
"behat/mink-goutte-driver": "*",
"behat/symfony2-extension": "*",
"symfony/class-loader": "2.1.*",
"symfony/form": "2.1.*",
"symfony/validator": "2.1.*",
"behat/mink-selenium-driver": "*",
"behat/mink-selenium2-driver": "*",
"behat/mink-extension": "*",
"behat/mink-sahi-driver": "*"
},
"minimum-stability": "dev",
"config": {
"bin-dir": "bin/"
}
}
I moved my behat.yml file to the root of the project, as directed. I updated my default profile to:
default:
paths:
features: 'features'
bootstrap: '%behat.paths.features%/bootstrap'
extensions:
Behat\Symfony2Extension\Extension:
mink_driver: true
kernel:
env: test
debug: true
Behat\MinkExtension\Extension:
default_session: symfony2
sahi: ~
though I'm not entirely sure that's what I need. Just going by the example given in the docs.
I updated my vendor/autoload.php by replacing the require_once with require:
<?php
// autoload.php generated by Composer
require __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInit::getLoader();
but I'm a little confused by this, because that file is different from the example code in the docs. If I were to add the line in the docs here, instead of what was already there, then it would just be loading itself. (I tried. It barfed.) Am I completely dense, or is the wording here confusing/misleading? Did I do this correctly?
As I mentioned before, I have 3 context files in features/bootstrap:
FeatureContext.php
EnvironmentContext.php
MinkContext.php
When running the tests via cli, I pass it a --profile, and then it uses the appropriate profile in behat.yml. In almost all of the profiles, FeatureContext is used.
context:
class: 'FeatureContext'
FeatureContext then gets EnvironmentContext and MinkContext, from what I can tell. So, theoretically, everything should be working there.
Only it's not.
$ bin/behat --profile=sahi
[ReflectionException]
Class AppKernel does not exist
Before I added all the Symfony stuff, I was getting this:
Warning: require(Behat\Symfony2Extension\Extension): failed to open stream: No such file or directory in /path/to/project/vendor/behat/behat/src/Behat/Behat/Extension/ExtensionManager.php on line 112
Fatal error: require(): Failed opening required 'Behat\Symfony2Extension\Extension' (include_path='/usr/share/pear:/usr/share/php:/usr/share/git core/templates/hooks:.') in /path/to/project/vendor/behat/behat/src/Behat/Behat/Extension/ExtensionManager.php on line 112
Which is why I added the Symfony stuff via composer.
Also possibly of note: when I forgot to pass it a --profile, before installing the Symfony stuff via composer, I got this:
Notice: Undefined index: environment in /home/lbaron/development/BeHat-Functional/features/bootstrap/FeatureContext.php on line 43
Warning: include(/path/to/project/features/bootstrap/environment/.php): failed to open stream: No such file or directory in /path/to/project/features/bootstrap/FeatureContext.php on line 44
Warning: include(): Failed opening '/path/to/project/features/bootstrap/environment/.php' for inclusion (include_path='/usr/share/pear:/usr/share/php:/usr/share/git-core/templates/hooks:.') in /path/to/project/features/bootstrap/FeatureContext.php on line 44
Catchable fatal error: Argument 1 passed to EnvironmentContext::__construct() must be an array, boolean given, called in /path/to/project/features/bootstrap/FeatureContext.php on line 44 and defined in /path/to/project/features/bootstrap/EnvironmentContext.php on line 27
Which I guess is to be expected.
So I'm at a loss now. Ideas?
I'm going to keep banging on it to see if I can figure it out, but any ideas/input would be greatly appreciated.
Update again:
Removing the extensions section from yml gives me this:
Catchable fatal error: Argument 2 passed to Symfony\Component\BrowserKit\Client::__construct() must be an instance of Symfony\Component\BrowserKit\History, array given, called in /usr/share/pear/mink/src/Behat/Mink/Behat/Context/MinkContext.php on line 163 and defined in /home/lbaron/development/BeHat-Functional/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Client.php on line 52
Current state of behat.yml:
default:
paths:
features: 'features'
bootstrap: '%behat.paths.features%/bootstrap'
formatter:
parameters:
language: 'en'
extensions:
Behat\MinkExtension\Extension:
sahi: ~
goutte: ~
You are running a version of behat which is older that 2.4 (the current version). I can tell because the command you use is "behat" instead of "bin/behat". Older versions had a different architecture and did not use extensions. The documentation on the behat.org website is all for the new 2.4 version and, as far as I know, does not have the documentation for older versions available anymore. You should upgrade your behat version to 2.4, there is a guide on how to do this here