Merge pull request #136 from stof/default_session_per_suite

Added the possibility to define the default session per suite
This commit is contained in:
Konstantin Kudryashov
2014-04-26 21:17:15 +01:00
4 changed files with 170 additions and 24 deletions

View File

@@ -144,18 +144,18 @@ Sessions
You can register as many Mink session as you want. For each session, you You can register as many Mink session as you want. For each session, you
will need to choose the driver you want to use. will need to choose the driver you want to use.
.. code-block:: yaml .. code-block:: yaml
default: default:
extensions: extensions:
Behat\MinkExtension\Extension: Behat\MinkExtension\Extension:
sessions: sessions:
first_session: first_session:
selenium2: ~ selenium2: ~
second_session: second_session:
goutte: ~ goutte: ~
third_session: third_session:
selenium2: ~ selenium2: ~
MinkExtension will set the default Mink session for each scenario based on MinkExtension will set the default Mink session for each scenario based on
the configuration settings ``default_session`` and ``javascript_session`` the configuration settings ``default_session`` and ``javascript_session``
@@ -165,6 +165,17 @@ and on scenario tags:
* A scenario tagged with ``@javascript`` will use the javascript session as default session; * A scenario tagged with ``@javascript`` will use the javascript session as default session;
* Other scenarios will use the default session. * Other scenarios will use the default session.
The default session and the default javascript session can also be configured for
each suite:
.. code-block:: yaml
default:
suites:
first:
mink_session: foo
mink_javascript_session: sahi
If it is not configured explicitly, the javascript session is set to the first If it is not configured explicitly, the javascript session is set to the first
session using a javascript driver in the order of the configuration (it would session using a javascript driver in the order of the configuration (it would
be ``first_session`` in the example above as ``selenium2`` supports Javascript). be ``first_session`` in the example above as ``selenium2`` supports Javascript).

View File

