FieldLayoutTest.php

Same filename in this branch
  1. 11.x core/modules/field_layout/tests/src/Functional/FieldLayoutTest.php
Same filename in other branches
  1. 9 core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php
  2. 9 core/modules/field_layout/tests/src/Functional/FieldLayoutTest.php
  3. 8.9.x core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php
  4. 8.9.x core/modules/field_layout/tests/src/Functional/FieldLayoutTest.php
  5. 10 core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php
  6. 10 core/modules/field_layout/tests/src/Functional/FieldLayoutTest.php

Namespace

Drupal\Tests\field_layout\FunctionalJavascript

File

core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php

View source
<?php

declare (strict_types=1);
namespace Drupal\Tests\field_layout\FunctionalJavascript;

use Drupal\entity_test\Entity\EntityTest;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;

/**
 * Tests using field layout for entity displays.
 *
 * @group field_layout
 */
class FieldLayoutTest extends WebDriverTestBase {
    
    /**
     * {@inheritdoc}
     */
    protected static $modules = [
        'field_layout',
        'field_ui',
        'field_layout_test',
        'layout_test',
    ];
    
    /**
     * {@inheritdoc}
     */
    protected $defaultTheme = 'stark';
    
    /**
     * {@inheritdoc}
     */
    protected function setUp() : void {
        parent::setUp();
        $entity = EntityTest::create([
            'name' => 'The name for this entity',
            'field_test_text' => [
                [
                    'value' => 'The field test text value',
                ],
            ],
        ]);
        $entity->save();
        $this->drupalLogin($this->drupalCreateUser([
            'access administration pages',
            'view test entity',
            'administer entity_test content',
            'administer entity_test fields',
            'administer entity_test display',
            'administer entity_test form display',
            'view the administration theme',
        ]));
    }
    
    /**
     * Tests that layouts are unique per view mode.
     */
    public function testEntityViewModes() : void {
        // By default, the field is not visible.
        $this->drupalGet('entity_test/1/test');
        $this->assertSession()
            ->elementNotExists('css', '.layout__region--content ');
        $this->drupalGet('entity_test/1');
        $this->assertSession()
            ->elementNotExists('css', '.layout__region--content');
        // Change the layout for the "test" view mode. See
        // core.entity_view_mode.entity_test.test.yml.
        $this->drupalGet('entity_test/structure/entity_test/display');
        $this->click('#edit-modes');
        $this->getSession()
            ->getPage()
            ->checkField('display_modes_custom[test]');
        $this->submitForm([], 'Save');
        $this->clickLink('configure them');
        $this->getSession()
            ->getPage()
            ->pressButton('Show row weights');
        $this->getSession()
            ->getPage()
            ->selectFieldOption('fields[field_test_text][region]', 'content');
        $this->submitForm([], 'Save');
        // Each view mode has a different layout.
        $this->drupalGet('entity_test/1/test');
        $this->assertSession()
            ->elementTextContains('css', '.layout__region--content', 'The field test text value');
        $this->drupalGet('entity_test/1');
        $this->assertSession()
            ->elementNotExists('css', '.layout__region--content');
    }
    
    /**
     * Tests the use of field layout for entity form displays.
     */
    public function testEntityForm() : void {
        // By default, the one-column layout is used.
        $this->drupalGet('entity_test/manage/1/edit');
        $this->assertFieldInRegion('field_test_text[0][value]', 'content');
        // The one-column layout is in use.
        $this->drupalGet('entity_test/structure/entity_test/form-display');
        $this->assertEquals([
            'Content',
            'Disabled',
        ], $this->getRegionTitles());
        // Switch the layout to two columns.
        $this->click('#edit-field-layouts');
        $this->getSession()
            ->getPage()
            ->selectFieldOption('field_layout', 'layout_twocol');
        $this->assertSession()
            ->assertWaitOnAjaxRequest();
        $this->submitForm([], 'Save');
        // The field is moved to the default region for the new layout.
        $this->assertSession()
            ->pageTextContains('Your settings have been saved.');
        $this->assertEquals([
            'Top',
            'First',
            'Second',
            'Bottom',
            'Disabled',
        ], $this->getRegionTitles());
        $this->drupalGet('entity_test/manage/1/edit');
        // No fields are visible, and the regions don't display when empty.
        $this->assertFieldInRegion('field_test_text[0][value]', 'first');
        $this->assertSession()
            ->elementExists('css', '.layout__region--first .field--name-field-test-text');
        // After a refresh the new regions are still there.
        $this->drupalGet('entity_test/structure/entity_test/form-display');
        $this->assertEquals([
            'Top',
            'First',
            'Second',
            'Bottom',
            'Disabled',
        ], $this->getRegionTitles());
        $this->assertSession()
            ->waitForElement('css', '.tabledrag-handle');
        $id = $this->getSession()
            ->getPage()
            ->find('css', '[name="form_build_id"]')
            ->getValue();
        // Drag the field to the second region.
        $field_test_text_row = $this->getSession()
            ->getPage()
            ->find('css', '#field-test-text');
        $second_region_row = $this->getSession()
            ->getPage()
            ->find('css', '.region-second-message');
        $field_test_text_row->find('css', '.handle')
            ->dragTo($second_region_row);
        $this->assertSession()
            ->assertWaitOnAjaxRequest();
        $this->assertSession()
            ->waitForElement('css', "[name='form_build_id']:not([value='{$id}'])");
        $this->submitForm([], 'Save');
        $this->assertSession()
            ->pageTextContains('Your settings have been saved.');
        // The new layout is used.
        $this->drupalGet('entity_test/manage/1/edit');
        $this->assertSession()
            ->elementExists('css', '.layout__region--second .field--name-field-test-text');
        $this->assertFieldInRegion('field_test_text[0][value]', 'second');
        // Tests if this layout works in an embedded context.
        $this->drupalGet('/field-layout-embedded-form');
        $this->assertSession()
            ->elementExists('css', '.layout__region--second .field--name-field-test-text');
        $this->assertFieldInRegion('foo[field_test_text][0][value]', 'second');
        // Move the field to the second region without tabledrag.
        $this->drupalGet('entity_test/structure/entity_test/form-display');
        $this->getSession()
            ->getPage()
            ->pressButton('Show row weights');
        $this->getSession()
            ->getPage()
            ->selectFieldOption('fields[field_test_text][region]', 'second');
        $this->submitForm([], 'Save');
        $this->assertSession()
            ->pageTextContains('Your settings have been saved.');
        // The updated region is used.
        $this->drupalGet('entity_test/manage/1/edit');
        $this->assertFieldInRegion('field_test_text[0][value]', 'second');
        // The layout is still in use without Field UI.
        $this->container
            ->get('module_installer')
            ->uninstall([
            'field_ui',
        ]);
        $this->drupalGet('entity_test/manage/1/edit');
        $this->assertFieldInRegion('field_test_text[0][value]', 'second');
    }
    
