Loading tests/src/FunctionalJavascript/IntegrationFunctionalTest.php 0 → 100644 +140 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\sam\FunctionalJavascript; /** * Tests the basic functionality of Simple Add More. * * @group sam */ class IntegrationFunctionalTest extends SamFunctionalJavascriptTestBase { /** * Tests the basic functionality of Simple Add More. */ public function testFormSimplification() { $assert_session = $this->assertSession(); $session = $this->getSession(); // Log in as admin. $this->adminUser = $this->drupalCreateUser([ 'access content', 'administer nodes', 'bypass node access', 'administer node display', 'administer display modes', ]); $this->drupalLogin($this->adminUser); // Nothing configured, by default we simplify the node form. $this->drupalGet("/node/add/{$this->nodeType->id()}"); $assert_session->pageTextContains("Create {$this->nodeType->label()}"); $field_widget = $assert_session->elementExists('css', "form .field--name-field-node__link"); // Only one empty element is visible. $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $value = $assert_session->elementExists('css', 'input[name="field_node__link[0][uri]"]', $rows[0]) ->getValue(); $this->assertEmpty($value); $this->assertFalse($rows[1]->isVisible()); $this->assertFalse($rows[2]->isVisible()); // We see how many more elements can be added. $message = '2 additional items can be added'; $assert_session->elementTextContains('css', '.field--name-field-node__link .sam-add-more-help', $message); // We can reveal one element at a time. $button = $assert_session->elementExists('css', '.sam-add-more-button', $field_widget); $button->press(); $session->wait(200); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $this->assertTrue($rows[1]->isVisible()); $this->assertFalse($rows[2]->isVisible()); // The message gets updated accordingly. $message = '1 additional item can be added'; $assert_session->elementTextContains('css', '.field--name-field-node__link .sam-add-more-help', $message); // Do it again. $button->press(); $session->wait(200); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $this->assertTrue($rows[1]->isVisible()); $this->assertTrue($rows[2]->isVisible()); // The button is hidden and no more messages are visible $button = $assert_session->elementExists('css', '.sam-add-more-button', $field_widget); $this->assertFalse($button->isVisible()); $message = 'can be added'; $assert_session->elementTextNotContains('css', '.field--name-field-node__link', $message); // If the field is not empty, no empty elements are shown. $node = $this->drupalCreateNode([ 'type' => $this->nodeType->id(), 'title' => 'Node with a link', 'field_node__link' => [ 'uri' => 'https://drupal.org', 'text' => 'Drupal dot org', ], ]); $this->drupalGet($node->toUrl('edit-form')); $field_widget = $assert_session->elementExists('css', "form .field--name-field-node__link"); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $value = $assert_session->elementExists('css', 'input[name="field_node__link[0][uri]"]', $rows[0]) ->getValue(); $this->assertNotEmpty($value); $this->assertFalse($rows[1]->isVisible()); $this->assertFalse($rows[2]->isVisible()); // We see how many more elements can be added. $message = '2 additional items can be added'; $assert_session->elementTextContains('css', '.field--name-field-node__link .sam-add-more-help', $message); // We can still reveal more elements. $button = $assert_session->elementExists('css', '.sam-add-more-button', $field_widget); $button->press(); $session->wait(200); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $this->assertTrue($rows[1]->isVisible()); $this->assertFalse($rows[2]->isVisible()); // Change the widget third-party settings and verify we skip simplifying. \Drupal::service('entity_display.repository') ->getFormDisplay('node', $this->nodeType->id(), 'default') ->setComponent('field_node__link', [ 'type' => 'link_default', 'third_party_settings' => [ 'sam' => ['skip_simplification' => TRUE], ], ]) ->save(); $this->drupalGet("/node/add/{$this->nodeType->id()}"); $assert_session->pageTextContains("Create {$this->nodeType->label()}"); $field_widget = $assert_session->elementExists('css', "form .field--name-field-node__link"); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $this->assertTrue($rows[1]->isVisible()); $this->assertTrue($rows[2]->isVisible()); // Switching it back simplifies again. \Drupal::service('entity_display.repository') ->getFormDisplay('node', $this->nodeType->id(), 'default') ->setComponent('field_node__link', [ 'type' => 'link_default', 'third_party_settings' => [ 'sam' => ['skip_simplification' => FALSE], ], ]) ->save(); $this->drupalGet("/node/add/{$this->nodeType->id()}"); $assert_session->pageTextContains("Create {$this->nodeType->label()}"); $field_widget = $assert_session->elementExists('css', "form .field--name-field-node__link"); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $this->assertFalse($rows[1]->isVisible()); $this->assertFalse($rows[2]->isVisible()); } } tests/src/FunctionalJavascript/SamFunctionalJavascriptTestBase.php 0 → 100644 +159 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\sam\FunctionalJavascript; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; /** * Base class for Simple Add More Functional Javascript tests. * * @group sam */ abstract class SamFunctionalJavascriptTestBase extends WebDriverTestBase { /** * {@inheritdoc} */ protected static $modules = [ 'block', 'link', 'field', 'field_ui', 'node', 'system', 'sam', ]; /** * {@inheritdoc} */ protected $defaultTheme = 'classy'; /** * An admin user. * * @var \Drupal\user\Entity\User */ protected $adminUser; /** * The node type under test. * * @var \Drupal\node\NodeTypeInterface */ protected $nodeType; /** * {@inheritdoc} */ public function setUp(): void { parent::setUp(); // Place some blocks to make our lives easier down the road. $this->drupalPlaceBlock('system_breadcrumb_block'); $this->drupalPlaceBlock('local_tasks_block'); $this->drupalPlaceBlock('local_actions_block'); $this->drupalPlaceBlock('page_title_block'); // Create a node type and link field. $this->nodeType = $this->drupalCreateContentType([ 'type' => 'node_type', 'name' => 'Node Type', ]); $storage = FieldStorageConfig::create([ 'field_name' => 'field_node__link', 'entity_type' => 'node', 'type' => 'link', 'cardinality' => 3, ]); $storage->save(); FieldConfig::create([ 'bundle' => $this->nodeType->id(), 'field_name' => 'field_node__link', 'entity_type' => 'node', 'label' => 'Link Field', ])->save(); // Add the field to the form \Drupal::service('entity_display.repository') ->getFormDisplay('node', $this->nodeType->id(), 'default') ->setComponent('field_node__link', [ 'type' => 'link_default', ]) ->save(); } /** * Asserts that text appears on page after a wait. * * @param string $text * The text that should appear on the page. * @param int $timeout * Timeout in milliseconds, defaults to 10000. */ protected function waitForText($text, $timeout = 10000) { $result = $this->assertSession()->waitForText($text, $timeout); $this->assertNotEmpty($result, "\"$text\" not found"); } /** * Asserts that text does not appear on page after a wait. * * @param string $text * The text that should not be on the page. * @param int $timeout * Timeout in milliseconds, defaults to 10000. */ protected function waitForNoText($text, $timeout = 10000) { $page = $this->getSession()->getPage(); $result = $page->waitFor($timeout / 1000, function ($page) use ($text) { $actual = preg_replace('/\s+/u', ' ', $page->getText()); $regex = '/' . preg_quote($text, '/') . '/ui'; return (bool) !preg_match($regex, $actual); }); $this->assertNotEmpty($result, "\"$text\" was found but shouldn't be there."); } /** * Waits for the specified selector and returns it if not empty. * * @param string $selector * The selector engine name. See ElementInterface::findAll() for the * supported selectors. * @param string|array $locator * The selector locator. * @param int $timeout * Timeout in milliseconds, defaults to 10000. * * @return \Behat\Mink\Element\NodeElement * The page element node if found. If not found, the test fails. */ protected function assertElementExistsAfterWait($selector, $locator, $timeout = 10000) { $element = $this->assertSession()->waitForElement($selector, $locator, $timeout); $this->assertNotEmpty($element); return $element; } /** * Debugger method to save additional HTML output. * * The base class will only save browser output when accessing page using * ::drupalGet and providing a printer class to PHPUnit. This method * is intended for developers to help debug browser test failures and capture * more verbose output. */ protected function saveHtmlOutput() { $out = $this->getSession()->getPage()->getContent(); // Ensure that any changes to variables in the other thread are picked up. $this->refreshVariables(); if ($this->htmlOutputEnabled) { $html_output = '<hr />Ending URL: ' . $this->getSession()->getCurrentUrl(); $html_output .= '<hr />' . $out; $html_output .= $this->getHtmlOutputHeaders(); $this->htmlOutput($html_output); } } } Loading
tests/src/FunctionalJavascript/IntegrationFunctionalTest.php 0 → 100644 +140 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\sam\FunctionalJavascript; /** * Tests the basic functionality of Simple Add More. * * @group sam */ class IntegrationFunctionalTest extends SamFunctionalJavascriptTestBase { /** * Tests the basic functionality of Simple Add More. */ public function testFormSimplification() { $assert_session = $this->assertSession(); $session = $this->getSession(); // Log in as admin. $this->adminUser = $this->drupalCreateUser([ 'access content', 'administer nodes', 'bypass node access', 'administer node display', 'administer display modes', ]); $this->drupalLogin($this->adminUser); // Nothing configured, by default we simplify the node form. $this->drupalGet("/node/add/{$this->nodeType->id()}"); $assert_session->pageTextContains("Create {$this->nodeType->label()}"); $field_widget = $assert_session->elementExists('css', "form .field--name-field-node__link"); // Only one empty element is visible. $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $value = $assert_session->elementExists('css', 'input[name="field_node__link[0][uri]"]', $rows[0]) ->getValue(); $this->assertEmpty($value); $this->assertFalse($rows[1]->isVisible()); $this->assertFalse($rows[2]->isVisible()); // We see how many more elements can be added. $message = '2 additional items can be added'; $assert_session->elementTextContains('css', '.field--name-field-node__link .sam-add-more-help', $message); // We can reveal one element at a time. $button = $assert_session->elementExists('css', '.sam-add-more-button', $field_widget); $button->press(); $session->wait(200); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $this->assertTrue($rows[1]->isVisible()); $this->assertFalse($rows[2]->isVisible()); // The message gets updated accordingly. $message = '1 additional item can be added'; $assert_session->elementTextContains('css', '.field--name-field-node__link .sam-add-more-help', $message); // Do it again. $button->press(); $session->wait(200); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $this->assertTrue($rows[1]->isVisible()); $this->assertTrue($rows[2]->isVisible()); // The button is hidden and no more messages are visible $button = $assert_session->elementExists('css', '.sam-add-more-button', $field_widget); $this->assertFalse($button->isVisible()); $message = 'can be added'; $assert_session->elementTextNotContains('css', '.field--name-field-node__link', $message); // If the field is not empty, no empty elements are shown. $node = $this->drupalCreateNode([ 'type' => $this->nodeType->id(), 'title' => 'Node with a link', 'field_node__link' => [ 'uri' => 'https://drupal.org', 'text' => 'Drupal dot org', ], ]); $this->drupalGet($node->toUrl('edit-form')); $field_widget = $assert_session->elementExists('css', "form .field--name-field-node__link"); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $value = $assert_session->elementExists('css', 'input[name="field_node__link[0][uri]"]', $rows[0]) ->getValue(); $this->assertNotEmpty($value); $this->assertFalse($rows[1]->isVisible()); $this->assertFalse($rows[2]->isVisible()); // We see how many more elements can be added. $message = '2 additional items can be added'; $assert_session->elementTextContains('css', '.field--name-field-node__link .sam-add-more-help', $message); // We can still reveal more elements. $button = $assert_session->elementExists('css', '.sam-add-more-button', $field_widget); $button->press(); $session->wait(200); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $this->assertTrue($rows[1]->isVisible()); $this->assertFalse($rows[2]->isVisible()); // Change the widget third-party settings and verify we skip simplifying. \Drupal::service('entity_display.repository') ->getFormDisplay('node', $this->nodeType->id(), 'default') ->setComponent('field_node__link', [ 'type' => 'link_default', 'third_party_settings' => [ 'sam' => ['skip_simplification' => TRUE], ], ]) ->save(); $this->drupalGet("/node/add/{$this->nodeType->id()}"); $assert_session->pageTextContains("Create {$this->nodeType->label()}"); $field_widget = $assert_session->elementExists('css', "form .field--name-field-node__link"); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $this->assertTrue($rows[1]->isVisible()); $this->assertTrue($rows[2]->isVisible()); // Switching it back simplifies again. \Drupal::service('entity_display.repository') ->getFormDisplay('node', $this->nodeType->id(), 'default') ->setComponent('field_node__link', [ 'type' => 'link_default', 'third_party_settings' => [ 'sam' => ['skip_simplification' => FALSE], ], ]) ->save(); $this->drupalGet("/node/add/{$this->nodeType->id()}"); $assert_session->pageTextContains("Create {$this->nodeType->label()}"); $field_widget = $assert_session->elementExists('css', "form .field--name-field-node__link"); $rows = $field_widget->findAll('css', 'table tr.draggable'); $this->assertSame(3, count($rows)); $this->assertTrue($rows[0]->isVisible()); $this->assertFalse($rows[1]->isVisible()); $this->assertFalse($rows[2]->isVisible()); } }
tests/src/FunctionalJavascript/SamFunctionalJavascriptTestBase.php 0 → 100644 +159 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\sam\FunctionalJavascript; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; /** * Base class for Simple Add More Functional Javascript tests. * * @group sam */ abstract class SamFunctionalJavascriptTestBase extends WebDriverTestBase { /** * {@inheritdoc} */ protected static $modules = [ 'block', 'link', 'field', 'field_ui', 'node', 'system', 'sam', ]; /** * {@inheritdoc} */ protected $defaultTheme = 'classy'; /** * An admin user. * * @var \Drupal\user\Entity\User */ protected $adminUser; /** * The node type under test. * * @var \Drupal\node\NodeTypeInterface */ protected $nodeType; /** * {@inheritdoc} */ public function setUp(): void { parent::setUp(); // Place some blocks to make our lives easier down the road. $this->drupalPlaceBlock('system_breadcrumb_block'); $this->drupalPlaceBlock('local_tasks_block'); $this->drupalPlaceBlock('local_actions_block'); $this->drupalPlaceBlock('page_title_block'); // Create a node type and link field. $this->nodeType = $this->drupalCreateContentType([ 'type' => 'node_type', 'name' => 'Node Type', ]); $storage = FieldStorageConfig::create([ 'field_name' => 'field_node__link', 'entity_type' => 'node', 'type' => 'link', 'cardinality' => 3, ]); $storage->save(); FieldConfig::create([ 'bundle' => $this->nodeType->id(), 'field_name' => 'field_node__link', 'entity_type' => 'node', 'label' => 'Link Field', ])->save(); // Add the field to the form \Drupal::service('entity_display.repository') ->getFormDisplay('node', $this->nodeType->id(), 'default') ->setComponent('field_node__link', [ 'type' => 'link_default', ]) ->save(); } /** * Asserts that text appears on page after a wait. * * @param string $text * The text that should appear on the page. * @param int $timeout * Timeout in milliseconds, defaults to 10000. */ protected function waitForText($text, $timeout = 10000) { $result = $this->assertSession()->waitForText($text, $timeout); $this->assertNotEmpty($result, "\"$text\" not found"); } /** * Asserts that text does not appear on page after a wait. * * @param string $text * The text that should not be on the page. * @param int $timeout * Timeout in milliseconds, defaults to 10000. */ protected function waitForNoText($text, $timeout = 10000) { $page = $this->getSession()->getPage(); $result = $page->waitFor($timeout / 1000, function ($page) use ($text) { $actual = preg_replace('/\s+/u', ' ', $page->getText()); $regex = '/' . preg_quote($text, '/') . '/ui'; return (bool) !preg_match($regex, $actual); }); $this->assertNotEmpty($result, "\"$text\" was found but shouldn't be there."); } /** * Waits for the specified selector and returns it if not empty. * * @param string $selector * The selector engine name. See ElementInterface::findAll() for the * supported selectors. * @param string|array $locator * The selector locator. * @param int $timeout * Timeout in milliseconds, defaults to 10000. * * @return \Behat\Mink\Element\NodeElement * The page element node if found. If not found, the test fails. */ protected function assertElementExistsAfterWait($selector, $locator, $timeout = 10000) { $element = $this->assertSession()->waitForElement($selector, $locator, $timeout); $this->assertNotEmpty($element); return $element; } /** * Debugger method to save additional HTML output. * * The base class will only save browser output when accessing page using * ::drupalGet and providing a printer class to PHPUnit. This method * is intended for developers to help debug browser test failures and capture * more verbose output. */ protected function saveHtmlOutput() { $out = $this->getSession()->getPage()->getContent(); // Ensure that any changes to variables in the other thread are picked up. $this->refreshVariables(); if ($this->htmlOutputEnabled) { $html_output = '<hr />Ending URL: ' . $this->getSession()->getCurrentUrl(); $html_output .= '<hr />' . $out; $html_output .= $this->getHtmlOutputHeaders(); $this->htmlOutput($html_output); } } }