@@ -7,17 +7,23 @@ use Behat\Gherkin\Node\FeatureNode;
use Behat\Gherkin\Node\ScenarioNode; use Behat\Gherkin\Node\ScenarioNode;
use Behat\Mink\Mink; use Behat\Mink\Mink;
use Behat\Testwork\ServiceContainer\Exception\ProcessingException; use Behat\Testwork\ServiceContainer\Exception\ProcessingException;
use Behat\Testwork\Suite\Exception\SuiteConfigurationException;
use Behat\Testwork\Suite\Suite;
use PhpSpec\ObjectBehavior; use PhpSpec\ObjectBehavior;
class SessionsListenerSpec extends ObjectBehavior class SessionsListenerSpec extends ObjectBehavior
{ {
function let(Mink $mink, ScenarioTested $event, FeatureNode $feature, ScenarioNode $scenario) function let(Mink $mink, ScenarioTested $event, FeatureNode $feature, ScenarioNode $scenario, Suite $suite)
{ {
$this->beConstructedWith($mink, 'goutte', 'selenium2'); $this->beConstructedWith($mink, 'goutte', 'selenium2', array('selenium2', 'sahi'));
$event->getSuite()->willReturn($suite);
$event->getFeature()->willReturn($feature); $event->getFeature()->willReturn($feature);
$event->getScenario()->willReturn($scenario); $event->getScenario()->willReturn($scenario);
$suite->hasSetting('mink_session')->willReturn(false);
$suite->getName()->willReturn('default');
$feature->hasTag('insulated')->willReturn(false); $feature->hasTag('insulated')->willReturn(false);
$feature->getTags()->willReturn(array()); $feature->getTags()->willReturn(array());
$scenario->hasTag('insulated')->willReturn(false); $scenario->hasTag('insulated')->willReturn(false);
@@ -37,8 +43,29 @@ class SessionsListenerSpec extends ObjectBehavior
$this->prepareDefaultMinkSession($event); $this->prepareDefaultMinkSession($event);
} }
function it_switches_to_the_javascript_session_for_tagged_scenarios($event, $mink, $scenario) function it_supports_changing_the_default_session_per_suite($event, $mink, $suite)
{ {
$suite->hasSetting('mink_session')->willReturn(true);
$suite->getSetting('mink_session')->willReturn('test');
$mink->resetSessions()->shouldBeCalled();
$mink->setDefaultSessionName('test')->shouldBeCalled();
$this->prepareDefaultMinkSession($event);
}
function it_fails_for_non_string_default_suite_session($event, $suite)
{
$suite->hasSetting('mink_session')->willReturn(true);
$suite->getSetting('mink_session')->willReturn(array());
$this->shouldThrow(new SuiteConfigurationException('`mink_session` setting of the "default" suite is expected to be a string, array given.', 'default'))
->duringPrepareDefaultMinkSession($event);
}
function it_switches_to_the_javascript_session_for_tagged_scenarios($event, $mink, $scenario, $suite)
{
$suite->hasSetting('mink_javascript_session')->willReturn(false);
$scenario->getTags()->willReturn(array('javascript')); $scenario->getTags()->willReturn(array('javascript'));
$mink->resetSessions()->shouldBeCalled(); $mink->resetSessions()->shouldBeCalled();
$mink->setDefaultSessionName('selenium2')->shouldBeCalled(); $mink->setDefaultSessionName('selenium2')->shouldBeCalled();
@@ -46,8 +73,9 @@ class SessionsListenerSpec extends ObjectBehavior
$this->prepareDefaultMinkSession($event); $this->prepareDefaultMinkSession($event);
} }
function it_switches_to_the_javascript_session_for_tagged_features($event, $mink, $feature) function it_switches_to_the_javascript_session_for_tagged_features($event, $mink, $feature, $suite)
{ {
$suite->hasSetting('mink_javascript_session')->willReturn(false);
$feature->getTags()->willReturn(array('javascript')); $feature->getTags()->willReturn(array('javascript'));
$mink->resetSessions()->shouldBeCalled(); $mink->resetSessions()->shouldBeCalled();
$mink->setDefaultSessionName('selenium2')->shouldBeCalled(); $mink->setDefaultSessionName('selenium2')->shouldBeCalled();
@@ -55,8 +83,43 @@ class SessionsListenerSpec extends ObjectBehavior
$this->prepareDefaultMinkSession($event); $this->prepareDefaultMinkSession($event);
} }
function it_fails_when_the_javascript_session_is_used_but_not_defined($event, $mink, $feature) function it_supports_changing_the_default_javascript_session_per_suite($event, $mink, $scenario, $suite)
{ {
$suite->hasSetting('mink_javascript_session')->willReturn(true);
$suite->getSetting('mink_javascript_session')->willReturn('sahi');
$scenario->getTags()->willReturn(array('javascript'));
$mink->resetSessions()->shouldBeCalled();
$mink->setDefaultSessionName('sahi')->shouldBeCalled();
$this->prepareDefaultMinkSession($event);
}
function it_fails_for_non_string_javascript_suite_session($event, $scenario, $suite)
{
$suite->hasSetting('mink_javascript_session')->willReturn(true);
$suite->getSetting('mink_javascript_session')->willReturn(array());
$scenario->getTags()->willReturn(array('javascript'));
$this->shouldThrow(new SuiteConfigurationException('`mink_javascript_session` setting of the "default" suite is expected to be a string, array given.', 'default'))
->duringPrepareDefaultMinkSession($event);
}
function it_fails_for_invalid_javascript_suite_session($event, $scenario, $suite)
{
$suite->hasSetting('mink_javascript_session')->willReturn(true);
$suite->getSetting('mink_javascript_session')->willReturn('test');
$scenario->getTags()->willReturn(array('javascript'));
$this->shouldThrow(new SuiteConfigurationException('`mink_javascript_session` setting of the "default" suite is not a javascript session. test given but expected one of selenium2, sahi.', 'default'))
->duringPrepareDefaultMinkSession($event);
}
function it_fails_when_the_javascript_session_is_used_but_not_defined($event, $mink, $feature, $suite)
{
$suite->hasSetting('mink_javascript_session')->willReturn(false);
$this->beConstructedWith($mink, 'goutte', null); $this->beConstructedWith($mink, 'goutte', null);
$feature->getTags()->willReturn(array('javascript')); $feature->getTags()->willReturn(array('javascript'));
@@ -73,8 +136,9 @@ class SessionsListenerSpec extends ObjectBehavior
$this->prepareDefaultMinkSession($event); $this->prepareDefaultMinkSession($event);
} }
function it_prefers_the_scenario_over_the_feature($event, $mink, $scenario, $feature) function it_prefers_the_scenario_over_the_feature($event, $mink, $scenario, $feature, $suite)
{ {
$suite->hasSetting('mink_javascript_session')->willReturn(false);
$scenario->getTags()->willReturn(array('mink:test')); $scenario->getTags()->willReturn(array('mink:test'));
$feature->getTags()->willReturn(array('javascript')); $feature->getTags()->willReturn(array('javascript'));
$mink->resetSessions()->shouldBeCalled(); $mink->resetSessions()->shouldBeCalled();

View File

@@ -255,6 +255,7 @@ class Extension implements ExtensionInterface
$container->setParameter('mink.default_session', $defaultSession); $container->setParameter('mink.default_session', $defaultSession);
$container->setParameter('mink.javascript_session', $javascriptSession); $container->setParameter('mink.javascript_session', $javascriptSession);
$container->setParameter('mink.available_javascript_sessions', $javascriptSessions);
} }
private function loadSessionsListener(ContainerBuilder $container) private function loadSessionsListener(ContainerBuilder $container)
@@ -263,6 +264,7 @@ class Extension implements ExtensionInterface
new Reference(self::MINK_ID), new Reference(self::MINK_ID),
'%mink.default_session%', '%mink.default_session%',
'%mink.javascript_session%', '%mink.javascript_session%',
'%mink.available_javascript_sessions%',
)); ));
$definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG, array('priority' => 0)); $definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG, array('priority' => 0));
$container->setDefinition('mink.listener.sessions', $definition); $container->setDefinition('mink.listener.sessions', $definition);

