3 namespace Drupal\Tests\field_layout\FunctionalJavascript;
5 use Drupal\entity_test\Entity\EntityTest;
6 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
9 * Tests using field layout for entity displays.
13 class FieldLayoutTest extends WebDriverTestBase {
18 public static $modules = ['field_layout', 'field_ui', 'field_layout_test', 'layout_test'];
23 protected function setUp() {
26 $entity = EntityTest::create([
27 'name' => 'The name for this entity',
28 'field_test_text' => [
29 ['value' => 'The field test text value'],
33 $this->drupalLogin($this->drupalCreateUser([
34 'access administration pages',
36 'administer entity_test content',
37 'administer entity_test fields',
38 'administer entity_test display',
39 'administer entity_test form display',
40 'view the administration theme',
45 * Tests that layouts are unique per view mode.
47 public function testEntityViewModes() {
48 // By default, the field is not visible.
49 $this->drupalGet('entity_test/1/test');
50 $this->assertSession()->elementNotExists('css', '.layout__region--content .field--name-field-test-text');
51 $this->drupalGet('entity_test/1');
52 $this->assertSession()->elementNotExists('css', '.layout__region--content .field--name-field-test-text');
54 // Change the layout for the "test" view mode. See
55 // core.entity_view_mode.entity_test.test.yml.
56 $this->drupalGet('entity_test/structure/entity_test/display');
57 $this->click('#edit-modes');
58 $this->getSession()->getPage()->checkField('display_modes_custom[test]');
59 $this->submitForm([], 'Save');
60 $this->clickLink('configure them');
61 $this->getSession()->getPage()->pressButton('Show row weights');
62 $this->getSession()->getPage()->selectFieldOption('fields[field_test_text][region]', 'content');
63 $this->assertSession()->assertWaitOnAjaxRequest();
64 $this->submitForm([], 'Save');
66 // Each view mode has a different layout.
67 $this->drupalGet('entity_test/1/test');
68 $this->assertSession()->elementExists('css', '.layout__region--content .field--name-field-test-text');
69 $this->drupalGet('entity_test/1');
70 $this->assertSession()->elementNotExists('css', '.layout__region--content .field--name-field-test-text');
74 * Tests the use of field layout for entity form displays.
76 public function testEntityForm() {
77 // By default, the one-column layout is used.
78 $this->drupalGet('entity_test/manage/1/edit');
79 $this->assertFieldInRegion('field_test_text[0][value]', 'content');
81 // The one-column layout is in use.
82 $this->drupalGet('entity_test/structure/entity_test/form-display');
83 $this->assertEquals(['Content', 'Disabled'], $this->getRegionTitles());
85 // Switch the layout to two columns.
86 $this->click('#edit-field-layouts');
87 $this->getSession()->getPage()->selectFieldOption('field_layout', 'layout_twocol');
88 $this->assertSession()->assertWaitOnAjaxRequest();
89 $this->submitForm([], 'Save');
91 // The field is moved to the default region for the new layout.
92 $this->assertSession()->pageTextContains('Your settings have been saved.');
93 $this->assertEquals(['Top', 'First', 'Second', 'Bottom', 'Disabled'], $this->getRegionTitles());
95 $this->drupalGet('entity_test/manage/1/edit');
96 // No fields are visible, and the regions don't display when empty.
97 $this->assertFieldInRegion('field_test_text[0][value]', 'first');
98 $this->assertSession()->elementExists('css', '.layout__region--first .field--name-field-test-text');
100 // After a refresh the new regions are still there.
101 $this->drupalGet('entity_test/structure/entity_test/form-display');
102 $this->assertEquals(['Top', 'First', 'Second', 'Bottom', 'Disabled'], $this->getRegionTitles());
103 $this->assertSession()->waitForElement('css', '.tabledrag-handle');
104 $id = $this->getSession()->getPage()->find('css', '[name="form_build_id"]')->getValue();
106 // Drag the field to the second region.
107 $field_test_text_row = $this->getSession()->getPage()->find('css', '#field-test-text');
108 $second_region_row = $this->getSession()->getPage()->find('css', '.region-second-message');
109 $field_test_text_row->find('css', '.handle')->dragTo($second_region_row);
110 $this->assertSession()->assertWaitOnAjaxRequest();
111 $this->assertSession()->waitForElement('css', "[name='form_build_id']:not([value='$id'])");
112 $this->submitForm([], 'Save');
113 $this->assertSession()->pageTextContains('Your settings have been saved.');
115 // The new layout is used.
116 $this->drupalGet('entity_test/manage/1/edit');
117 $this->assertSession()->elementExists('css', '.layout__region--second .field--name-field-test-text');
118 $this->assertFieldInRegion('field_test_text[0][value]', 'second');
120 // Move the field to the second region without tabledrag.
121 $this->drupalGet('entity_test/structure/entity_test/form-display');
122 $this->getSession()->getPage()->pressButton('Show row weights');
123 $this->getSession()->getPage()->selectFieldOption('fields[field_test_text][region]', 'second');
124 $this->assertSession()->assertWaitOnAjaxRequest();
125 $this->submitForm([], 'Save');
126 $this->assertSession()->pageTextContains('Your settings have been saved.');
128 // The updated region is used.
129 $this->drupalGet('entity_test/manage/1/edit');
130 $this->assertFieldInRegion('field_test_text[0][value]', 'second');
132 // The layout is still in use without Field UI.
133 $this->container->get('module_installer')->uninstall(['field_ui']);
134 $this->drupalGet('entity_test/manage/1/edit');
135 $this->assertFieldInRegion('field_test_text[0][value]', 'second');
139 * Tests the use of field layout for entity view displays.
141 public function testEntityView() {
142 // The one-column layout is in use.
143 $this->drupalGet('entity_test/structure/entity_test/display');
144 $this->assertEquals(['Content', 'Disabled'], $this->getRegionTitles());
146 // Switch the layout to two columns.
147 $this->click('#edit-field-layouts');
148 $this->getSession()->getPage()->selectFieldOption('field_layout', 'layout_twocol');
149 $this->assertSession()->assertWaitOnAjaxRequest();
150 $this->submitForm([], 'Save');
152 $this->assertSession()->pageTextContains('Your settings have been saved.');
153 $this->assertEquals(['Top', 'First', 'Second', 'Bottom', 'Disabled'], $this->getRegionTitles());
155 $this->drupalGet('entity_test/1');
156 // No fields are visible, and the regions don't display when empty.
157 $this->assertSession()->elementNotExists('css', '.layout--twocol');
158 $this->assertSession()->elementNotExists('css', '.layout__region');
159 $this->assertSession()->elementNotExists('css', '.field--name-field-test-text');
161 // After a refresh the new regions are still there.
162 $this->drupalGet('entity_test/structure/entity_test/display');
163 $this->assertEquals(['Top', 'First', 'Second', 'Bottom', 'Disabled'], $this->getRegionTitles());
164 $this->assertSession()->waitForElement('css', '.tabledrag-handle');
165 $id = $this->getSession()->getPage()->find('css', '[name="form_build_id"]')->getValue();
167 // Drag the field to the first region.
168 $this->assertTrue($this->assertSession()->optionExists('fields[field_test_text][region]', 'hidden')->isSelected());
169 $field_test_text_row = $this->getSession()->getPage()->find('css', '#field-test-text');
170 $first_region_row = $this->getSession()->getPage()->find('css', '.region-first-message');
171 $field_test_text_row->find('css', '.handle')->dragTo($first_region_row);
172 $this->assertSession()->assertWaitOnAjaxRequest();
173 $this->assertFalse($this->assertSession()->optionExists('fields[field_test_text][region]', 'hidden')->isSelected());
174 $this->assertSession()->waitForElement('css', "[name='form_build_id']:not([value='$id'])");
175 $this->submitForm([], 'Save');
176 $this->assertSession()->pageTextContains('Your settings have been saved.');
178 // The new layout is used.
179 $this->drupalGet('entity_test/1');
180 $this->assertSession()->elementExists('css', '.layout--twocol');
181 $this->assertSession()->elementExists('css', '.layout__region--first .field--name-field-test-text');
183 // Move the field to the second region without tabledrag.
184 $this->drupalGet('entity_test/structure/entity_test/display');
185 $this->getSession()->getPage()->pressButton('Show row weights');
186 $this->getSession()->getPage()->selectFieldOption('fields[field_test_text][region]', 'second');
187 $this->assertSession()->assertWaitOnAjaxRequest();
188 $this->submitForm([], 'Save');
189 $this->assertSession()->pageTextContains('Your settings have been saved.');
191 // The updated region is used.
192 $this->drupalGet('entity_test/1');
193 $this->assertSession()->elementExists('css', '.layout__region--second .field--name-field-test-text');
195 // The layout is still in use without Field UI.
196 $this->container->get('module_installer')->uninstall(['field_ui']);
197 $this->drupalGet('entity_test/1');
198 $this->assertSession()->elementExists('css', '.layout--twocol');
199 $this->assertSession()->elementExists('css', '.layout__region--second .field--name-field-test-text');
203 * Tests layout plugins with forms.
205 public function testLayoutForms() {
206 $this->drupalGet('entity_test/structure/entity_test/display');
207 // Switch to a field layout with settings.
208 $this->click('#edit-field-layouts');
210 // Test switching between layouts with and without forms.
211 $this->getSession()->getPage()->selectFieldOption('field_layout', 'layout_test_plugin');
212 $this->assertSession()->assertWaitOnAjaxRequest();
213 $this->assertSession()->fieldExists('settings_wrapper[layout_settings][setting_1]');
215 $this->getSession()->getPage()->selectFieldOption('field_layout', 'layout_test_2col');
216 $this->assertSession()->assertWaitOnAjaxRequest();
217 $this->assertSession()->fieldNotExists('settings_wrapper[layout_settings][setting_1]');
219 $this->getSession()->getPage()->selectFieldOption('field_layout', 'layout_test_plugin');
220 $this->assertSession()->assertWaitOnAjaxRequest();
221 $this->assertSession()->fieldExists('settings_wrapper[layout_settings][setting_1]');
223 // Move the test field to the content region.
224 $this->getSession()->getPage()->pressButton('Show row weights');
225 $this->getSession()->getPage()->selectFieldOption('fields[field_test_text][region]', 'content');
226 $this->assertSession()->assertWaitOnAjaxRequest();
227 $this->submitForm([], 'Save');
229 $this->drupalGet('entity_test/1');
230 $this->assertSession()->pageTextContains('Blah: Default');
232 // Update the field layout settings.
233 $this->drupalGet('entity_test/structure/entity_test/display');
234 $this->click('#edit-field-layouts');
235 $this->getSession()->getPage()->fillField('settings_wrapper[layout_settings][setting_1]', 'Test text');
236 $this->submitForm([], 'Save');
238 $this->drupalGet('entity_test/1');
239 $this->assertSession()->pageTextContains('Blah: Test text');
243 * Tests changing the formatter and region at the same time.
245 public function testChangingFormatterAndRegion() {
246 $assert_session = $this->assertSession();
247 $page = $this->getSession()->getPage();
249 // Add the test field to the content region.
250 $this->drupalGet('entity_test/structure/entity_test/display');
251 $page->find('css', '#field-test-text .handle')->dragTo($page->find('css', '.region-content-message'));
252 $assert_session->assertWaitOnAjaxRequest();
253 $page->pressButton('Save');
254 $assert_session->fieldValueEquals('fields[field_test_text][region]', 'content');
255 $assert_session->fieldValueEquals('fields[field_test_text][type]', 'text_default');
257 // Switch the layout to two columns.
258 $this->click('#edit-field-layouts');
259 $page->selectFieldOption('field_layout', 'layout_twocol');
260 $assert_session->assertWaitOnAjaxRequest();
261 $page->pressButton('Save');
262 $assert_session->fieldValueEquals('fields[field_test_text][region]', 'first');
264 // Change the formatter and move to another region.
265 $page->selectFieldOption('fields[field_test_text][type]', 'text_trimmed');
266 $assert_session->assertWaitOnAjaxRequest();
267 $page->find('css', '#field-test-text .handle')->dragTo($page->find('css', '.region-second-message'));
268 $assert_session->assertWaitOnAjaxRequest();
269 $page->pressButton('Save');
271 // Assert that both the formatter and region change are persisted.
272 $assert_session->fieldValueEquals('fields[field_test_text][region]', 'second');
273 $assert_session->fieldValueEquals('fields[field_test_text][type]', 'text_trimmed');
277 * Gets the region titles on the page.
280 * An array of region titles.
282 protected function getRegionTitles() {
284 $region_title_elements = $this->getSession()->getPage()->findAll('css', '.region-title td');
285 /** @var \Behat\Mink\Element\NodeElement[] $region_title_elements */
286 foreach ($region_title_elements as $region_title_element) {
287 $region_titles[] = $region_title_element->getText();
289 return $region_titles;
293 * Asserts that a field exists in a given region.
295 * @param string $field_selector
296 * The field selector, one of field id|name|label|value.
297 * @param string $region_name
298 * The machine name of the region.
300 protected function assertFieldInRegion($field_selector, $region_name) {
301 $region_element = $this->getSession()->getPage()->find('css', ".layout__region--$region_name");
302 $this->assertNotNull($region_element);
303 $this->assertSession()->fieldExists($field_selector, $region_element);