added support for automatic show on failures

This commit is contained in:
everzet
2012-09-10 20:20:10 +02:00
parent 0b8a4d7d10
commit 9e2c34cbd0
6 changed files with 237 additions and 76 deletions

View File

@@ -2,12 +2,8 @@
namespace Behat\MinkExtension\Context\Initializer;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Behat\Behat\Context\Initializer\InitializerInterface,
Behat\Behat\Context\ContextInterface,
Behat\Behat\Event\ScenarioEvent,
Behat\Behat\Event\OutlineEvent;
Behat\Behat\Context\ContextInterface;
use Behat\Mink\Mink;
@@ -27,7 +23,7 @@ use Behat\MinkExtension\Context\MinkAwareInterface;
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class MinkAwareInitializer implements InitializerInterface, EventSubscriberInterface
class MinkAwareInitializer implements InitializerInterface
{
private $mink;
private $parameters;
@@ -44,33 +40,6 @@ class MinkAwareInitializer implements InitializerInterface, EventSubscriberInter
$this->parameters = $parameters;
}
/**
* Returns an array of event names this subscriber wants to listen to.
*
* The array keys are event names and the value can be:
*
* * The method name to call (priority defaults to 0)
* * An array composed of the method name to call and the priority
* * An array of arrays composed of the method names to call and respective
* priorities, or 0 if unset
*
* For instance:
*
* * array('eventName' => 'methodName')
* * array('eventName' => array('methodName', $priority))
* * array('eventName' => array(array('methodName1', $priority), array('methodName2'))
*
* @return array The event names to listen to
*/
public static function getSubscribedEvents()
{
return array(
'beforeScenario' => array('prepareDefaultMinkSession', 10),
'beforeOutline' => array('prepareDefaultMinkSession', 10),
'afterSuite' => array('tearDownMinkSessions', -10)
);
}
/**
* Checks if initializer supports provided context.
*
@@ -106,47 +75,4 @@ class MinkAwareInitializer implements InitializerInterface, EventSubscriberInter
$context->setMink($this->mink);
$context->setMinkParameters($this->parameters);
}
/**
* Configures default Mink session before each scenario.
* Configuration is based on provided scenario tags:
*
* `@javascript` tagged scenarios will get `javascript_session` as default session
* `@mink:CUSTOM_NAME tagged scenarios will get `CUSTOM_NAME` as default session
* Other scenarios get `default_session` as default session
*
* `@insulated` tag will cause Mink to stop current sessions before scenario
* instead of just soft-resetting them
*
* @param ScenarioEvent|OutlineEvent $event
*/
public function prepareDefaultMinkSession($event)
{
$scenario = $event instanceof ScenarioEvent ? $event->getScenario() : $event->getOutline();
$session = $this->parameters['default_session'];
foreach ($scenario->getTags() as $tag) {
if ('javascript' === $tag) {
$session = $this->parameters['javascript_session'];
} elseif (preg_match('/^mink\:(.+)/', $tag, $matches)) {
$session = $matches[1];
}
}
if ($scenario->hasTag('insulated')) {
$this->mink->stopSessions();
} else {
$this->mink->resetSessions();
}
$this->mink->setDefaultSessionName($session);
}
/**
* Stops all started Mink sessions.
*/
public function tearDownMinkSessions()
{
$this->mink->stopSessions();
}
}

View File

@@ -114,6 +114,10 @@ class Extension implements ExtensionInterface
$minkReflection = new \ReflectionClass('Behat\Mink\Mink');
$minkLibPath = realpath(dirname($minkReflection->getFilename()) . '/../../../');
$container->setParameter('mink.paths.lib', $minkLibPath);
if ($config['show_auto']) {
$loader->load('failure_show_listener.xml');
}
}
/**
@@ -136,6 +140,9 @@ class Extension implements ExtensionInterface
scalarNode('files_path')->
defaultValue(isset($config['files_path']) ? $config['files_path'] : null)->
end()->
booleanNode('show_auto')->
defaultValue(false)->
end()->
scalarNode('show_cmd')->
defaultValue(isset($config['show_cmd']) ? $config['show_cmd'] : null)->
end()->

View File

@@ -0,0 +1,91 @@
<?php
namespace Behat\MinkExtension\Listener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Behat\Behat\Event\StepEvent;
use Behat\Mink\Mink;
/*
* This file is part of the Behat\MinkExtension.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Failed step response show listener.
* Listens to failed Behat steps and shows last response in a browser.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class FailureShowListener implements EventSubscriberInterface
{
private $mink;
private $parameters;
/**
* Initializes initializer.
*
* @param Mink $mink
* @param array $parameters
*/
public function __construct(Mink $mink, array $parameters)
{
$this->mink = $mink;
$this->parameters = $parameters;
}
/**
* Returns an array of event names this subscriber wants to listen to.
*
* The array keys are event names and the value can be:
*
* * The method name to call (priority defaults to 0)
* * An array composed of the method name to call and the priority
* * An array of arrays composed of the method names to call and respective
* priorities, or 0 if unset
*
* For instance:
*
* * array('eventName' => 'methodName')
* * array('eventName' => array('methodName', $priority))
* * array('eventName' => array(array('methodName1', $priority), array('methodName2'))
*
* @return array The event names to listen to
*/
public static function getSubscribedEvents()
{
return array(
'afterStep' => array('showFailedStepResponse', -10)
);
}
/**
* Shows last response of failed step with preconfigured command.
* Configuration is based on `behat.yml`:
*
* `show_auto` enable this listener (default to false)
* `show_cmd` command to run (`open %s` to open default browser on Mac)
* `show_tmp_dir` folder where to store temp files (default is system temp)
*
* @param StepEvent $event
*/
public function showFailedStepResponse($event)
{
if (StepEvent::FAILED !== $event->getResult()) {
return;
}
if (null === $this->parameters['show_cmd']) {
throw new \RuntimeException('Set "show_cmd" parameter in behat.yml to be able to open page in browser (ex.: "show_cmd: open %s")');
}
$filename = rtrim($this->parameters['show_tmp_dir'], DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.uniqid().'.html';
file_put_contents($filename, $this->mink->getSession()->getPage()->getContent());
system(sprintf($this->parameters['show_cmd'], escapeshellarg($filename)));
}
}