View File

@@ -16,6 +16,8 @@ use Behat\Behat\EventDispatcher\Event\ScenarioTested;
use Behat\Mink\Mink; use Behat\Mink\Mink;
use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted; use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted;
use Behat\Testwork\ServiceContainer\Exception\ProcessingException; use Behat\Testwork\ServiceContainer\Exception\ProcessingException;
use Behat\Testwork\Suite\Exception\SuiteConfigurationException;
use Behat\Testwork\Suite\Suite;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/** /**
@@ -30,18 +32,25 @@ class SessionsListener implements EventSubscriberInterface
private $defaultSession; private $defaultSession;
private $javascriptSession; private $javascriptSession;
/**
* @var string[] The available javascript sessions
*/
private $availableJavascriptSessions;
/** /**
* Initializes initializer. * Initializes initializer.
* *
* @param Mink $mink * @param Mink $mink
* @param string $defaultSession * @param string $defaultSession
* @param string|null $javascriptSession * @param string|null $javascriptSession
* @param string[] $availableJavascriptSessions
*/ */
public function __construct(Mink $mink, $defaultSession, $javascriptSession) public function __construct(Mink $mink, $defaultSession, $javascriptSession, array $availableJavascriptSessions = array())
{ {
$this->mink = $mink; $this->mink = $mink;
$this->defaultSession = $defaultSession; $this->defaultSession = $defaultSession;
$this->javascriptSession = $javascriptSession; $this->javascriptSession = $javascriptSession;
$this->availableJavascriptSessions = $availableJavascriptSessions;
} }
/** /**
@@ -75,20 +84,20 @@ class SessionsListener implements EventSubscriberInterface
{ {
$scenario = $event->getScenario(); $scenario = $event->getScenario();
$feature = $event->getFeature(); $feature = $event->getFeature();
$session = $this->defaultSession; $session = null;
foreach (array_merge($feature->getTags(), $scenario->getTags()) as $tag) { foreach (array_merge($feature->getTags(), $scenario->getTags()) as $tag) {
if ('javascript' === $tag) { if ('javascript' === $tag) {
if (null === $this->javascriptSession) { $session = $this->getJavascriptSession($event->getSuite());
throw new ProcessingException('The @javascript tag cannot be used without enabling a javascript session');
}
$session = $this->javascriptSession;
} elseif (preg_match('/^mink\:(.+)/', $tag, $matches)) { } elseif (preg_match('/^mink\:(.+)/', $tag, $matches)) {
$session = $matches[1]; $session = $matches[1];
} }
} }
if (null === $session) {
$session = $this->getDefaultSession($event->getSuite());
}
if ($scenario->hasTag('insulated') || $feature->hasTag('insulated')) { if ($scenario->hasTag('insulated') || $feature->hasTag('insulated')) {
$this->mink->stopSessions(); $this->mink->stopSessions();
} else { } else {
@@ -105,4 +114,64 @@ class SessionsListener implements EventSubscriberInterface
{ {
$this->mink->stopSessions(); $this->mink->stopSessions();
} }
private function getDefaultSession(Suite $suite)
{
if (!$suite->hasSetting('mink_session')) {
return $this->defaultSession;
}
$session = $suite->getSetting('mink_session');
if (!is_string($session)) {
throw new SuiteConfigurationException(
sprintf(
'`mink_session` setting of the "%s" suite is expected to be a string, %s given.',
$suite->getName(),
gettype($session)
),
$suite->getName()
);
}
return $session;
}
private function getJavascriptSession(Suite $suite)
{
if (!$suite->hasSetting('mink_javascript_session')) {
if (null === $this->javascriptSession) {
throw new ProcessingException('The @javascript tag cannot be used without enabling a javascript session');
}
return $this->javascriptSession;
}
$session = $suite->getSetting('mink_javascript_session');
if (!is_string($session)) {
throw new SuiteConfigurationException(
sprintf(
'`mink_javascript_session` setting of the "%s" suite is expected to be a string, %s given.',
$suite->getName(),
gettype($session)
),
$suite->getName()
);
}
if (!in_array($session, $this->availableJavascriptSessions)) {
throw new SuiteConfigurationException(
sprintf(
'`mink_javascript_session` setting of the "%s" suite is not a javascript session. %s given but expected one of %s.',
$suite->getName(),
$session,
implode(', ', $this->availableJavascriptSessions)
),
$suite->getName()
);
}
return $session;
}
} }