.../LayoutBuilderQuickEditTest.php | 275 ++++++++++++--------- 1 file changed, 158 insertions(+), 117 deletions(-) diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderQuickEditTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderQuickEditTest.php index d4b7e435be..00d8563022 100644 --- a/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderQuickEditTest.php +++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderQuickEditTest.php @@ -2,12 +2,10 @@ namespace Drupal\Tests\layout_builder\FunctionalJavascript; -use Drupal\Core\Entity\Entity\EntityViewDisplay; -use Drupal\field\Entity\FieldConfig; -use Drupal\field\Entity\FieldStorageConfig; use Drupal\node\Entity\NodeType; -use Drupal\node\NodeInterface; -use Drupal\Tests\quickedit\FunctionalJavascript\QuickEditIntegrationTest; +use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; +use Drupal\Tests\quickedit\FunctionalJavascript\QuickEditJavascriptTestBase; /** * Tests that Layout Builder functions with Quick Edit. @@ -17,17 +15,34 @@ * * @group layout_builder */ -class LayoutBuilderQuickEditTest extends QuickEditIntegrationTest { +class LayoutBuilderQuickEditTest extends QuickEditJavascriptTestBase { + + use EntityReferenceTestTrait; + use ContextualLinkClickTrait; /** * {@inheritdoc} */ public static $modules = [ + 'node', 'layout_builder', 'layout_builder_test_css_transitions', - 'datetime', ]; + /** + * The article node under test. + * + * @var \Drupal\node\NodeInterface + */ + protected $article; + + /** + * A user with permissions to edit Articles and use Quick Edit. + * + * @var \Drupal\user\UserInterface + */ + protected $contentAuthorUser; + /** * Whether the test is currently using Layout Builder on the entity. * @@ -46,37 +61,136 @@ class LayoutBuilderQuickEditTest extends QuickEditIntegrationTest { protected function setUp() { parent::setUp(); + $this->drupalPlaceBlock('page_title_block'); + // @todo The Layout Builder UI relies on local tasks; fix in // https://www.drupal.org/project/drupal/issues/2917777. $this->drupalPlaceBlock('local_tasks_block'); - $field_storage = FieldStorageConfig::create([ - 'field_name' => 'field_date', - 'entity_type' => 'node', - 'type' => 'datetime', + // Create the Article node type. + $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); + $this->article = $this->drupalCreateNode([ + 'type' => 'article', + 'title' => t('My Test Node'), + 'body' => [ + 'value' => 'Hello Layout Builder!', + 'format' => 'plain_text', + ], ]); - $field_storage->save(); - FieldConfig::create([ - 'field_storage' => $field_storage, - 'bundle' => 'article', - 'label' => 'Date field', - ])->save(); - // Save the current user to re-login after Layout Builder changes. - $user = $this->loggedInUser; - $this->loginLayoutAdmin(); + // Log in as a content author who can use Quick Edit and edit Articles. + $this->contentAuthorUser = $this->drupalCreateUser([ + 'access contextual links', + 'access in-place editing', + 'access content', + 'edit any article content', + ]); + $this->drupalLogin($this->contentAuthorUser); + } + + /** + * Tests that the Layout Builder render pipeline for Quick Edit works. + * + * @covers \Drupal\layout_builder\QuickEditIntegration::quickEditRenderField + */ + public function testLayoutBuilderRenderPipelineForQuickEdit() { + $this->enableLayouts('admin/structure/types/manage/article/display/default'); + $this->usingLayoutBuilder = TRUE; + $this->assertQuickEditInit(); + + // Start in-place editing of the article node. + $this->clickContextualLink('[data-quickedit-entity-id="node/1"]', 'Quick edit'); + $this->assertEntityInstanceStates([ + 'node/1[0]' => 'opened', + ]); + $this->assertQuickEditEntityToolbar((string) $this->article->label(), NULL); + $this->assertEntityInstanceFieldStates('node', 1, 0, [ + 'node/1/title/en/full' => 'candidate', + 'node/1/uid/en/full' => 'candidate', + 'node/1/created/en/full' => 'candidate', + 'node/1/body/en/full' => 'candidate', + ]); + + $assert_session = $this->assertSession(); + + // Click the body field. + $this->click('[data-quickedit-entity-id="node/1"] .field--name-body'); + $assert_session->waitForElement('css', '.quickedit-toolbar-field div[id*="body"]'); + $this->assertQuickEditEntityToolbar((string) $this->article->label(), 'Body'); + $this->assertEntityInstanceFieldStates('node', 1, 0, [ + 'node/1/title/en/full' => 'candidate', + 'node/1/uid/en/full' => 'candidate', + 'node/1/created/en/full' => 'candidate', + 'node/1/body/en/full' => 'active', + ]); + // Change the body field. $page = $this->getSession()->getPage(); + $page->fillField('body[0][value]', 'foobar'); + $this->awaitEntityInstanceFieldState('node', 1, 0, 'body', 'en', 'changed'); + $this->assertEntityInstanceFieldStates('node', 1, 0, [ + 'node/1/title/en/full' => 'candidate', + 'node/1/uid/en/full' => 'candidate', + 'node/1/created/en/full' => 'candidate', + 'node/1/body/en/full' => 'changed', + ]); - $this->drupalGet('admin/structure/block/block-content/manage/basic/display'); - $page->checkField('layout[enabled]'); - $page->pressButton('Save'); + // Save the entity. + $this->saveQuickEdit(); + $this->assertEntityInstanceStates([ + 'node/1[0]' => 'committing', + ]); + $this->assertEntityInstanceFieldStates('node', 1, 0, [ + 'node/1/uid/en/full' => 'inactive', + 'node/1/created/en/full' => 'inactive', + 'node/1/body/en/full' => 'inactive', + 'node/1/title/en/full' => 'inactive', + ]); - $this->drupalLogin($user); + // Verify that the render pipeline worked: it should result in updated HTML. + $this->assertSession()->elementContains('css', '.block-layout-builder.block-field-blocknodearticlebody div[data-quickedit-field-id^="node/1/body/en/layout_builder-default-0-"]', 'foobar'); } /** - * Tests enabling and displaying Layout Builder on a node. + * Tests that Quick Edit still works even when there are duplicate fields. + * + * @see https://www.drupal.org/project/drupal/issues/3041850 + */ + public function testQuickEditIgnoresDuplicateFields() { + // Place the body field a second time using Layout Builder. + $this->enableLayouts('admin/structure/types/manage/article/display/default'); + $page = $this->getSession()->getPage(); + $assert_session = $this->assertSession(); + $this->loginLayoutAdmin(); + $this->drupalGet('admin/structure/types/manage/article/display/default/layout'); + $page->clickLink('Add Block'); + $this->assertNotEmpty($assert_session->waitForElementVisible('css', '#drupal-off-canvas')); + $assert_session->assertWaitOnAjaxRequest(); + $page->clickLink('Body'); + $assert_session->assertWaitOnAjaxRequest(); + $page->pressButton('Add Block'); + $assert_session->assertWaitOnAjaxRequest(); + $page->pressButton('Save layout'); + $this->assertNotEmpty($assert_session->waitForElement('css', '.messages--status')); + $assert_session->pageTextContains('The layout has been saved.'); + + $this->drupalLogin($this->contentAuthorUser); + $this->drupalGet('node/' . $this->article->id()); + $this->usingLayoutBuilder = TRUE; + + $this->awaitQuickEditForEntity('node', 1); + $this->assertEntityInstanceStates([ + 'node/1[0]' => 'closed', + ]); + $this->assertEntityInstanceFieldStates('node', 1, 0, [ + 'node/1/title/en/full' => 'inactive', + 'node/1/uid/en/full' => 'inactive', + 'node/1/created/en/full' => 'inactive', + ]); + } + + /** + * Tests Quick Edit boots correctly with Layout Builder defaults & overrides. * * @param bool $use_revisions * If revisions are used. @@ -89,29 +203,31 @@ public function testEnableDisableLayoutBuilder($use_revisions) { $content_type->setNewRevision(FALSE); $content_type->save(); } - $node = $this->createNodeWithTerm(); - $this->assertQuickEditInit($node); + // Test article with Layout Builder disabled. + $this->assertQuickEditInit(); + + // Test article with Layout Builder enabled. $this->enableLayouts('admin/structure/types/manage/article/display/default'); $this->usingLayoutBuilder = TRUE; - // Test article with Layout Builder enabled. - $this->assertQuickEditInit($node); + $this->assertQuickEditInit(); // Test article with Layout Builder override. - $this->createLayoutOverride('node/' . $node->id() . '/layout'); - $this->assertQuickEditInit($node); + $this->createLayoutOverride(); + $this->assertQuickEditInit(); - // If we are not using revisions remove the layout override and disable - // layout for the bundle. + // If we're using revisions, it's not possible to disable Layout Builder + // without deleting the node (unless the revisions containing the override + // would be deleted). if (!$use_revisions) { // Test article with Layout Builder when reverted back to defaults. - $this->revertLayoutToDefaults('node/' . $node->id() . '/layout'); - $this->assertQuickEditInit($node); + $this->revertLayoutToDefaults(); + $this->assertQuickEditInit(); // Test with Layout Builder disabled after being enabled. $this->usingLayoutBuilder = FALSE; $this->disableLayoutBuilder('admin/structure/types/manage/article/display/default'); - $this->assertQuickEditInit($node); + $this->assertQuickEditInit(); } } @@ -125,32 +241,6 @@ public function providerEnableDisableLayoutBuilder() { ]; } - /** - * {@inheritdoc} - * - * @param bool $useOverride - * Whether test should use a layout override. - * - * @dataProvider provideTestArticleNode - */ - public function testArticleNode($useOverride = FALSE) { - $this->enableLayouts('admin/structure/types/manage/article/display/default'); - $this->usingLayoutBuilder = TRUE; - $node = $this->createNodeWithTerm(); - if ($useOverride) { - $this->createLayoutOverride('node/' . $node->id() . '/layout'); - } - $this->doTestArticle($node); - } - - /** - * {@inheritdoc} - */ - public function testCustomBlock() { - $this->usingLayoutBuilder = TRUE; - parent::testCustomBlock(); - } - /** * Enables layouts at an admin path. * @@ -169,16 +259,6 @@ protected function enableLayouts($path) { $this->drupalLogin($user); } - /** - * Data provider for testArticleNode(). - */ - public function provideTestArticleNode() { - return [ - 'no override' => [FALSE], - 'use override' => [TRUE], - ]; - } - /** * {@inheritdoc} */ @@ -227,44 +307,21 @@ protected function loginLayoutAdmin() { 'access content', 'administer node display', 'administer node fields', - 'administer block_content display', - 'administer block_content fields', 'administer blocks', ])); } /** * Creates a layout override. - * - * @param string $layout_url - * The Layout Builder URL. */ - protected function createLayoutOverride($layout_url) { + protected function createLayoutOverride() { $page = $this->getSession()->getPage(); $assert_session = $this->assertSession(); // Save the current user to re-login after Layout Builder changes. $user = $this->loggedInUser; $this->loginLayoutAdmin(); - $this->drupalGet($layout_url); - - $page->clickLink('Add Block'); - $this->assertNotEmpty($assert_session->waitForElementVisible('css', '#drupal-off-canvas')); - $assert_session->assertWaitOnAjaxRequest(); - - $page->clickLink('Date field'); - $assert_session->assertWaitOnAjaxRequest(); - $page->pressButton('Add Block'); - $assert_session->assertWaitOnAjaxRequest(); - - $page->clickLink('Add Block'); - $this->assertNotEmpty($assert_session->waitForElementVisible('css', '#drupal-off-canvas')); - $assert_session->assertWaitOnAjaxRequest(); - - $page->clickLink('Date field'); - $assert_session->assertWaitOnAjaxRequest(); - $page->pressButton('Add Block'); - $assert_session->assertWaitOnAjaxRequest(); + $this->drupalGet('node/' . $this->article->id() . '/layout'); $page->pressButton('Save layout'); $this->assertNotEmpty($assert_session->waitForElement('css', '.messages--status')); @@ -274,17 +331,14 @@ protected function createLayoutOverride($layout_url) { /** * Reverts a layout override. - * - * @param string $layout_url - * The Layout Builder URL. */ - protected function revertLayoutToDefaults($layout_url) { + protected function revertLayoutToDefaults() { $page = $this->getSession()->getPage(); $assert_session = $this->assertSession(); // Save the current user to re-login after Layout Builder changes. $user = $this->loggedInUser; $this->loginLayoutAdmin(); - $this->drupalGet($layout_url); + $this->drupalGet('node/' . $this->article->id() . '/layout'); $assert_session->buttonExists('Revert to defaults'); $page->pressButton('Revert to defaults'); $page->pressButton('Revert'); @@ -316,11 +370,9 @@ protected function disableLayoutBuilder($path) { * * @todo Replace calls to this method with calls to ::doTestArticle() in * https://www.drupal.org/node/3037436. - * - * @param \Drupal\node\NodeInterface $node - * The node. */ - private function assertQuickEditInit(NodeInterface $node) { + private function assertQuickEditInit() { + $node = $this->article; $this->drupalGet('node/' . $node->id()); // Initial state. @@ -333,7 +385,6 @@ private function assertQuickEditInit(NodeInterface $node) { 'node/1/uid/en/full' => 'inactive', 'node/1/created/en/full' => 'inactive', 'node/1/body/en/full' => 'inactive', - 'node/1/field_tags/en/full' => 'inactive', ]); } @@ -362,14 +413,4 @@ protected function getQuickEditFieldId($original_field_id) { return $new_field_id; } - /** - * {@inheritdoc} - */ - protected function createNodeWithTerm() { - $node = parent::createNodeWithTerm(); - $node->field_date = '1978-11-19T05:00:00'; - $node->save(); - return $node; - } - }