You are here

CardinalityTest.php in Entity Browser 8

Same filename and directory in other branches
  1. 8.2 tests/src/FunctionalJavascript/CardinalityTest.php

File

tests/src/FunctionalJavascript/CardinalityTest.php
View source
<?php

namespace Drupal\Tests\entity_browser\FunctionalJavascript;

use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\entity_browser\Element\EntityBrowserElement;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\user\Entity\Role;

/**
 * Tests the Cardinality handling.
 *
 * @group entity_browser
 */
class CardinalityTest extends EntityBrowserWebDriverTestBase {

  /**
   * Modules to enable.
   *
   * @var array
   */
  public static $modules = [
    'entity_browser_test',
    'embed',
    'entity_embed',
    'entity_browser_entity_embed_test',
    'inline_entity_form',
    'entity_browser_ief_test',
  ];

  /**
   * {@inheritdoc}
   */
  public function setUp() {
    parent::setUp();

    /** @var \Drupal\user\RoleInterface $role */
    $role = Role::load('authenticated');
    $this
      ->grantPermissions($role, [
      'access cardinality entity browser pages',
      'bypass node access',
      'administer node form display',
      'access content',
    ]);
  }

  /**
   * Tests Entity Reference widget.
   */
  public function testEntityReferenceWidget() {

    // Create an entity_reference field to test the widget.
    $field_storage = FieldStorageConfig::create([
      'field_name' => 'field_fellowship',
      'type' => 'entity_reference',
      'entity_type' => 'node',
      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
      'settings' => [
        'target_type' => 'node',
      ],
    ]);
    $field_storage
      ->save();
    $field = FieldConfig::create([
      'field_name' => 'field_fellowship',
      'entity_type' => 'node',
      'bundle' => 'article',
      'label' => 'Referenced articles',
      'settings' => [
        'handler' => 'default:node',
        'handler_settings' => [
          'target_bundles' => [
            'article' => 'article',
            'shark' => 'shark',
            'jet' => 'jet',
          ],
        ],
      ],
    ]);
    $field
      ->save();

    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
    $form_display = $this->container
      ->get('entity_type.manager')
      ->getStorage('entity_form_display')
      ->load('node.article.default');
    $form_display
      ->setComponent('field_fellowship', [
      'type' => 'entity_browser_entity_reference',
      'settings' => [
        'entity_browser' => 'cardinality',
        'open' => TRUE,
        'field_widget_edit' => TRUE,
        'field_widget_remove' => TRUE,
        'field_widget_replace' => TRUE,
        'selection_mode' => EntityBrowserElement::SELECTION_MODE_APPEND,
        'field_widget_display' => 'label',
        'field_widget_display_settings' => [],
      ],
    ])
      ->save();
    $gollum = $this
      ->createNode([
      'type' => 'shark',
      'title' => 'Gollum',
    ]);
    $aragorn = $this
      ->createNode([
      'type' => 'jet',
      'title' => 'Aragorn',
    ]);
    $gandolf = $this
      ->createNode([
      'type' => 'article',
      'title' => 'Gandolf',
    ]);
    $legolas = $this
      ->createNode([
      'type' => 'article',
      'title' => 'Legolas',
    ]);
    $boromir = $this
      ->createNode([
      'type' => 'article',
      'title' => 'Boromir',
    ]);

    // Test the cardinality handling.
    $role = Role::load('authenticated');
    $this
      ->grantPermissions($role, [
      'access cardinality entity browser pages',
      'bypass node access',
      'administer node form display',
    ]);
    FieldStorageConfig::load('node.field_fellowship')
      ->setCardinality(2)
      ->save();

    // Without using field cardinality, the view should contain checkboxes.
    // Set view to use field cardinality.
    $this
      ->config('views.view.bundle_filter_exposed')
      ->set('display.default.display_options.fields.entity_browser_select.use_field_cardinality', FALSE)
      ->save();
    $this
      ->drupalGet('/node/add/article');
    $this
      ->assertSession()
      ->fieldExists('title[0][value]')
      ->setValue('Le Seigneur des anneaux');
    $this
      ->openIframe();
    $gollum_checkbox = $this
      ->assertCheckboxExistsByValue('node:' . $gollum
      ->id());
    $gollum_checkbox
      ->check();
    $aragorn_checkbox = $this
      ->assertCheckboxExistsByValue('node:' . $aragorn
      ->id());
    $aragorn_checkbox
      ->check();
    $this
      ->assertTrue($gollum_checkbox
      ->isChecked());
    $this
      ->assertTrue($aragorn_checkbox
      ->isChecked());

    // If using field cardinality and field cardinality is greater than 1 then
    // there should be still checkboxes.
    $this
      ->config('views.view.bundle_filter_exposed')
      ->set('display.default.display_options.fields.entity_browser_select.use_field_cardinality', TRUE)
      ->save();
    $this
      ->drupalGet('/node/add/article');
    $this
      ->openIframe();
    $gollum_checkbox = $this
      ->assertCheckboxExistsByValue('node:' . $gollum
      ->id());
    $aragorn_checkbox = $this
      ->assertCheckboxExistsByValue('node:' . $aragorn
      ->id());
    $gandolf_checkbox = $this
      ->assertCheckboxExistsByValue('node:' . $gandolf
      ->id());
    $this
      ->assertCheckboxExistsByValue('node:' . $legolas
      ->id());
    $this
      ->assertCheckboxExistsByValue('node:' . $boromir
      ->id());

    // If we attempt to select 3 nodes, Entity Browser should prevent it and
    // return an error message.
    $gollum_checkbox
      ->check();
    $aragorn_checkbox
      ->check();
    $gandolf_checkbox
      ->check();
    $this
      ->assertSession()
      ->buttonExists('Select entities')
      ->press();
    $this
      ->waitForAjaxToFinish();
    $this
      ->assertSession()
      ->pageTextContains('You can only select up to 2 items');

    // If we change the cardinality to 1, we should have radios.
    FieldStorageConfig::load('node.field_fellowship')
      ->setCardinality(1)
      ->save();
    $this
      ->drupalGet('/node/add/article');
    $this
      ->openIframe();
    $gollum_radio = $this
      ->assertRadioExistsByValue('node:' . $gollum
      ->id());
    $gollum_radio
      ->click();
    $this
      ->assertSession()
      ->buttonExists('Select entities')
      ->press();
    $this
      ->getSession()
      ->switchToIFrame();
    $this
      ->waitForAjaxToFinish();

    // Assert the selected entity.
    $this
      ->assertSession()
      ->pageTextContains('Gollum');

    // Attempt to select more than one element.
    $this
      ->assertSession()
      ->buttonExists('Replace')
      ->press();
    $this
      ->waitForAjaxToFinish();
    $this
      ->getSession()
      ->switchToIFrame('entity_browser_iframe_cardinality');
    $this
      ->waitForAjaxToFinish();
    $gollum_radio = $this
      ->assertRadioExistsByValue('node:' . $gollum
      ->id());
    $gollum_radio
      ->click();
    $gandolf_radio = $this
      ->assertRadioExistsByValue('node:' . $gandolf
      ->id());
    $gandolf_radio
      ->click();
    $this
      ->assertFalse($gollum_radio
      ->isSelected());
    $this
      ->assertTrue($gandolf_radio
      ->isSelected());
    $this
      ->assertSession()
      ->buttonExists('Select entities')
      ->press();
    $this
      ->getSession()
      ->switchToIFrame();
    $this
      ->waitForAjaxToFinish();

    // Assert the selected entity.
    $this
      ->assertSession()
      ->pageTextContains('Gandolf');
    $this
      ->assertSession()
      ->pageTextNotContains('Gollum');
    $this
      ->assertSession()
      ->buttonExists('Replace')
      ->press();
    $this
      ->waitForAjaxToFinish();
    $this
      ->getSession()
      ->switchToIFrame('entity_browser_iframe_cardinality');
    $this
      ->waitForAjaxToFinish();

    // Test that cardinality setting persists when using exposed filters form,
    // When applying the exposed filters, the radios should persist.
    $this
      ->assertSession()
      ->selectExists('Type')
      ->selectOption('jet');
    $this
      ->assertSession()
      ->buttonExists('Apply')
      ->press();
    $this
      ->assertSession()
      ->assertWaitOnAjaxRequest();
    $this
      ->assertRadioExistsByValue('node:' . $aragorn
      ->id());
    $this
      ->assertRadioNotExistsByValue('node:' . $legolas
      ->id());
    $this
      ->assertSession()
      ->selectExists('Type')
      ->selectOption('shark');
    $this
      ->assertSession()
      ->buttonExists('Apply')
      ->press();
    $this
      ->assertSession()
      ->assertWaitOnAjaxRequest();
    $this
      ->assertRadioExistsByValue('node:' . $gollum
      ->id());
    $this
      ->assertRadioNotExistsByValue('node:' . $aragorn
      ->id());
  }