    /**
     * Tests the use of field layout for entity view displays.
     */
    public function testEntityView() : void {
        // The one-column layout is in use.
        $this->drupalGet('entity_test/structure/entity_test/display');
        $this->assertEquals([
            'Content',
            'Disabled',
        ], $this->getRegionTitles());
        // Switch the layout to two columns.
        $this->click('#edit-field-layouts');
        $this->getSession()
            ->getPage()
            ->selectFieldOption('field_layout', 'layout_twocol');
        $this->assertSession()
            ->assertWaitOnAjaxRequest();
        $this->submitForm([], 'Save');
        $this->assertSession()
            ->pageTextContains('Your settings have been saved.');
        $this->assertEquals([
            'Top',
            'First',
            'Second',
            'Bottom',
            'Disabled',
        ], $this->getRegionTitles());
        $this->drupalGet('entity_test/1');
        // No fields are visible, and the regions don't display when empty.
        $this->assertSession()
            ->elementNotExists('css', '.layout--twocol');
        $this->assertSession()
            ->elementNotExists('css', '.layout__region');
        $this->assertSession()
            ->pageTextNotContains('The field test text value');
        // After a refresh the new regions are still there.
        $this->drupalGet('entity_test/structure/entity_test/display');
        $this->assertEquals([
            'Top',
            'First',
            'Second',
            'Bottom',
            'Disabled',
        ], $this->getRegionTitles());
        $this->assertSession()
            ->waitForElement('css', '.tabledrag-handle');
        $id = $this->getSession()
            ->getPage()
            ->find('css', '[name="form_build_id"]')
            ->getValue();
        // Drag the field to the first region.
        $this->assertTrue($this->assertSession()
            ->optionExists('fields[field_test_text][region]', 'hidden')
            ->isSelected());
        $field_test_text_row = $this->getSession()
            ->getPage()
            ->find('css', '#field-test-text');
        $first_region_row = $this->getSession()
            ->getPage()
            ->find('css', '.region-first-message');
        $field_test_text_row->find('css', '.handle')
            ->dragTo($first_region_row);
        $this->assertSession()
            ->assertWaitOnAjaxRequest();
        $this->assertFalse($this->assertSession()
            ->optionExists('fields[field_test_text][region]', 'hidden')
            ->isSelected());
        $this->assertSession()
            ->waitForElement('css', "[name='form_build_id']:not([value='{$id}'])");
        $this->submitForm([], 'Save');
        $this->assertSession()
            ->pageTextContains('Your settings have been saved.');
        // The new layout is used.
        $this->drupalGet('entity_test/1');
        $this->assertSession()
            ->elementExists('css', '.layout--twocol');
        $this->assertSession()
            ->elementTextContains('css', '.layout__region--first', 'The field test text value');
        // Move the field to the second region without tabledrag.
        $this->drupalGet('entity_test/structure/entity_test/display');
        $this->getSession()
            ->getPage()
            ->pressButton('Show row weights');
        $this->getSession()
            ->getPage()
            ->selectFieldOption('fields[field_test_text][region]', 'second');
        $this->submitForm([], 'Save');
        $this->assertSession()
            ->pageTextContains('Your settings have been saved.');
        // The updated region is used.
        $this->drupalGet('entity_test/1');
        $this->assertSession()
            ->elementTextContains('css', '.layout__region--second', 'The field test text value');
        // The layout is still in use without Field UI.
        $this->container
            ->get('module_installer')
            ->uninstall([
            'field_ui',
        ]);
        $this->drupalGet('entity_test/1');
        $this->assertSession()
            ->elementExists('css', '.layout--twocol');
        $this->assertSession()
            ->elementTextContains('css', '.layout__region--second', 'The field test text value');
    }
    
