layout_paragraphs-1.0.x-dev/tests/src/FunctionalJavascript/BuilderTestBase.php
tests/src/FunctionalJavascript/BuilderTestBase.php
<?php
declare(strict_types=1);
namespace Drupal\Tests\layout_paragraphs\FunctionalJavascript;
use Behat\Mink\Exception\ExpectationException;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\Tests\paragraphs\FunctionalJavascript\ParagraphsTestBaseTrait;
/**
* Base class for Layout Paragraphs Builder tests.
*
* @group layout_paragraphs
*/
abstract class BuilderTestBase extends WebDriverTestBase {
use ParagraphsTestBaseTrait;
/**
* {@inheritdoc}
*/
protected static $modules = [
'layout_paragraphs',
'paragraphs',
'node',
'field',
'field_ui',
'block',
'paragraphs_test',
];
/**
* List of admin permissions.
*
* @var array
*/
protected $adminPermissions = [
'administer site configuration',
'administer node fields',
'administer node display',
'administer paragraphs types',
];
/**
* List of content creation related permissions.
*
* @var array
*/
protected $contentPermissions = [
'create page content',
'edit own page content',
];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->addParagraphsType('section');
$this->addParagraphsType('text');
$this->addFieldtoParagraphType('text', 'field_text', 'text');
$this->loginWithPermissions($this->adminPermissions);
// Enable Layout Paragraphs behavior for section paragraph type.
$this->drupalGet('admin/structure/paragraphs_type/section');
$this->submitForm([
'behavior_plugins[layout_paragraphs][enabled]' => TRUE,
'behavior_plugins[layout_paragraphs][settings][available_layouts][]' => [
'layout_onecol',
'layout_twocol',
'layout_threecol_25_50_25',
'layout_threecol_33_34_33',
],
], 'Save');
$this->assertSession()->pageTextContains('Saved the section Paragraphs type.');
$this->addLayoutParagraphedContentType('page', 'field_content');
$this->drupalGet('admin/structure/paragraphs_type/section');
$this->drupalLogout();
}
/**
* Adds a content type with a layout paragraphs field.
*
* @param string $type_name
* The name of the content type.
* @param string $paragraph_field
* The name of the paragraphs reference field.
*/
protected function addLayoutParagraphedContentType($type_name, $paragraph_field) {
$this->addParagraphedContentType($type_name, $paragraph_field, 'layout_paragraphs');
// Add "section" and "text" paragraph types to the "page" content type.
$this->drupalGet('admin/structure/types/manage/page/fields/node.' . $type_name . '.' . $paragraph_field);
// Enables all paragraph types.
$this->submitForm([
'settings[handler_settings][negate]' => '1',
], 'Save settings');
// Use "Layout Paragraphs" formatter for the content field.
$this->drupalGet('admin/structure/types/manage/' . $type_name . '/display');
$page = $this->getSession()->getPage();
$page->selectFieldOption('fields[' . $paragraph_field . '][type]', 'layout_paragraphs');
$this->assertSession()->assertWaitOnAjaxRequest(10000, 'Unable to choose layout paragraphs (fields[' . $paragraph_field . '][type]) field formatter.');
$this->submitForm([], 'Save');
}
/**
* Uses Javascript to make a DOM element visible.
*
* @param string $selector
* A css selector.
*/
protected function forceVisible($selector) {
$this->getSession()->executeScript("jQuery('{$selector}').css({display:'inline-block', opacity:1, visibility: 'visible'});");
}
/**
* Uses Javascript to hide a DOM element.
*
* @param string $selector
* A css selector.
*/
protected function forceHidden($selector) {
$this->getSession()->executeScript("jQuery('{$selector}').css({display:'none', opacity:0, visibility: 'hidden'});");
}
/**
* Inserts a text component by clicking the "+" button.
*
* @param string $text
* The text for the component's field_text value.
* @param string $css_selector
* A css selector targeting the "+" button.
*/
protected function addTextComponent($text, $css_selector) {
$page = $this->getSession()->getPage();
// Add a text item to first column.
// Because there are only two component types and sections cannot
// be nested, this will load the text component form directly.
$button = $page->find('css', $css_selector);
$button->click();
$this->assertSession()->assertWaitOnAjaxRequest();
$title = $page->find('css', '.ui-dialog-title');
if ($title->getText() == 'Choose a component') {
$page->clickLink('text');
$this->assertSession()->assertWaitOnAjaxRequest();
}
$dialog = $page->find('css', '.lpb-dialog');
$style = $dialog->getAttribute('style');
if (strpos($style, 'width: 90%;') === FALSE || strpos($style, 'height: auto;') === FALSE) {
throw new ExpectationException('Incorrect dialog width or height settings', $this->getSession()->getDriver());
}
$this->assertSession()->pageTextContains('field_text');
$page->fillField('field_text[0][value]', $text);
// Force show the hidden submit button so we can click it.
$this->getSession()->executeScript("jQuery('.lpb-btn--save').attr('style', '');");
$button = $this->assertSession()->waitForElementVisible('css', ".lpb-btn--save");
$button->press();
$this->assertSession()->assertWaitOnAjaxRequest();
$this->assertSession()->pageTextContains($text);
}
/**
* Inserts a text component by clicking the "+" button and choosing "section".
*
* @param int $columns_choice
* Which column option to choose.
* @param string $css_selector
* A css selector targeting the "+" button.
*/
protected function addSectionComponent(int $columns_choice, $css_selector) {
$page = $this->getSession()->getPage();
// Click the Add Component button.
$page->find('css', $css_selector)->click();
$this->assertNotEmpty($this->assertSession()->waitForText('Choose a component'));
// Add a section.
$page->clickLink('section');
$this->assertNotEmpty($this->assertSession()->waitForText('Create new section'));
// Choose a three-column layout.
$elements = $page->findAll('css', '.layout-select__item label.option');
$elements[$columns_choice]->click();
$this->assertNotEmpty($this->assertSession()->waitForText('Choose a layout:'));
$this->getSession()->wait(1000);
// Save the layout.
$button = $page->find('css', 'button.lpb-btn--save');
$button->click();
// $this->assertSession()->assertWaitOnAjaxRequest();
$this->getSession()->wait(1000);
}
/**
* Creates a new user with provided permissions and logs them in.
*
* @param array $permissions
* An array of permissions.
*
* @return \Drupal\Core\Session\AccountInterface
* The user.
*/
protected function loginWithPermissions(array $permissions) {
$user = $this->drupalCreateUser($permissions);
$this->drupalLogin($user);
return $user;
}
/**
* {@inheritdoc}
*
* Added method with fixed return comment for IDE type hinting.
*
* @return \Drupal\FunctionalJavascriptTests\JSWebAssert
* A new JS web assert object.
*/
public function assertSession($name = '') {
$js_web_assert = parent::assertSession($name);
return $js_web_assert;
}
/**
* Asserts that provided strings appear on page in same order as in array.
*
* @param array $strings
* A list of strings in the order they are expected to appear.
* @param string $assert_message
* Message if assertion fails.
*/
protected function assertOrderOfStrings(array $strings, $assert_message = 'Strings are not in correct order.') {
$page = $this->getSession()->getPage();
$page_text = $page->getHtml();
$high_mark = -1;
foreach ($strings as $string) {
$this->assertSession()->pageTextContains($string);
$pos = strpos($page_text, $string);
if ($pos <= $high_mark) {
throw new ExpectationException($assert_message, $this->getSession()->getDriver());
}
$high_mark = $pos;
}
}
/**
* Simulates pressing a key with javascript.
*
* @param string $key_code
* The string key code (i.e. ArrowUp, Enter).
*/
protected function keyPress($key_code) {
$script = 'var e = new KeyboardEvent("keydown", {bubbles : true, cancelable : true, code: "' . $key_code . '"});
document.body.dispatchEvent(e);';
$this->getSession()->executeScript($script);
}
/**
* Enables the frontend builder formatter for a content type and field.
*/
protected function useFrontEndBuilderFormatter($type, $field) {
$this->loginWithPermissions($this->adminPermissions);
$this->drupalGet('admin/structure/types/manage/' . $type . '/display');
$page = $this->getSession()->getPage();
$page->selectFieldOption('fields[' . $field . '][type]', 'layout_paragraphs_builder');
$this->assertSession()->assertWaitOnAjaxRequest(10000, 'Unable to choose layout paragraphs builder (fields[' . $field . '][type]) field formatter.');
$this->submitForm([], 'Save');
$this->drupalLogout();
}
/**
* Enables the frontend editor.
*/
protected function enableFrontendBuilder() {
$this->forceVisible('.lpb-enable-button');
$this->getSession()->getPage()->find('css', '.lpb-enable-button')->click();
$this->assertSession()->assertWaitOnAjaxRequest();
$this->assertSession()->elementExists('css', '.layout-paragraphs-builder-form');
}
/**
* Save the frontend builder.
*/
protected function saveFrontendBuilder() {
$page = $this->getSession()->getPage();
$page->find('css', '.lpb-form__actions .button--primary')->click();
$this->assertSession()->assertWaitOnAjaxRequest();
}
/**
* Close the frontend builder.
*/
protected function closeFrontendBuilder() {
$page = $this->getSession()->getPage();
$page->find('css', '.lpb-form__actions .lpb-btn--cancel')->click();
$this->assertSession()->assertWaitOnAjaxRequest();
}
/**
* Save and close the frontend builder.
*/
protected function saveAndCloseFrontendBuilder() {
$this->saveFrontendBuilder();
$this->closeFrontendBuilder();
}
}