  /**
   * Tests cardinality functionality using Entity Embed button.
   */
  public function testEntityEmbed() {
    $this
      ->config('entity_browser.browser.bundle_filter')
      ->set('widgets.b882a89d-9ce4-4dfe-9802-62df93af232a.settings.view', 'bundle_filter_exposed')
      ->save();
    $role = Role::load('authenticated');
    $this
      ->grantPermissions($role, [
      'access content',
      'use text format full_html',
      'create test_entity_embed content',
      'access bundle_filter entity browser pages',
    ]);
    FieldStorageConfig::load('node.field_nodes')
      ->setCardinality(1)
      ->save();
    $westley = $this
      ->createNode([
      'type' => 'shark',
      'title' => 'Westley',
    ]);
    $buttercup = $this
      ->createNode([
      'type' => 'jet',
      'title' => 'Buttercup',
    ]);
    $humperdinck = $this
      ->createNode([
      'type' => 'article',
      'title' => 'Humperdinck',
    ]);
    $this
      ->drupalGet('/node/add/test_entity_embed');
    $this
      ->assertSession()
      ->waitForElement('css', 'a.cke_button__bundle_filter_test')
      ->click();
    $this
      ->assertSession()
      ->waitForElementVisible('xpath', "//iframe[contains(@name, 'entity_browser_iframe_bundle_filter')]", 3000);
    $this
      ->getSession()
      ->switchToIFrame('entity_browser_iframe_bundle_filter');
    $this
      ->assertSession()
      ->waitForElementVisible('xpath', "//div[contains(@class, 'views-exposed-form')]");

    // Without use_field_cardinality set, there should be checkboxes, the default.
    $this
      ->assertCheckBoxExistsByValue('node:' . $westley
      ->id());
    $this
      ->assertCheckBoxExistsByValue('node:' . $buttercup
      ->id());
    $this
      ->assertCheckBoxNotExistsByValue('node:' . $humperdinck
      ->id());

    // Set view to use field cardinality.
    $this
      ->config('views.view.bundle_filter_exposed')
      ->set('display.default.display_options.fields.entity_browser_select.use_field_cardinality', TRUE)
      ->save();
    $this
      ->drupalGet('/node/add/test_entity_embed');
    $this
      ->assertSession()
      ->waitForElement('css', 'a.cke_button__bundle_filter_test')
      ->click();
    $this
      ->assertSession()
      ->waitForElementVisible('xpath', "//iframe[contains(@name, 'entity_browser_iframe_bundle_filter')]", 3000);
    $this
      ->getSession()
      ->switchToIFrame('entity_browser_iframe_bundle_filter');
    $this
      ->assertSession()
      ->waitForElementVisible('xpath', "//div[contains(@class, 'views-exposed-form')]");

    // With use_field_cardinality set to true, there should be radios, since
    // cardinality on entity embed is always 1.
    $this
      ->assertRadioExistsByValue('node:' . $westley
      ->id());
    $this
      ->assertRadioExistsByValue('node:' . $buttercup
      ->id());
    $this
      ->assertRadioNotExistsByValue('node:' . $humperdinck
      ->id());

    // Test that cardinality setting persists when using exposed filters form.
    // When applying the exposed filters, the radios should persist.
    $this
      ->assertSession()
      ->selectExists('Type')
      ->selectOption('jet');
    $this
      ->assertSession()
      ->buttonExists('Apply')
      ->press();
    $this
      ->assertSession()
      ->assertWaitOnAjaxRequest();
    $this
      ->assertRadioNotExistsByValue('node:' . $westley
      ->id());
    $this
      ->assertRadioExistsByValue('node:' . $buttercup
      ->id());
    $this
      ->assertRadioNotExistsByValue('node:' . $humperdinck
      ->id());
    $this
      ->assertSession()
      ->selectExists('Type')
      ->selectOption('shark');
    $this
      ->assertSession()
      ->buttonExists('Apply')
      ->press();
    $this
      ->assertSession()
      ->assertWaitOnAjaxRequest();
    $this
      ->assertRadioExistsByValue('node:' . $westley
      ->id());
    $this
      ->assertRadioNotExistsByValue('node:' . $buttercup
      ->id());
    $this
      ->assertRadioNotExistsByValue('node:' . $humperdinck
      ->id());
  }

