getMainContext()->getSession($name); } /** * Wait until CMS loading overlay isn't present. * This is an addition to the "ajax steps" logic in * SilverStripe\BehatExtension\Context\BasicContext * which also waits for any ajax requests to finish before continuing. * * The check also applies in when not in the CMS, which is a structural issue: * Every step could cause the CMS to be loaded, and we don't know if we're in the * CMS UI until we run a check. * * Excluding scenarios with @modal tag is required, * because modal dialogs stop any JS interaction * * @AfterStep * @param AfterStepScope $event */ public function handleCmsLoadingAfterStep(AfterStepScope $event) { // Manually exclude @modal if ($this->stepHasTag($event, 'modal')) { return; } $timeoutMs = $this->getMainContext()->getAjaxTimeout(); $this->getSession()->wait( $timeoutMs, "(" . "document.getElementsByClassName('cms-content-loading-overlay').length +" . "document.getElementsByClassName('cms-loading-container').length" . ") == 0" ); } /** * @Then /^I should see the CMS$/ */ public function iShouldSeeTheCms() { $page = $this->getSession()->getPage(); $cms_element = $page->find('css', '.cms'); Assert::assertNotNull($cms_element, 'CMS not found'); } /** * @Then /^I should see a "([^"]*)" notice$/ * @deprecated 4.7.0 Use `iShouldSeeAToast` instead */ public function iShouldSeeANotice($notice) { $this->getMainContext()->assertElementContains('.toast, .notice-wrap', $notice); } /** * @Then /^I should see a "(.+)" (\w+) toast$/ */ public function iShouldSeeAToast($notice, $type) { $this->getMainContext()->assertElementContains('.toast--' . $type, $notice); } /** * @Then /^I should see a "(.+)" (\w+) toast with these actions: (.+)$/ */ public function iShouldSeeAToastWithAction($notice, $type, $actions) { $this->iShouldSeeAToast($notice, $type); $actions = explode(',', $actions); foreach ($actions as $order => $action) { $this->getMainContext()->assertElementContains( sprintf('.toast--%s .toast__action:nth-child(%s)', $type, $order+1), trim($action) ); } } /** * @param $action * @When /^I click the "(.*)" toast action$/ */ public function stepIClickTheToastAction($action) { $page = $this->getMainContext()->getSession()->getPage(); $toasts = $page->find('css', '.toasts'); Assert::assertNotNull($toasts, "We have a toast container"); $toastAction = $toasts->find('named', ['link_or_button', "'{$action}'"]); Assert::assertNotNull($toastAction, "We have a $action toast action"); $toastAction->click(); } /** * @Then /^I should see a "([^"]*)" message$/ */ public function iShouldSeeAMessage($message) { $page = $this->getMainContext()->getSession()->getPage(); if ($page->find('css', '.message')) { $this->getMainContext()->assertElementContains('.message', $message); } else { // Support for new Bootstrap alerts $this->getMainContext()->assertElementContains('.alert', $message); } } protected function getCmsTabsElement() { $this->getSession()->wait( 5000, "window.jQuery && window.jQuery('.cms-content-header-tabs').size() > 0" ); $page = $this->getSession()->getPage(); $cms_content_header_tabs = $page->find('css', '.cms-content-header-tabs'); Assert::assertNotNull($cms_content_header_tabs, 'CMS tabs not found'); return $cms_content_header_tabs; } protected function getCmsContentToolbarElement() { $this->getSession()->wait( 5000, "window.jQuery && window.jQuery('.cms-content-toolbar').size() > 0 " . "&& window.jQuery('.cms-content-toolbar').children().size() > 0" ); $page = $this->getSession()->getPage(); $cms_content_toolbar_element = $page->find('css', '.cms-content-toolbar'); Assert::assertNotNull($cms_content_toolbar_element, 'CMS content toolbar not found'); return $cms_content_toolbar_element; } protected function getCmsTreeElement() { $this->getSession()->wait( 5000, "window.jQuery && window.jQuery('.cms-tree').size() > 0" ); $page = $this->getSession()->getPage(); $cms_tree_element = $page->find('css', '.cms-tree'); Assert::assertNotNull($cms_tree_element, 'CMS tree not found'); return $cms_tree_element; } /** * @Given /^I should see a "([^"]*)" button in CMS Content Toolbar$/ */ public function iShouldSeeAButtonInCmsContentToolbar($text) { $cms_content_toolbar_element = $this->getCmsContentToolbarElement(); $element = $cms_content_toolbar_element->find('named', ['link_or_button', "'$text'"]); Assert::assertNotNull($element, sprintf('%s button not found', $text)); } /** * @When /^I should see "([^"]*)" in the tree$/ */ public function stepIShouldSeeInCmsTree($text) { // Wait until visible $cmsTreeElement = $this->getCmsTreeElement(); $element = $cmsTreeElement->find('named', ['content', "'$text'"]); Assert::assertNotNull($element, sprintf('%s not found', $text)); } /** * @When /^I should not see "([^"]*)" in the tree$/ */ public function stepIShouldNotSeeInCmsTree($text) { // Wait until not visible $cmsTreeElement = $this->getCmsTreeElement(); $element = $cmsTreeElement->find('named', ['content', "'$text'"]); Assert::assertNull($element, sprintf('%s found', $text)); } /** * @When /^I should (|not )see "([^"]*)" in the cms list$/ */ public function stepIShouldSeeInCmsList($negate, $text) { // Wait until visible $this->getSession()->wait( 5000, "document.querySelector('.cms-lists') !== null" ); $page = $this->getSession()->getPage(); $cmsListElement = $page->find('css', '.cms-list'); Assert::assertNotNull($cmsListElement, 'CMS list not found'); // Check text within this element $element = $cmsListElement->find('named', ['content', "'$text'"]); if (strstr($negate, 'not')) { Assert::assertNull($element, sprintf('Unexpected %s found in cms list', $text)); } else { Assert::assertNotNull($element, sprintf('Expected %s not found in cms list', $text)); } } /** * @When /^I should see a "([^"]*)" tab in the CMS content header tabs$/ */ public function stepIShouldSeeInCMSContentTabs($text) { // Wait until visible Assert::assertNotNull($this->getCmsTabElement($text), sprintf('%s content tab not found', $text)); } /** * Applies a specific action to an element * * @param NodeElement $element Element to act on * @param string $action Action, which may be one of 'hover', 'double click', 'right click', or 'left click' * The default 'click' behaves the same as left click */ protected function interactWithElement($element, $action = 'click') { switch ($action) { case 'hover': $element->mouseOver(); break; case 'double click': $element->doubleClick(); break; case 'right click': $element->rightClick(); break; case 'left click': case 'click': default: $element->click(); break; } } /** * @When /^I (?P(?:(?:double |right |left |)click)|hover) on "(?P[^"]*)" in the context menu/ */ public function stepIClickOnElementInTheContextMenu($method, $link) { $context = $this->getMainContext(); // Wait until context menu has appeared $this->getSession()->wait( 1000, "window.jQuery && window.jQuery('.jstree-apple-context').size() > 0" ); $regionObj = $context->getRegionObj('.jstree-apple-context'); Assert::assertNotNull($regionObj, "Context menu could not be found"); $linkObj = $regionObj->findLink($link); if (empty($linkObj)) { throw new \Exception(sprintf( 'The link "%s" was not found in the context menu on the page %s', $link, $this->getSession()->getCurrentUrl() )); } $this->interactWithElement($linkObj, $method); } /** * @When /^I (?P(?:(?:double |right |left |)click)|hover) on "(?P[^"]*)" in the tree$/ */ public function stepIClickOnElementInTheTree($method, $text) { $treeEl = $this->getCmsTreeElement(); $treeNode = $treeEl->findLink($text); Assert::assertNotNull($treeNode, sprintf('%s not found', $text)); $this->interactWithElement($treeNode, $method); } /** * @When /^I (?P(?:(?:double |right |left |)click)|hover) on "(?P[^"]*)" in the header tabs$/ */ public function stepIClickOnElementInTheHeaderTabs($method, $text) { $tabsNode = $this->getCmsTabElement($text); Assert::assertNotNull($tabsNode, sprintf('%s not found', $text)); $this->interactWithElement($tabsNode, $method); } /** * @Then the :text header tab should be active */ public function theHeaderTabShouldBeActive($text) { $element = $this->getCmsTabElement($text); Assert::assertNotNull($element); Assert::assertTrue($element->hasClass('active')); } /** * @Then the :text header tab should not be active */ public function theHeaderTabShouldNotBeActive($text) { $element = $this->getCmsTabElement($text); Assert::assertNotNull($element); Assert::assertFalse($element->hasClass('active')); } /** * @return NodeElement */ protected function getCmsTabElement($text) { return $this->getCmsTabsElement()->findLink($text); } /** * @When /^I expand the "([^"]*)" CMS Panel$/ */ public function iExpandTheCmsPanel() { //Tries to find the first visiable toggle in the page $page = $this->getSession()->getPage(); $toggle_elements = $page->findAll('css', '.toggle-expand'); Assert::assertNotNull($toggle_elements, 'Panel toggle not found'); /** @var NodeElement $toggle */ foreach ($toggle_elements as $toggle) { if ($toggle->isVisible()) { $toggle->click(); } } } /** * @When /^I (expand|collapse) the content filters$/ */ public function iExpandTheContentFilters($action) { $page = $this->getSession()->getPage(); $filterButton = $page->find('css', '.search-box__filter-trigger'); Assert::assertNotNull($filterButton, sprintf('Filter button link not found')); $filterButtonExpanded = $filterButton->getAttribute('aria-expanded'); if ($action === 'expand') { if ($filterButtonExpanded === false) { $filterButton->click(); } } else { if ($filterButtonExpanded === true) { $filterButton->click(); } } $this->getSession()->wait(2000, 'window.jQuery(".cms-content-filters:animated").length === 0'); // If activating, wait until chosen is activated if ($action === 'expand') { $this->getSession()->wait( 2000, <<<'SCRIPT' (window.jQuery(".cms-content-filters select").length === 0) || (window.jQuery(".cms-content-filters select:visible.has-chosen").length > 0) SCRIPT ); } } /** * @Given /^I press the "([^"]*)" key in the "([^"]*)" field$/ */ public function iPressTheKeyInTheField($key, $field) { $this->getSession()->evaluateScript(sprintf( "jQuery('[name=\"%s\"]')[0].dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: \"%s\" })); jQuery('[name=\"%s\"]')[0].dispatchEvent(new KeyboardEvent('keyup', { bubbles: true, key: \"%s\" }));", $field, $key, $field, $key )); } /** * @When /^I (expand|collapse) "([^"]*)" in the tree$/ */ public function iExpandInTheTree($action, $nodeText) { //Tries to find the first visiable matched Node in the page $treeEl = $this->getCmsTreeElement(); $treeNode = $treeEl->findLink($nodeText); Assert::assertNotNull($treeNode, sprintf('%s link not found', $nodeText)); $cssIcon = $treeNode->getParent()->getAttribute("class"); if ($action == "expand") { //ensure it is collapsed if (false === strpos($cssIcon, 'jstree-open')) { $nodeIcon = $treeNode->getParent()->find('css', '.jstree-icon'); Assert::assertTrue($nodeIcon->isVisible(), "CMS node '$nodeText' not found"); $nodeIcon->click(); } } else { //ensure it is expanded if (false === strpos($cssIcon, 'jstree-closed')) { $nodeIcon = $treeNode->getParent()->find('css', '.jstree-icon'); Assert::assertTrue($nodeIcon->isVisible(), "CMS node '$nodeText' not found"); $nodeIcon->click(); } } } /** * @When /^I should (not |)see a "([^"]*)" CMS tab$/ */ public function iShouldSeeACmsTab($negate, $tab) { $this->getSession()->wait( 5000, "window.jQuery && window.jQuery('.ui-tabs-nav').size() > 0" ); $page = $this->getSession()->getPage(); $tabsets = $page->findAll('css', '.ui-tabs-nav'); Assert::assertNotNull($tabsets, 'CMS tabs not found'); $tab_element = null; /** @var NodeElement $tabset */ foreach ($tabsets as $tabset) { $tab_element = $tabset->find('named', ['link_or_button', "'$tab'"]); if ($tab_element) { break; } } if ($negate) { Assert::assertNull($tab_element, sprintf('%s tab found', $tab)); } else { Assert::assertNotNull($tab_element, sprintf('%s tab not found', $tab)); } } /** * @When /^I click the "([^"]*)" CMS tab$/ */ public function iClickTheCmsTab($tab) { $this->getSession()->wait( 5000, "window.jQuery && window.jQuery('.ui-tabs-nav').size() > 0" ); $page = $this->getSession()->getPage(); $tabsets = $page->findAll('css', '.ui-tabs-nav'); Assert::assertNotNull($tabsets, 'CMS tabs not found'); $tab_element = null; /** @var NodeElement $tabset */ foreach ($tabsets as $tabset) { if ($tab_element) { continue; } $tab_element = $tabset->find('named', ['link_or_button', "'$tab'"]); } Assert::assertNotNull($tab_element, sprintf('%s tab not found', $tab)); $tab_element->click(); } /** * @Then /^I can see the preview panel$/ */ public function iCanSeeThePreviewPanel() { $this->getMainContext()->assertElementOnPage('.cms-preview'); } /** * @Given /^the preview contains "([^"]*)"$/ */ public function thePreviewContains($content) { // see https://groups.google.com/forum/#!topic/behat/QNhOuGHKEWI $this->getSession()->switchToIFrame('cms-preview-iframe'); $this->getMainContext()->assertPageContainsText($content); $this->getSession()->switchToWindow(); } /** * @Given /^I set the CMS mode to "([^"]*)"$/ */ public function iSetTheCmsToMode($mode) { $this->theIFillInTheDropdownWith('Change view mode', $mode); sleep(1); } /** * @Given /^I wait for the preview to load$/ */ public function iWaitForThePreviewToLoad() { // see https://groups.google.com/forum/#!topic/behat/QNhOuGHKEWI $this->getSession()->switchToIFrame('cms-preview-iframe'); $this->getSession()->wait( 5000, "window.jQuery && !window.jQuery('iframe[name=cms-preview-iframe]').hasClass('loading')" ); $this->getSession()->switchToWindow(); } /** * @Given /^I switch the preview to "([^"]*)"$/ */ public function iSwitchThePreviewToMode($mode) { $controls = $this->getSession()->getPage()->find('css', '.cms-preview-controls'); Assert::assertNotNull($controls, 'Preview controls not found'); $label = $controls->find('xpath', sprintf( './/*[count(*)=0 and contains(text(), \'%s\')]', $mode )); Assert::assertNotNull($label, 'Preview mode switch not found'); $label->click(); $this->iWaitForThePreviewToLoad(); } /** * @Given /^the preview does not contain "([^"]*)"$/ */ public function thePreviewDoesNotContain($content) { // see https://groups.google.com/forum/#!topic/behat/QNhOuGHKEWI $this->getSession()->switchToIFrame('cms-preview-iframe'); $this->getMainContext()->assertPageNotContainsText($content); $this->getSession()->switchToWindow(); } /** * When I follow "my link" in preview * * @When /^(?:|I )follow "(?P(?:[^"]|\\")*)" in preview$/ */ public function clickLinkInPreview($link) { // TODO Remove once we have native support in Mink and php-webdriver, // see https://groups.google.com/forum/#!topic/behat/QNhOuGHKEWI $this->getSession()->switchToIFrame('cms-preview-iframe'); $link = $this->fixStepArgument($link); $this->getSession()->getPage()->clickLink($link); $this->getSession()->switchToWindow(); } /** * When I press "submit" in preview * * @When /^(?:|I )press "(?P