    /**
     * Tests layout plugins with forms.
     */
    public function testLayoutForms() : void {
        $this->drupalGet('entity_test/structure/entity_test/display');
        // Switch to a field layout with settings.
        $this->click('#edit-field-layouts');
        // Test switching between layouts with and without forms.
        $this->getSession()
            ->getPage()
            ->selectFieldOption('field_layout', 'layout_test_plugin');
        $this->assertSession()
            ->assertExpectedAjaxRequest(1);
        $this->assertSession()
            ->fieldExists('settings_wrapper[layout_settings][setting_1]');
        $this->getSession()
            ->getPage()
            ->selectFieldOption('field_layout', 'layout_test_2col');
        $this->assertSession()
            ->assertExpectedAjaxRequest(2);
        $this->assertSession()
            ->fieldNotExists('settings_wrapper[layout_settings][setting_1]');
        $this->getSession()
            ->getPage()
            ->selectFieldOption('field_layout', 'layout_test_plugin');
        $this->assertSession()
            ->assertExpectedAjaxRequest(3);
        $this->assertSession()
            ->fieldExists('settings_wrapper[layout_settings][setting_1]');
        // Move the test field to the content region.
        $this->getSession()
            ->getPage()
            ->pressButton('Show row weights');
        $this->getSession()
            ->getPage()
            ->selectFieldOption('fields[field_test_text][region]', 'content');
        $this->submitForm([], 'Save');
        $this->drupalGet('entity_test/1');
        $this->assertSession()
            ->pageTextContains('Blah: Default');
        // Update the field layout settings.
        $this->drupalGet('entity_test/structure/entity_test/display');
        $this->click('#edit-field-layouts');
        $this->getSession()
            ->getPage()
            ->fillField('settings_wrapper[layout_settings][setting_1]', 'Test text');
        $this->submitForm([], 'Save');
        $this->drupalGet('entity_test/1');
        $this->assertSession()
            ->pageTextContains('Blah: Test text');
    }
    
    /**
     * Tests changing the formatter and region at the same time.
     */
    public function testChangingFormatterAndRegion() : void {
        $assert_session = $this->assertSession();
        $page = $this->getSession()
            ->getPage();
        // Add the test field to the content region.
        $this->drupalGet('entity_test/structure/entity_test/display');
        $page->find('css', '#field-test-text .handle')
            ->dragTo($page->find('css', '.region-content-message'));
        $assert_session->assertWaitOnAjaxRequest();
        $page->pressButton('Save');
        $assert_session->fieldValueEquals('fields[field_test_text][region]', 'content');
        $assert_session->fieldValueEquals('fields[field_test_text][type]', 'text_default');
        // Switch the layout to two columns.
        $this->click('#edit-field-layouts');
        $page->selectFieldOption('field_layout', 'layout_twocol');
        $assert_session->assertWaitOnAjaxRequest();
        $page->pressButton('Save');
        $assert_session->fieldValueEquals('fields[field_test_text][region]', 'first');
        // Change the formatter and move to another region.
        $page->selectFieldOption('fields[field_test_text][type]', 'text_trimmed');
        $assert_session->assertWaitOnAjaxRequest();
        $page->find('css', '#field-test-text .handle')
            ->dragTo($page->find('css', '.region-second-message'));
        $assert_session->assertWaitOnAjaxRequest();
        $page->pressButton('Save');
        // Assert that both the formatter and region change are persisted.
        $assert_session->fieldValueEquals('fields[field_test_text][region]', 'second');
        $assert_session->fieldValueEquals('fields[field_test_text][type]', 'text_trimmed');
    }
    
    /**
     * Gets the region titles on the page.
     *
     * @return string[]
     *   An array of region titles.
     */
    protected function getRegionTitles() : array {
        $region_titles = [];
        $region_title_elements = $this->getSession()
            ->getPage()
            ->findAll('css', '.region-title td');
        
        /** @var \Behat\Mink\Element\NodeElement[] $region_title_elements */
        foreach ($region_title_elements as $region_title_element) {
            $region_titles[] = $region_title_element->getText();
        }
        return $region_titles;
    }
    
    /**
     * Asserts that a field exists in a given region.
     *
     * @param string $field_selector
     *   The field selector, one of field id|name|label|value.
     * @param string $region_name
     *   The machine name of the region.
     *
     * @internal
     */
    protected function assertFieldInRegion(string $field_selector, string $region_name) : void {
        $region_element = $this->getSession()
            ->getPage()
            ->find('css', ".layout__region--{$region_name}");
        $this->assertNotNull($region_element);
        $this->assertSession()
            ->fieldExists($field_selector, $region_element);
    }

}

Classes

Title Deprecated Summary
FieldLayoutTest Tests using field layout for entity displays.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.