  /**
   * Tests cardinality functionality using Inline Entity Form.
   */
  public function testInlineEntityForm() {

    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
    $form_display = $this->container
      ->get('entity_type.manager')
      ->getStorage('entity_form_display')
      ->load('node.ief_content.default');
    $field_nodes = $form_display
      ->getComponent('field_nodes');
    $field_nodes['third_party_settings']['entity_browser_entity_form']['entity_browser_id'] = 'cardinality';
    $form_display
      ->setComponent('field_nodes', $field_nodes);
    $form_display
      ->save();

    // Set auto open to TRUE on the entity browser.
    $entity_browser = $this->container
      ->get('entity_type.manager')
      ->getStorage('entity_browser')
      ->load('cardinality');
    $display_configuration = $entity_browser
      ->get('display_configuration');
    $display_configuration['auto_open'] = TRUE;
    $entity_browser
      ->set('display_configuration', $display_configuration);
    $entity_browser
      ->save();
    $vizzini = $this
      ->createNode([
      'type' => 'shark',
      'title' => 'Vizzini',
    ]);
    $inigo = $this
      ->createNode([
      'type' => 'jet',
      'title' => 'Inigo',
    ]);
    $miracle_max = $this
      ->createNode([
      'type' => 'article',
      'title' => 'Miracle Max',
    ]);
    $this
      ->drupalGet('node/add/ief_content');
    $page = $this
      ->getSession()
      ->getPage();
    $page
      ->pressButton('Add existing node');
    $this
      ->assertSession()
      ->assertWaitOnAjaxRequest();
    $this
      ->getSession()
      ->switchToIFrame('entity_browser_iframe_cardinality');

    // Without use_field_cardinality set, there should be checkboxes, the default.
    $this
      ->assertCheckBoxExistsByValue('node:' . $vizzini
      ->id());
    $this
      ->assertCheckBoxExistsByValue('node:' . $inigo
      ->id());
    $this
      ->assertCheckBoxNotExistsByValue('node:' . $miracle_max
      ->id());
    $view = $this
      ->config('views.view.bundle_filter_exposed');
    $field = $view
      ->get('display.default.display_options.fields.entity_browser_select', TRUE);
    $field['use_field_cardinality'] = TRUE;
    $view
      ->set('display.default.display_options.fields.entity_browser_select', $field);
    $view
      ->save();
    FieldStorageConfig::load('node.field_nodes')
      ->setCardinality(1)
      ->save();
    $this
      ->drupalGet('node/add/ief_content');
    $page = $this
      ->getSession()
      ->getPage();
    $page
      ->pressButton('Add existing node');
    $this
      ->assertSession()
      ->assertWaitOnAjaxRequest();
    $this
      ->getSession()
      ->switchToIFrame('entity_browser_iframe_cardinality');

    // With use_field_cardinality set to true, and cardinality set to 1,
    // there should be radios.
    $this
      ->assertRadioExistsByValue('node:' . $vizzini
      ->id());
    $this
      ->assertRadioExistsByValue('node:' . $inigo
      ->id());
    $this
      ->assertRadioNotExistsByValue('node:' . $miracle_max
      ->id());

    // Test that cardinality setting persists when using exposed filters form.
    // When applying the exposed filters, the radios should persist.
    $this
      ->assertSession()
      ->selectExists('Type')
      ->selectOption('jet');
    $this
      ->assertSession()
      ->buttonExists('Apply')
      ->press();
    $this
      ->assertSession()
      ->assertWaitOnAjaxRequest();
    $this
      ->assertRadioNotExistsByValue('node:' . $vizzini
      ->id());
    $this
      ->assertRadioExistsByValue('node:' . $inigo
      ->id());
    $this
      ->assertRadioNotExistsByValue('node:' . $miracle_max
      ->id());
    $this
      ->assertSession()
      ->selectExists('Type')
      ->selectOption('shark');
    $this
      ->assertSession()
      ->buttonExists('Apply')
      ->press();
    $this
      ->assertSession()
      ->assertWaitOnAjaxRequest();
    $this
      ->assertRadioExistsByValue('node:' . $vizzini
      ->id());
    $this
      ->assertRadioNotExistsByValue('node:' . $inigo
      ->id());
    $this
      ->assertRadioNotExistsByValue('node:' . $miracle_max
      ->id());
  }

  /**
   * Helper function for repetitive task.
   *
   * @throws \Behat\Mink\Exception\ElementNotFoundException
   */
  protected function openIframe() {
    $open_iframe_link = $this
      ->assertSession()
      ->elementExists('css', 'a[data-drupal-selector="edit-field-fellowship-entity-browser-entity-browser-link"]');
    $open_iframe_link
      ->click();
    $this
      ->waitForAjaxToFinish();
    $this
      ->getSession()
      ->switchToIFrame('entity_browser_iframe_cardinality');
    $this
      ->waitForAjaxToFinish();
  }

}

Classes

Namesort descending Description
CardinalityTest Tests the Cardinality handling.