context = $parameters; } /** * Get Mink session from MinkContext */ public function getSession($name = null) { return $this->getMainContext()->getSession($name); } /** * @AfterStep ~@modal * * Excluding scenarios with @modal tag is required, * because modal dialogs stop any JS interaction */ public function appendErrorHandlerBeforeStep(StepEvent $event) { $javascript = <<getSession()->executeScript($javascript); } /** * @AfterStep ~@modal * * Excluding scenarios with @modal tag is required, * because modal dialogs stop any JS interaction */ public function readErrorHandlerAfterStep(StepEvent $event) { $page = $this->getSession()->getPage(); $jserrors = $page->find('xpath', '//body[@data-jserrors]'); if (null !== $jserrors) { $this->takeScreenshot($event); file_put_contents('php://stderr', $jserrors->getAttribute('data-jserrors') . PHP_EOL); } $javascript = <<getSession()->executeScript($javascript); } /** * Hook into jQuery ajaxStart, ajaxSuccess and ajaxComplete events. * Prepare __ajaxStatus() functions and attach them to these handlers. * Event handlers are removed after one run. * * @BeforeStep */ public function handleAjaxBeforeStep(StepEvent $event) { $ajax_enabled_steps = $this->getMainContext()->getAjaxEnabledSteps(); $ajax_enabled_steps = implode('|', array_filter($ajax_enabled_steps)); if (empty($ajax_enabled_steps) || !preg_match('/(' . $ajax_enabled_steps . ')/i', $event->getStep()->getText())) { return; } $javascript = <<getSession()->executeScript($javascript); } /** * Wait for the __ajaxStatus()to return anything but 'waiting'. * Don't wait longer than 5 seconds. * * Don't unregister handler if we're dealing with modal windows * * @AfterStep ~@modal */ public function handleAjaxAfterStep(StepEvent $event) { $ajax_enabled_steps = $this->getMainContext()->getAjaxEnabledSteps(); $ajax_enabled_steps = implode('|', array_filter($ajax_enabled_steps)); if (empty($ajax_enabled_steps) || !preg_match('/(' . $ajax_enabled_steps . ')/i', $event->getStep()->getText())) { return; } $this->handleAjaxTimeout(); $javascript = <<getSession()->executeScript($javascript); } public function handleAjaxTimeout() { // Wait for an ajax request to complete, but only for a maximum of 5 seconds to avoid deadlocks $this->getSession()->wait(5000, "(typeof window.__ajaxStatus !== 'undefined' ? window.__ajaxStatus() : 'no ajax') !== 'waiting'" ); // wait additional 100ms to allow DOM to update $this->getSession()->wait(100); } /** * Take screenshot when step fails. * Works only with Selenium2Driver. * * @AfterStep */ public function takeScreenshotAfterFailedStep(StepEvent $event) { if (4 === $event->getResult()) { $this->takeScreenshot($event); } } public function takeScreenshot(StepEvent $event) { $driver = $this->getSession()->getDriver(); // quit silently when unsupported if (!($driver instanceof Selenium2Driver)) { return; } $parent = $event->getLogicalParent(); $feature = $parent->getFeature(); $step = $event->getStep(); $screenshot_path = null; if (isset($this->context['screenshot_path'])) { $screenshot_path = realpath($this->context['screenshot_path']); if (!$screenshot_path) { \Filesystem::makeFolder($this->context['screenshot_path']); $screenshot_path = realpath($this->context['screenshot_path']); } } if (!$screenshot_path) { $screenshot_path = realpath(sys_get_temp_dir()); } if (!file_exists($screenshot_path)) { file_put_contents('php://stderr', sprintf('"%s" is not valid directory and failed to create it' . PHP_EOL, $this->context['screenshot_path'])); return; } if (file_exists($screenshot_path) && !is_dir($screenshot_path)) { file_put_contents('php://stderr', sprintf('"%s" is not valid directory' . PHP_EOL, $this->context['screenshot_path'])); return; } if (file_exists($screenshot_path) && !is_writable($screenshot_path)) { file_put_contents('php://stderr', sprintf('"%s" directory is not writable' . PHP_EOL, $screenshot_path)); return; } $screenshot_path = sprintf('%s/%s_%d.png', $screenshot_path, basename($feature->getFile()), $step->getLine()); $screenshot = $driver->wdSession->screenshot(); file_put_contents($screenshot_path, base64_decode($screenshot)); file_put_contents('php://stderr', sprintf('Saving screenshot into %s' . PHP_EOL, $screenshot_path)); } /** * @Then /^I should be redirected to "([^"]+)"/ */ public function stepIShouldBeRedirectedTo($url) { if ($this->getMainContext()->canIntercept()) { $client = $this->getSession()->getDriver()->getClient(); $client->followRedirects(true); $client->followRedirect(); $url = $this->getMainContext()->joinUrlParts($this->context['base_url'], $url); assertTrue($this->getMainContext()->isCurrentUrlSimilarTo($url), sprintf('Current URL is not %s', $url)); } } /** * @Given /^I wait for ([\d\.]+) seconds$/ */ public function stepIWaitFor($secs) { $this->getSession()->wait((float)$secs*1000); } /** * @Given /^I press the "([^"]*)" button$/ */ public function stepIPressTheButton($button) { $page = $this->getSession()->getPage(); $button_element = $page->find('named', array('link_or_button', "'$button'")); assertNotNull($button_element, sprintf('%s button not found', $button)); $button_element->click(); } /** * @Given /^I click "([^"]*)" in the "([^"]*)" element$/ */ public function iClickInTheElement($text, $selector) { $page = $this->getSession()->getPage(); $parent_element = $page->find('css', $selector); assertNotNull($parent_element, sprintf('"%s" element not found', $selector)); $element = $parent_element->find('xpath', sprintf('//*[count(*)=0 and contains(.,"%s")]', $text)); assertNotNull($element, sprintf('"%s" not found', $text)); $element->click(); } /** * @Given /^I type "([^"]*)" into the dialog$/ */ public function iTypeIntoTheDialog($data) { $data = array( 'text' => $data, ); $this->getSession()->getDriver()->wdSession->postAlert_text($data); } /** * @Given /^I confirm the dialog$/ */ public function iConfirmTheDialog() { $this->getSession()->getDriver()->wdSession->accept_alert(); $this->handleAjaxTimeout(); } /** * @Given /^I dismiss the dialog$/ */ public function iDismissTheDialog() { $this->getSession()->getDriver()->wdSession->dismiss_alert(); $this->handleAjaxTimeout(); } /** * @Given /^(I attach the file .*) with HTML5$/ */ public function iAttachTheFileTo($step) { $this->getSession()->evaluateScript("jQuery('.ss-uploadfield-editandorganize').show()"); $this->getSession()->evaluateScript("jQuery('[name=\"AssetUploadField\"]').css({opacity:1,visibility:'visible',height:'1px',width:'1px'})"); $this->getSession()->evaluateScript("jQuery('[name=\"files[]\"]').css({opacity:1,visibility:'visible',height:'1px',width:'1px'})"); $this->getSession()->wait(1000); return new Step\Given($step); } }