From 888ab86a72135f522541278c268ad8e5ecb43c46 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Sat, 26 Apr 2014 20:23:19 +0200 Subject: [PATCH] Added the possibility to define the default session per suite --- doc/index.rst | 33 +++++--- .../Listener/SessionsListenerSpec.php | 76 +++++++++++++++-- src/Behat/MinkExtension/Extension.php | 2 + .../Listener/SessionsListener.php | 83 +++++++++++++++++-- 4 files changed, 170 insertions(+), 24 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 2ffc56b..dfa5ce0 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -144,18 +144,18 @@ Sessions You can register as many Mink session as you want. For each session, you will need to choose the driver you want to use. - .. code-block:: yaml +.. code-block:: yaml - default: - extensions: - Behat\MinkExtension\Extension: - sessions: - first_session: - selenium2: ~ - second_session: - goutte: ~ - third_session: - selenium2: ~ + default: + extensions: + Behat\MinkExtension\Extension: + sessions: + first_session: + selenium2: ~ + second_session: + goutte: ~ + third_session: + selenium2: ~ MinkExtension will set the default Mink session for each scenario based on 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; * 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 session using a javascript driver in the order of the configuration (it would be ``first_session`` in the example above as ``selenium2`` supports Javascript). diff --git a/spec/Behat/MinkExtension/Listener/SessionsListenerSpec.php b/spec/Behat/MinkExtension/Listener/SessionsListenerSpec.php index aedbe43..be72e21 100644 --- a/spec/Behat/MinkExtension/Listener/SessionsListenerSpec.php +++ b/spec/Behat/MinkExtension/Listener/SessionsListenerSpec.php @@ -7,17 +7,23 @@ use Behat\Gherkin\Node\FeatureNode; use Behat\Gherkin\Node\ScenarioNode; use Behat\Mink\Mink; use Behat\Testwork\ServiceContainer\Exception\ProcessingException; +use Behat\Testwork\Suite\Exception\SuiteConfigurationException; +use Behat\Testwork\Suite\Suite; use PhpSpec\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->getScenario()->willReturn($scenario); + $suite->hasSetting('mink_session')->willReturn(false); + $suite->getName()->willReturn('default'); + $feature->hasTag('insulated')->willReturn(false); $feature->getTags()->willReturn(array()); $scenario->hasTag('insulated')->willReturn(false); @@ -37,8 +43,29 @@ class SessionsListenerSpec extends ObjectBehavior $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')); $mink->resetSessions()->shouldBeCalled(); $mink->setDefaultSessionName('selenium2')->shouldBeCalled(); @@ -46,8 +73,9 @@ class SessionsListenerSpec extends ObjectBehavior $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')); $mink->resetSessions()->shouldBeCalled(); $mink->setDefaultSessionName('selenium2')->shouldBeCalled(); @@ -55,8 +83,43 @@ class SessionsListenerSpec extends ObjectBehavior $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); $feature->getTags()->willReturn(array('javascript')); @@ -73,8 +136,9 @@ class SessionsListenerSpec extends ObjectBehavior $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')); $feature->getTags()->willReturn(array('javascript')); $mink->resetSessions()->shouldBeCalled(); diff --git a/src/Behat/MinkExtension/Extension.php b/src/Behat/MinkExtension/Extension.php index a2fba1f..41711c9 100644 --- a/src/Behat/MinkExtension/Extension.php +++ b/src/Behat/MinkExtension/Extension.php @@ -255,6 +255,7 @@ class Extension implements ExtensionInterface $container->setParameter('mink.default_session', $defaultSession); $container->setParameter('mink.javascript_session', $javascriptSession); + $container->setParameter('mink.available_javascript_sessions', $javascriptSessions); } private function loadSessionsListener(ContainerBuilder $container) @@ -263,6 +264,7 @@ class Extension implements ExtensionInterface new Reference(self::MINK_ID), '%mink.default_session%', '%mink.javascript_session%', + '%mink.available_javascript_sessions%', )); $definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG, array('priority' => 0)); $container->setDefinition('mink.listener.sessions', $definition); diff --git a/src/Behat/MinkExtension/Listener/SessionsListener.php b/src/Behat/MinkExtension/Listener/SessionsListener.php index f372918..7a18cc9 100644 --- a/src/Behat/MinkExtension/Listener/SessionsListener.php +++ b/src/Behat/MinkExtension/Listener/SessionsListener.php @@ -16,6 +16,8 @@ use Behat\Behat\EventDispatcher\Event\ScenarioTested; use Behat\Mink\Mink; use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted; use Behat\Testwork\ServiceContainer\Exception\ProcessingException; +use Behat\Testwork\Suite\Exception\SuiteConfigurationException; +use Behat\Testwork\Suite\Suite; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -30,18 +32,25 @@ class SessionsListener implements EventSubscriberInterface private $defaultSession; private $javascriptSession; + /** + * @var string[] The available javascript sessions + */ + private $availableJavascriptSessions; + /** * Initializes initializer. * * @param Mink $mink * @param string $defaultSession * @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->defaultSession = $defaultSession; $this->javascriptSession = $javascriptSession; + $this->availableJavascriptSessions = $availableJavascriptSessions; } /** @@ -75,20 +84,20 @@ class SessionsListener implements EventSubscriberInterface { $scenario = $event->getScenario(); $feature = $event->getFeature(); - $session = $this->defaultSession; + $session = null; foreach (array_merge($feature->getTags(), $scenario->getTags()) as $tag) { if ('javascript' === $tag) { - if (null === $this->javascriptSession) { - throw new ProcessingException('The @javascript tag cannot be used without enabling a javascript session'); - } - - $session = $this->javascriptSession; + $session = $this->getJavascriptSession($event->getSuite()); } elseif (preg_match('/^mink\:(.+)/', $tag, $matches)) { $session = $matches[1]; } } + if (null === $session) { + $session = $this->getDefaultSession($event->getSuite()); + } + if ($scenario->hasTag('insulated') || $feature->hasTag('insulated')) { $this->mink->stopSessions(); } else { @@ -105,4 +114,64 @@ class SessionsListener implements EventSubscriberInterface { $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; + } }