6c99c6c39f107068d21fe5d46edf3d581d58e781
[yaffs-website] / web / core / modules / layout_builder / tests / src / FunctionalJavascript / InlineBlockTestBase.php
1 <?php
2
3 namespace Drupal\Tests\layout_builder\FunctionalJavascript;
4
5 use Drupal\block_content\Entity\BlockContentType;
6 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
7 use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait;
8
9 /**
10  * Base class for testing inline blocks.
11  */
12 abstract class InlineBlockTestBase extends WebDriverTestBase {
13
14   use ContextualLinkClickTrait;
15
16   /**
17    * Locator for inline blocks.
18    */
19   const INLINE_BLOCK_LOCATOR = '.block-inline-blockbasic';
20
21   /**
22    * Path prefix for the field UI for the test bundle.
23    */
24   const FIELD_UI_PREFIX = 'admin/structure/types/manage/bundle_with_section_field';
25
26   /**
27    * {@inheritdoc}
28    */
29   public static $modules = [
30     'block_content',
31     'layout_builder',
32     'block',
33     'node',
34     'contextual',
35     // @todo Remove after https://www.drupal.org/project/drupal/issues/2901792.
36     'no_transitions_css',
37   ];
38
39   /**
40    * The block storage.
41    *
42    * @var \Drupal\Core\Entity\EntityStorageInterface
43    */
44   protected $blockStorage;
45
46   /**
47    * {@inheritdoc}
48    */
49   protected function setUp() {
50     parent::setUp();
51     // @todo The Layout Builder UI relies on local tasks; fix in
52     //   https://www.drupal.org/project/drupal/issues/2917777.
53     $this->drupalPlaceBlock('local_tasks_block');
54
55     $this->createContentType(['type' => 'bundle_with_section_field', 'new_revision' => TRUE]);
56     $this->createNode([
57       'type' => 'bundle_with_section_field',
58       'title' => 'The node title',
59       'body' => [
60         [
61           'value' => 'The node body',
62         ],
63       ],
64     ]);
65     $this->createNode([
66       'type' => 'bundle_with_section_field',
67       'title' => 'The node2 title',
68       'body' => [
69         [
70           'value' => 'The node2 body',
71         ],
72       ],
73     ]);
74     $bundle = BlockContentType::create([
75       'id' => 'basic',
76       'label' => 'Basic block',
77       'revision' => 1,
78     ]);
79     $bundle->save();
80     block_content_add_body_field($bundle->id());
81
82     $this->blockStorage = $this->container->get('entity_type.manager')->getStorage('block_content');
83   }
84
85   /**
86    * Saves a layout and asserts the message is correct.
87    */
88   protected function assertSaveLayout() {
89     $assert_session = $this->assertSession();
90     $assert_session->linkExists('Save Layout');
91     // Go to the Save Layout page. Currently there are random test failures if
92     // 'clickLink()' is used.
93     // @todo Convert tests that extend this class to NightWatch tests in
94     // https://www.drupal.org/node/2984161
95     $link = $this->getSession()->getPage()->findLink('Save Layout');
96     $this->drupalGet($link->getAttribute('href'));
97     $this->assertNotEmpty($assert_session->waitForElement('css', '.messages--status'));
98
99     if (stristr($this->getUrl(), 'admin/structure') === FALSE) {
100       $assert_session->pageTextContains('The layout override has been saved.');
101     }
102     else {
103       $assert_session->pageTextContains('The layout has been saved.');
104     }
105   }
106
107   /**
108    * Gets the latest block entity id.
109    */
110   protected function getLatestBlockEntityId() {
111     $block_ids = \Drupal::entityQuery('block_content')->sort('id', 'DESC')->range(0, 1)->execute();
112     $block_id = array_pop($block_ids);
113     $this->assertNotEmpty($this->blockStorage->load($block_id));
114     return $block_id;
115   }
116
117   /**
118    * Removes an entity block from the layout but does not save the layout.
119    */
120   protected function removeInlineBlockFromLayout() {
121     $assert_session = $this->assertSession();
122     $page = $this->getSession()->getPage();
123     $block_text = $page->find('css', static::INLINE_BLOCK_LOCATOR)->getText();
124     $this->assertNotEmpty($block_text);
125     $assert_session->pageTextContains($block_text);
126     $this->clickContextualLink(static::INLINE_BLOCK_LOCATOR, 'Remove block');
127     $assert_session->waitForElement('css', "#drupal-off-canvas input[value='Remove']");
128     $assert_session->assertWaitOnAjaxRequest();
129     $page->find('css', '#drupal-off-canvas')->pressButton('Remove');
130     $this->waitForNoElement('#drupal-off-canvas');
131     $this->waitForNoElement(static::INLINE_BLOCK_LOCATOR);
132     $assert_session->assertWaitOnAjaxRequest();
133     $assert_session->pageTextNotContains($block_text);
134   }
135
136   /**
137    * Adds an entity block to the layout.
138    *
139    * @param string $title
140    *   The title field value.
141    * @param string $body
142    *   The body field value.
143    */
144   protected function addInlineBlockToLayout($title, $body) {
145     $assert_session = $this->assertSession();
146     $page = $this->getSession()->getPage();
147     $page->clickLink('Add Block');
148     $assert_session->assertWaitOnAjaxRequest();
149     $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.block-categories details:contains(Create new block)'));
150     $this->clickLink('Basic block');
151     $assert_session->assertWaitOnAjaxRequest();
152     $textarea = $assert_session->waitForElement('css', '[name="settings[block_form][body][0][value]"]');
153     $this->assertNotEmpty($textarea);
154     $assert_session->fieldValueEquals('Title', '');
155     $page->findField('Title')->setValue($title);
156     $textarea->setValue($body);
157     $page->pressButton('Add Block');
158     $this->assertDialogClosedAndTextVisible($body, static::INLINE_BLOCK_LOCATOR);
159   }
160
161   /**
162    * Configures an inline block in the Layout Builder.
163    *
164    * @param string $old_body
165    *   The old body field value.
166    * @param string $new_body
167    *   The new body field value.
168    * @param string $block_css_locator
169    *   The CSS locator to use to select the contextual link.
170    */
171   protected function configureInlineBlock($old_body, $new_body, $block_css_locator = NULL) {
172     $block_css_locator = $block_css_locator ?: static::INLINE_BLOCK_LOCATOR;
173     $assert_session = $this->assertSession();
174     $page = $this->getSession()->getPage();
175     $this->clickContextualLink($block_css_locator, 'Configure');
176     $textarea = $assert_session->waitForElementVisible('css', '[name="settings[block_form][body][0][value]"]');
177     $this->assertNotEmpty($textarea);
178     $this->assertSame($old_body, $textarea->getValue());
179     $textarea->setValue($new_body);
180     $page->pressButton('Update');
181     $this->waitForNoElement('#drupal-off-canvas');
182     $assert_session->assertWaitOnAjaxRequest();
183     $this->assertDialogClosedAndTextVisible($new_body);
184   }
185
186   /**
187    * Waits for an element to be removed from the page.
188    *
189    * @param string $selector
190    *   CSS selector.
191    * @param int $timeout
192    *   (optional) Timeout in milliseconds, defaults to 10000.
193    *
194    * @todo Remove in https://www.drupal.org/node/2892440.
195    */
196   protected function waitForNoElement($selector, $timeout = 10000) {
197     $condition = "(typeof jQuery !== 'undefined' && jQuery('$selector').length === 0)";
198     $this->assertJsCondition($condition, $timeout);
199   }
200
201   /**
202    * Asserts that the dialog closes and the new text appears on the main canvas.
203    *
204    * @param string $text
205    *   The text.
206    * @param string|null $css_locator
207    *   The css locator to use inside the main canvas if any.
208    */
209   protected function assertDialogClosedAndTextVisible($text, $css_locator = NULL) {
210     $assert_session = $this->assertSession();
211     $this->waitForNoElement('#drupal-off-canvas');
212     $assert_session->assertWaitOnAjaxRequest();
213     $assert_session->elementNotExists('css', '#drupal-off-canvas');
214     if ($css_locator) {
215       $this->assertNotEmpty($assert_session->waitForElementVisible('css', ".dialog-off-canvas-main-canvas $css_locator:contains('$text')"));
216     }
217     else {
218       $this->assertNotEmpty($assert_session->waitForElementVisible('css', ".dialog-off-canvas-main-canvas:contains('$text')"));
219     }
220   }
221
222 }