Chris@14: assertPageLoadComplete(); Chris@14: return $return; Chris@14: } Chris@14: Chris@14: /** Chris@14: * Assert the page is completely loaded. Chris@14: * Chris@14: * Ajax requests may happen after page loads. Also for users who have access Chris@14: * to contextual links the contextual link placeholders will be filled after Chris@14: * the page is received. Chris@14: */ Chris@14: protected function assertPageLoadComplete() { Chris@14: $this->assertSession()->assertWaitOnAjaxRequest(); Chris@14: if ($this->loggedInUser && $this->loggedInUser->hasPermission('access contextual links')) { Chris@14: $this->assertAllContextualLinksLoaded(); Chris@14: } Chris@14: } Chris@14: Chris@14: /** Chris@14: * Assert all contextual link areas have be loaded. Chris@14: * Chris@14: * Contextual link placeholders will be filled after Chris@14: * the page is received. Chris@14: * Chris@14: * @todo Move this function to https://www.drupal.org/node/2821724. Chris@14: */ Chris@14: protected function assertAllContextualLinksLoaded() { Chris@14: $this->waitForNoElement('[data-contextual-id]:empty'); Chris@14: } Chris@14: Chris@14: /** Chris@14: * Enables a theme. Chris@14: * Chris@14: * @param string $theme Chris@14: * The theme. Chris@14: */ Chris@14: protected function enableTheme($theme) { Chris@14: // Enable the theme. Chris@14: \Drupal::service('theme_installer')->install([$theme]); Chris@14: $theme_config = \Drupal::configFactory()->getEditable('system.theme'); Chris@14: $theme_config->set('default', $theme); Chris@14: $theme_config->save(); Chris@14: } Chris@14: Chris@14: /** Chris@14: * Waits for off-canvas dialog to open. Chris@17: * Chris@17: * @param string $position Chris@17: * The position of the dialog. Chris@17: * Chris@17: * @throws \Behat\Mink\Exception\ElementNotFoundException Chris@14: */ Chris@17: protected function waitForOffCanvasToOpen($position = 'side') { Chris@14: $web_assert = $this->assertSession(); Chris@14: // Wait just slightly longer than the off-canvas dialog CSS animation. Chris@14: // @see core/misc/dialog/off-canvas.motion.css Chris@14: $this->getSession()->wait(800); Chris@14: $web_assert->assertWaitOnAjaxRequest(); Chris@14: $this->assertElementVisibleAfterWait('css', '#drupal-off-canvas'); Chris@17: // Check that the canvas is positioned on the side. Chris@17: $web_assert->elementExists('css', '.ui-dialog-position-' . $position); Chris@14: } Chris@14: Chris@14: /** Chris@14: * Waits for off-canvas dialog to close. Chris@14: */ Chris@14: protected function waitForOffCanvasToClose() { Chris@14: $this->waitForNoElement('#drupal-off-canvas'); Chris@14: } Chris@14: Chris@14: /** Chris@14: * Gets the off-canvas dialog element. Chris@14: * Chris@14: * @return \Behat\Mink\Element\NodeElement|null Chris@14: */ Chris@14: protected function getOffCanvasDialog() { Chris@14: $off_canvas_dialog = $this->getSession()->getPage()->find('css', '.ui-dialog[aria-describedby="drupal-off-canvas"]'); Chris@14: $this->assertEquals(FALSE, empty($off_canvas_dialog), 'The off-canvas dialog was found.'); Chris@14: return $off_canvas_dialog; Chris@14: } Chris@14: Chris@14: /** Chris@14: * Waits for an element to be removed from the page. Chris@14: * Chris@14: * @param string $selector Chris@14: * CSS selector. Chris@14: * @param int $timeout Chris@14: * (optional) Timeout in milliseconds, defaults to 10000. Chris@14: * Chris@14: * @todo Remove in https://www.drupal.org/node/2892440. Chris@14: */ Chris@14: protected function waitForNoElement($selector, $timeout = 10000) { Chris@17: Chris@17: $start = microtime(TRUE); Chris@17: $end = $start + ($timeout / 1000); Chris@17: $page = $this->getSession()->getPage(); Chris@17: Chris@17: do { Chris@17: $result = $page->find('css', $selector); Chris@17: Chris@17: if (empty($result)) { Chris@17: return; Chris@17: } Chris@17: Chris@17: usleep(100000); Chris@17: } while (microtime(TRUE) < $end); Chris@17: Chris@17: $this->assertEmpty($result, 'Element was not on the page after wait.'); Chris@14: } Chris@14: Chris@14: /** Chris@14: * Get themes to test. Chris@14: * Chris@14: * @return string[] Chris@14: * Theme names to test. Chris@14: */ Chris@14: protected function getTestThemes() { Chris@14: return ['bartik', 'stark', 'classy', 'stable', 'seven']; Chris@14: } Chris@14: Chris@14: /** Chris@14: * Asserts the specified selector is visible after a wait. Chris@14: * Chris@14: * @param string $selector Chris@14: * The selector engine name. See ElementInterface::findAll() for the Chris@14: * supported selectors. Chris@14: * @param string|array $locator Chris@14: * The selector locator. Chris@14: * @param int $timeout Chris@14: * (Optional) Timeout in milliseconds, defaults to 10000. Chris@14: */ Chris@14: protected function assertElementVisibleAfterWait($selector, $locator, $timeout = 10000) { Chris@17: $this->assertSession()->assertWaitOnAjaxRequest(); Chris@14: $this->assertNotEmpty($this->assertSession()->waitForElementVisible($selector, $locator, $timeout)); Chris@14: } Chris@14: Chris@17: /** Chris@17: * Dataprovider that returns theme name as the sole argument. Chris@17: */ Chris@17: public function themeDataProvider() { Chris@17: $themes = $this->getTestThemes(); Chris@17: $data = []; Chris@17: foreach ($themes as $theme) { Chris@17: $data[$theme] = [ Chris@17: $theme, Chris@17: ]; Chris@17: } Chris@17: return $data; Chris@17: } Chris@17: Chris@14: }