diff --git a/README.md b/README.md index 68ce963..8e4e2fe 100755 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ activate `MinkExtension`: Usage ----- -After installing extension, there would be 3 usage options available for you: +After installing extension, there would be 4 usage options available for you: * Subcontexting/extending `Behat\MinkExtension\Context\RawMinkContext` in your feature suite. This will give you ability to use preconfigured `Mink` instance altogether with some @@ -66,6 +66,9 @@ After installing extension, there would be 3 usage options available for you: * Subcontexting/extending `Behat\MinkExtension\Context\MinkContext` in your feature suite. Exactly like previous option, but also provides lot of predefined step definitions out of the box. +* If you're on the php 5.4+, you can simply use `Behat\MinkExtension\Context\MinkDictionary` + trait inside your `FeatureContext` or any of its subcontexts. This trait will provide + all the needed methods, hooks and definitions for you to start. * Implementing `Behat\MinkExtension\Context\MinkAwareContextInterface` with your context or its subcontexts. This will give you more customization options. Also, you can use this mechanism on multiple @@ -97,6 +100,28 @@ class FeatureContext extends MinkContext } ``` +Dictionary usage example: + +``` php +getSession()->wait(5000, "$('.suggestions-results').children().length > 0"); + } +} +``` + Copyright --------- diff --git a/src/Behat/MinkExtension/Context/MinkAwareContextInitializer.php b/src/Behat/MinkExtension/Context/MinkAwareContextInitializer.php index 91d131a..d03eb39 100644 --- a/src/Behat/MinkExtension/Context/MinkAwareContextInitializer.php +++ b/src/Behat/MinkExtension/Context/MinkAwareContextInitializer.php @@ -47,7 +47,20 @@ class MinkAwareContextInitializer implements ContextInitializerInterface */ public function supports(ContextInterface $context) { - return $context instanceof MinkAwareContextInterface; + // if context/subcontext implements MinkAwareContextInterface + if ($context instanceof MinkAwareContextInterface) { + return true; + } + + // if context/subcontext uses MinkDictionary trait + $refl = new \ReflectionObject($context); + if (method_exists($refl, 'getTraitNames')) { + if (in_array('Behat\\MinkExtension\\Context\\MinkDictionary', $refl->getTraitNames())) { + return true; + } + } + + return false; } /** diff --git a/src/Behat/MinkExtension/Context/MinkContext.php b/src/Behat/MinkExtension/Context/MinkContext.php index 7c10a9a..3f871a6 100644 --- a/src/Behat/MinkExtension/Context/MinkContext.php +++ b/src/Behat/MinkExtension/Context/MinkContext.php @@ -4,7 +4,8 @@ namespace Behat\MinkExtension\Context; use Behat\Gherkin\Node\TableNode; -use Behat\Behat\Context\TranslatedContextInterface; +use Behat\Behat\Context\TranslatedContextInterface, + Behat\Behat\Event\ScenarioEvent; /* * This file is part of the Behat\MinkExtension. @@ -22,6 +23,31 @@ use Behat\Behat\Context\TranslatedContextInterface; */ class MinkContext extends RawMinkContext implements TranslatedContextInterface { + /** + * @BeforeScenario + */ + public function prepareMinkSessions($event) + { + $scenario = $event instanceof ScenarioEvent ? $event->getScenario() : $event->getOutline(); + $session = $this->getMinkParameter('default_session'); + + foreach ($scenario->getTags() as $tag) { + if ('javascript' === $tag) { + $session = $this->getMinkParameter('javascript_session'); + } elseif (preg_match('/^mink\:(.+)/', $tag, $matches)) { + $session = $matches[1]; + } + } + + if ($scenario->hasTag('insulated')) { + $this->getMink()->stopSessions(); + } else { + $this->getMink()->resetSessions(); + } + + $this->getMink()->setDefaultSessionName($session); + } + /** * Opens specified page. * @@ -165,8 +191,8 @@ class MinkContext extends RawMinkContext implements TranslatedContextInterface { $field = $this->fixStepArgument($field); - if (isset($this->minkParameters['files_path']) && $this->minkParameters['files_path']) { - $path = $this->minkParameters['files_path'].DIRECTORY_SEPARATOR.$path; + if ($this->getMinkParameter('files_path')) { + $path = $this->getMinkParameter('files_path').DIRECTORY_SEPARATOR.$path; } $this->getSession()->getPage()->attachFileToField($field, $path); @@ -392,13 +418,13 @@ class MinkContext extends RawMinkContext implements TranslatedContextInterface */ public function showLastResponse() { - if (null === $this->minkParameters['show_cmd']) { + if (null === $this->getMinkParameter('show_cmd')) { throw new \RuntimeException('Set "show_cmd" parameter in behat.yml to be able to open page in browser (ex.: "show_cmd: firefox %s")'); } - $filename = rtrim($this->minkParameters['show_tmp_dir'], DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.uniqid().'.html'; + $filename = rtrim($this->getMinkParameter('show_tmp_dir'), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.uniqid().'.html'; file_put_contents($filename, $this->getSession()->getPage()->getContent()); - system(sprintf($this->minkParameters['show_cmd'], escapeshellarg($filename))); + system(sprintf($this->getMinkParameter('show_cmd'), escapeshellarg($filename))); } /** @@ -407,6 +433,16 @@ class MinkContext extends RawMinkContext implements TranslatedContextInterface * @return array */ public function getTranslationResources() + { + return $this->getMinkTranslationResources(); + } + + /** + * Returns list of definition translation resources paths for this dictionary. + * + * @return array + */ + public function getMinkTranslationResources() { return glob(__DIR__.'/../../../../i18n/*.xliff'); } @@ -421,7 +457,7 @@ class MinkContext extends RawMinkContext implements TranslatedContextInterface */ protected function locatePath($path) { - $startUrl = rtrim($this->minkParameters['base_url'], '/') . '/'; + $startUrl = rtrim($this->getMinkParameter('base_url'), '/') . '/'; return 0 !== strpos($path, 'http') ? $startUrl . ltrim($path, '/') : $path; } diff --git a/src/Behat/MinkExtension/Context/MinkDictionary.php b/src/Behat/MinkExtension/Context/MinkDictionary.php new file mode 100644 index 0000000..971d25e --- /dev/null +++ b/src/Behat/MinkExtension/Context/MinkDictionary.php @@ -0,0 +1,546 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Mink steps dictionary for Behat BDD tool. + * + * @author Konstantin Kudryashov + */ +trait MinkDictionary +{ + private $mink; + private $minkParameters; + + /** + * Sets Mink instance. + * + * @param Mink $mink Mink session manager + */ + public function setMink(Mink $mink) + { + $this->mink = $mink; + } + + /** + * Returns Mink instance. + * + * @return Mink + */ + public function getMink() + { + return $this->mink; + } + + /** + * Sets parameters provided for Mink. + * + * @param array $parameters + */ + public function setMinkParameters(array $parameters) + { + $this->minkParameters = $parameters; + } + + /** + * Returns specific mink parameter. + * + * @param string $name + * + * @return mixed + */ + public function getMinkParameter($name) + { + return isset($this->minkParameters[$name]) ? $this->minkParameters[$name] : null; + } + + /** + * Returns Mink session. + * + * @param string|null $name name of the session OR active session will be used + * + * @return Session + */ + public function getSession($name = null) + { + return $this->getMink()->getSession($name); + } + + /** + * Returns Mink session assertion tool. + * + * @param string|null $name name of the session OR active session will be used + * + * @return WebAssert + */ + public function assertSession($name = null) + { + return $this->getMink()->assertSession($name); + } + + /** + * @BeforeScenario + */ + public function prepareMinkSessions($event) + { + $scenario = $event instanceof ScenarioEvent ? $event->getScenario() : $event->getOutline(); + $session = $this->getMinkParameter('default_session'); + + foreach ($scenario->getTags() as $tag) { + if ('javascript' === $tag) { + $session = $this->getMinkParameter('javascript_session'); + } elseif (preg_match('/^mink\:(.+)/', $tag, $matches)) { + $session = $matches[1]; + } + } + + if ($scenario->hasTag('insulated')) { + $this->getMink()->stopSessions(); + } else { + $this->getMink()->resetSessions(); + } + + $this->getMink()->setDefaultSessionName($session); + } + + /** + * Opens specified page. + * + * @Given /^(?:|I )am on "(?P[^"]+)"$/ + * @When /^(?:|I )go to "(?P[^"]+)"$/ + */ + public function visit($page) + { + $this->getSession()->visit($this->locatePath($page)); + } + + /** + * Reloads current page. + * + * @When /^(?:|I )reload the page$/ + */ + public function reload() + { + $this->getSession()->reload(); + } + + /** + * Moves backward one page in history. + * + * @When /^(?:|I )move backward one page$/ + */ + public function back() + { + $this->getSession()->back(); + } + + /** + * Moves forward one page in history + * + * @When /^(?:|I )move forward one page$/ + */ + public function forward() + { + $this->getSession()->forward(); + } + + /** + * Presses button with specified id|name|title|alt|value. + * + * @When /^(?:|I )press "(?P