View File

@@ -0,0 +1,112 @@
<?php
namespace Behat\MinkExtension\Listener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Behat\Behat\Event\ScenarioEvent,
Behat\Behat\Event\OutlineEvent;
use Behat\Mink\Mink;
/*
* This file is part of the Behat\MinkExtension.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Mink sessions listener.
* Listens Behat events and configures/stops Mink sessions.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class SessionsListener implements EventSubscriberInterface
{
private $mink;
private $parameters;
/**
* Initializes initializer.
*
* @param Mink $mink
* @param array $parameters
*/
public function __construct(Mink $mink, array $parameters)
{
$this->mink = $mink;
$this->parameters = $parameters;
}
/**
* Returns an array of event names this subscriber wants to listen to.
*
* The array keys are event names and the value can be:
*
* * The method name to call (priority defaults to 0)
* * An array composed of the method name to call and the priority
* * An array of arrays composed of the method names to call and respective
* priorities, or 0 if unset
*
* For instance:
*
* * array('eventName' => 'methodName')
* * array('eventName' => array('methodName', $priority))
* * array('eventName' => array(array('methodName1', $priority), array('methodName2'))
*
* @return array The event names to listen to
*/
public static function getSubscribedEvents()
{
return array(
'beforeScenario' => array('prepareDefaultMinkSession', 10),
'beforeOutline' => array('prepareDefaultMinkSession', 10),
'afterSuite' => array('tearDownMinkSessions', -10)
);
}
/**
* Configures default Mink session before each scenario.
* Configuration is based on provided scenario tags:
*
* `@javascript` tagged scenarios will get `javascript_session` as default session
* `@mink:CUSTOM_NAME tagged scenarios will get `CUSTOM_NAME` as default session
* Other scenarios get `default_session` as default session
*
* `@insulated` tag will cause Mink to stop current sessions before scenario
* instead of just soft-resetting them
*
* @param ScenarioEvent|OutlineEvent $event
*/
public function prepareDefaultMinkSession($event)
{
$scenario = $event instanceof ScenarioEvent ? $event->getScenario() : $event->getOutline();
$session = $this->parameters['default_session'];
foreach ($scenario->getTags() as $tag) {
if ('javascript' === $tag) {
$session = $this->parameters['javascript_session'];
} elseif (preg_match('/^mink\:(.+)/', $tag, $matches)) {
$session = $matches[1];
}
}
if ($scenario->hasTag('insulated')) {
$this->mink->stopSessions();
} else {
$this->mink->resetSessions();
}
$this->mink->setDefaultSessionName($session);
}
/**
* Stops all started Mink sessions.
*/
public function tearDownMinkSessions()
{
$this->mink->stopSessions();
}
}

View File

@@ -14,6 +14,7 @@
<parameter key="behat.mink.context.class_guesser.class">Behat\MinkExtension\Context\ClassGuesser\MinkContextClassGuesser</parameter>
<parameter key="behat.mink.context.initializer.class">Behat\MinkExtension\Context\Initializer\MinkAwareInitializer</parameter>
<parameter key="behat.mink.listener.sessions_listener.class">Behat\MinkExtension\Listener\SessionsListener</parameter>
<parameter key="behat.mink.default_session">goutte</parameter>
<parameter key="behat.mink.javascript_session">selenium2</parameter>
@@ -43,6 +44,11 @@
<argument type="service" id="behat.mink" />
<argument>%behat.mink.parameters%</argument>
<tag name="behat.context.initializer" />
</service>
<service id="behat.mink.listener.sessions_listener" class="%behat.mink.listener.sessions_listener.class%">
<argument type="service" id="behat.mink" />
<argument>%behat.mink.parameters%</argument>
<tag name="behat.event_subscriber" priority="0" />
</service>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="behat.mink.listener.failure_show_listener.class">Behat\MinkExtension\Listener\FailureShowListener</parameter>
</parameters>
<services>
<service id="behat.mink.listener.failure_show_listener" class="%behat.mink.listener.failure_show_listener.class%">
<argument type="service" id="behat.mink" />
<argument>%behat.mink.parameters%</argument>
<tag name="behat.event_subscriber" priority="0" />
</service>
</services>
</container>