You are here

public function EntityReferenceWidgetTest::testEntityReferenceWidget in Entity Browser 8

Same name and namespace in other branches
  1. 8.2 tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php \Drupal\Tests\entity_browser\FunctionalJavascript\EntityReferenceWidgetTest::testEntityReferenceWidget()

Tests Entity Reference widget.

File

tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php, line 39

Class

EntityReferenceWidgetTest
Tests the Entity Reference Widget.

Namespace

Drupal\Tests\entity_browser\FunctionalJavascript

Code

public function testEntityReferenceWidget() {

  // Create an entity_reference field to test the widget.
  $field_storage = FieldStorageConfig::create([
    'field_name' => 'field_entity_reference1',
    'type' => 'entity_reference',
    'entity_type' => 'node',
    'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
    'settings' => [
      'target_type' => 'node',
    ],
  ]);
  $field_storage
    ->save();
  $field = FieldConfig::create([
    'field_name' => 'field_entity_reference1',
    'entity_type' => 'node',
    'bundle' => 'article',
    'label' => 'Referenced articles',
    'settings' => [],
  ]);
  $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_entity_reference1', [
    'type' => 'entity_browser_entity_reference',
    'settings' => [
      'entity_browser' => 'test_entity_browser_iframe_node_view',
      'open' => TRUE,
      'field_widget_edit' => TRUE,
      'field_widget_remove' => TRUE,
      'field_widget_replace' => FALSE,
      'selection_mode' => EntityBrowserElement::SELECTION_MODE_APPEND,
      'field_widget_display' => 'rendered_entity',
      'field_widget_display_settings' => [
        'view_mode' => 'teaser',
      ],
    ],
  ])
    ->save();

  // Create a dummy node that will be used as target.
  $target_node = Node::create([
    'title' => 'Walrus',
    'type' => 'article',
  ]);
  $target_node
    ->save();
  $target_node_translation = $target_node
    ->addTranslation('fr', $target_node
    ->toArray());
  $target_node_translation
    ->setTitle('le Morse');
  $target_node_translation
    ->save();
  $this
    ->drupalGet('/node/add/article');
  $this
    ->assertSession()
    ->fieldExists('title[0][value]')
    ->setValue('Referencing node 1');
  $this
    ->getSession()
    ->switchToIFrame('entity_browser_iframe_test_entity_browser_iframe_node_view');
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->fieldExists('entity_browser_select[node:1]')
    ->check();
  $this
    ->assertSession()
    ->buttonExists('Select entities')
    ->press();
  $this
    ->getSession()
    ->switchToIFrame();
  $this
    ->assertTrue($this
    ->assertSession()
    ->waitForText('Walrus'));
  $this
    ->assertSession()
    ->buttonExists('Save')
    ->press();
  $this
    ->assertSession()
    ->pageTextContains('Article Referencing node 1 has been created.');
  $nid = $this->container
    ->get('entity.query')
    ->get('node')
    ->condition('title', 'Referencing node 1')
    ->execute();
  $nid = reset($nid);

  // Assert correct translation appears.
  // @see Drupal\entity_browser\Plugin\EntityBrowser\FieldWidgetDisplay\EntityLabel
  $this
    ->drupalGet('fr/node/' . $nid . '/edit');
  $this
    ->assertSession()
    ->pageTextContains('le Morse');
  $this
    ->drupalGet('node/' . $nid . '/edit');
  $this
    ->assertSession()
    ->pageTextContains('Walrus');

  // Make sure both "Edit" and "Remove" buttons are visible.
  $this
    ->assertSession()
    ->buttonExists('edit-field-entity-reference1-current-items-0-remove-button');
  $this
    ->assertSession()
    ->buttonExists('edit-field-entity-reference1-current-items-0-edit-button')
    ->press();

  // Make sure the contextual links are not present.
  $this
    ->assertSession()
    ->elementNotExists('css', '.contextual-links');

  // Test edit dialog by changing title of referenced entity.
  $edit_dialog = $this
    ->assertSession()
    ->waitForElement('xpath', '//div[contains(@id, "node-' . $target_node
    ->id() . '-edit-dialog")]');
  $title_field = $edit_dialog
    ->findField('title[0][value]');
  $title = $title_field
    ->getValue();
  $this
    ->assertEquals('Walrus', $title);
  $title_field
    ->setValue('Alpaca');
  $this
    ->assertSession()
    ->elementExists('css', '.ui-dialog-buttonset.form-actions .form-submit')
    ->press();
  $this
    ->waitForAjaxToFinish();

  // Check that new title is displayed.
  $this
    ->assertSession()
    ->pageTextNotContains('Walrus');
  $this
    ->assertSession()
    ->pageTextContains('Alpaca');

  // Test whether changing these definitions on the browser config effectively
  // change the visibility of the buttons.
  $form_display
    ->setComponent('field_entity_reference1', [
    'type' => 'entity_browser_entity_reference',
    'settings' => [
      'entity_browser' => 'test_entity_browser_iframe_node_view',
      'open' => TRUE,
      'field_widget_edit' => FALSE,
      'field_widget_remove' => FALSE,
      'field_widget_replace' => FALSE,
      'selection_mode' => EntityBrowserElement::SELECTION_MODE_APPEND,
      'field_widget_display' => 'label',
      'field_widget_display_settings' => [],
    ],
  ])
    ->save();
  $this
    ->drupalGet('node/' . $nid . '/edit');
  $this
    ->assertSession()
    ->buttonNotExists('edit-field-entity-reference1-current-items-0-remove-button');
  $this
    ->assertSession()
    ->buttonNotExists('edit-field-entity-reference1-current-items-0-edit-button');

  // Set them to visible again.
  $form_display
    ->setComponent('field_entity_reference1', [
    'type' => 'entity_browser_entity_reference',
    'settings' => [
      'entity_browser' => 'test_entity_browser_iframe_node_view',
      'open' => TRUE,
      'field_widget_edit' => TRUE,
      'field_widget_remove' => TRUE,
      'field_widget_replace' => FALSE,
      'selection_mode' => EntityBrowserElement::SELECTION_MODE_APPEND,
      'field_widget_display' => 'label',
      'field_widget_display_settings' => [],
    ],
  ])
    ->save();
  $this
    ->drupalGet('node/' . $nid . '/edit');
  $remove_button = $this
    ->assertSession()
    ->buttonExists('edit-field-entity-reference1-current-items-0-remove-button');
  $this
    ->assertEquals('Remove', $remove_button
    ->getValue());
  $this
    ->assertTrue($remove_button
    ->hasClass('remove-button'));
  $edit_button = $this
    ->assertSession()
    ->buttonExists('edit-field-entity-reference1-current-items-0-edit-button');
  $this
    ->assertEquals('Edit', $edit_button
    ->getValue());
  $this
    ->assertTrue($edit_button
    ->hasClass('edit-button'));

  // Make sure the "Replace" button is not there.
  $this
    ->assertSession()
    ->buttonNotExists('edit-field-entity-reference1-current-items-0-replace-button');

  // Test the "Remove" button on the widget works.
  $this
    ->assertSession()
    ->buttonExists('Remove')
    ->press();
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->pageTextNotContains('Alpaca');

  // Test the "Replace" button functionality.
  $form_display
    ->setComponent('field_entity_reference1', [
    'type' => 'entity_browser_entity_reference',
    'settings' => [
      'entity_browser' => 'test_entity_browser_iframe_node_view',
      '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();

  // In order to ensure the replace button opens the browser, it needs to be
  // closed.

  /** @var \Drupal\entity_browser\EntityBrowserInterface $browser */
  $browser = $this->container
    ->get('entity_type.manager')
    ->getStorage('entity_browser')
    ->load('test_entity_browser_iframe_node_view');
  $browser
    ->getDisplay()
    ->setConfiguration([
    'width' => 650,
    'height' => 500,
    'link_text' => 'Select entities',
    'auto_open' => FALSE,
  ]);
  $browser
    ->save();

  // We'll need a third node to be able to make a new selection.
  $target_node2 = Node::create([
    'title' => 'Target example node 2',
    'type' => 'article',
  ]);
  $target_node2
    ->save();
  $this
    ->drupalGet('node/' . $nid . '/edit');

  // If there is only one entity in the current selection the button should
  // show up.
  $replace_button = $this
    ->assertSession()
    ->buttonExists('edit-field-entity-reference1-current-items-0-replace-button');
  $this
    ->assertEquals('Replace', $replace_button
    ->getValue());
  $this
    ->assertTrue($replace_button
    ->hasClass('replace-button'));

  // Clicking on the button should empty the selection and automatically
  // open the browser again.
  $replace_button
    ->click();
  $this
    ->waitForAjaxToFinish();
  $this
    ->getSession()
    ->switchToIFrame('entity_browser_iframe_test_entity_browser_iframe_node_view');
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->fieldExists('entity_browser_select[node:3]')
    ->check();
  $this
    ->assertSession()
    ->buttonExists('Select entities')
    ->press();
  $this
    ->getSession()
    ->wait(1000);
  $this
    ->getSession()
    ->switchToIFrame();
  $this
    ->waitForAjaxToFinish();

  // Even in the AJAX-built markup for the newly selected element, the replace
  // button should be there.
  $this
    ->assertSession()
    ->elementExists('css', 'input[data-drupal-selector="edit-field-entity-reference1-current-items-0-replace-button"]');

  // Adding a new node to the selection, however, should make it disappear.
  $open_iframe_link = $this
    ->assertSession()
    ->elementExists('css', 'a[data-drupal-selector="edit-field-entity-reference1-entity-browser-entity-browser-link"]');
  $open_iframe_link
    ->click();
  $this
    ->waitForAjaxToFinish();
  $this
    ->getSession()
    ->switchToIFrame('entity_browser_iframe_test_entity_browser_iframe_node_view');
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->fieldExists('entity_browser_select[node:1]')
    ->check();
  $this
    ->assertSession()
    ->buttonExists('Select entities')
    ->press();
  $this
    ->getSession()
    ->wait(1000);
  $this
    ->getSession()
    ->switchToIFrame();
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->elementNotExists('css', 'input[data-drupal-selector="edit-field-entity-reference1-current-items-0-replace-button"]');
  $this
    ->assertSession()
    ->buttonExists('Save')
    ->press();
  $this
    ->assertSession()
    ->pageTextContains('Article Referencing node 1 has been updated.');

  // Test the replace button again with different field cardinalities.
  FieldStorageConfig::load('node.field_entity_reference1')
    ->setCardinality(1)
    ->save();
  $this
    ->drupalGet('/node/add/article');
  $this
    ->assertSession()
    ->fieldExists('title[0][value]')
    ->setValue('Referencing node 2');
  $open_iframe_link = $this
    ->assertSession()
    ->elementExists('css', 'a[data-drupal-selector="edit-field-entity-reference1-entity-browser-entity-browser-link"]');
  $open_iframe_link
    ->click();
  $this
    ->waitForAjaxToFinish();
  $this
    ->getSession()
    ->switchToIFrame('entity_browser_iframe_test_entity_browser_iframe_node_view');
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->fieldExists('entity_browser_select[node:1]')
    ->check();
  $this
    ->assertSession()
    ->buttonExists('Select entities')
    ->press();
  $this
    ->getSession()
    ->wait(1000);
  $this
    ->getSession()
    ->switchToIFrame();
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->elementContains('css', '#edit-field-entity-reference1-wrapper', 'Alpaca');

  // All three buttons should be visible.
  $this
    ->assertSession()
    ->elementExists('css', 'input[data-drupal-selector="edit-field-entity-reference1-current-items-0-remove-button"]');
  $this
    ->assertSession()
    ->elementExists('css', 'input[data-drupal-selector="edit-field-entity-reference1-current-items-0-edit-button"]');
  $replace_button = $this
    ->assertSession()
    ->elementExists('css', 'input[data-drupal-selector="edit-field-entity-reference1-current-items-0-replace-button"]');

  // Clicking on the button should empty the selection and automatically
  // open the browser again.
  $replace_button
    ->click();
  $this
    ->waitForAjaxToFinish();
  $this
    ->getSession()
    ->switchToIFrame('entity_browser_iframe_test_entity_browser_iframe_node_view');
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->fieldExists('entity_browser_select[node:2]')
    ->check();
  $this
    ->assertSession()
    ->buttonExists('Select entities')
    ->press();
  $this
    ->getSession()
    ->wait(1000);
  $this
    ->getSession()
    ->switchToIFrame();
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->elementContains('css', '#edit-field-entity-reference1-wrapper', 'Referencing node 1');

  // Do the same as above but now with cardinality 2.
  FieldStorageConfig::load('node.field_entity_reference1')
    ->setCardinality(2)
    ->save();
  $this
    ->drupalGet('/node/add/article');
  $this
    ->assertSession()
    ->fieldExists('title[0][value]')
    ->setValue('Referencing node 3');
  $open_iframe_link = $this
    ->assertSession()
    ->elementExists('css', 'a[data-drupal-selector="edit-field-entity-reference1-entity-browser-entity-browser-link"]');
  $open_iframe_link
    ->click();
  $this
    ->waitForAjaxToFinish();
  $this
    ->getSession()
    ->switchToIFrame('entity_browser_iframe_test_entity_browser_iframe_node_view');
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->fieldExists('entity_browser_select[node:1]')
    ->check();
  $this
    ->assertSession()
    ->buttonExists('Select entities')
    ->press();
  $this
    ->getSession()
    ->wait(1000);
  $this
    ->getSession()
    ->switchToIFrame();
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->elementContains('css', '#edit-field-entity-reference1-wrapper', 'Alpaca');

  // All three buttons should be visible.
  $this
    ->assertSession()
    ->elementExists('css', 'input[data-drupal-selector="edit-field-entity-reference1-current-items-0-remove-button"]');
  $this
    ->assertSession()
    ->elementExists('css', 'input[data-drupal-selector="edit-field-entity-reference1-current-items-0-edit-button"]');
  $replace_button = $this
    ->assertSession()
    ->elementExists('css', 'input[data-drupal-selector="edit-field-entity-reference1-current-items-0-replace-button"]');

  // Clicking on the button should empty the selection and automatically
  // open the browser again.
  $replace_button
    ->click();
  $this
    ->waitForAjaxToFinish();
  $this
    ->getSession()
    ->switchToIFrame('entity_browser_iframe_test_entity_browser_iframe_node_view');
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->fieldExists('entity_browser_select[node:2]')
    ->check();
  $this
    ->assertSession()
    ->buttonExists('Select entities')
    ->press();
  $this
    ->getSession()
    ->wait(1000);
  $this
    ->getSession()
    ->switchToIFrame();
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->elementContains('css', '#edit-field-entity-reference1-wrapper', 'Referencing node 1');

  // Verify that if the user cannot edit the entity, the "Edit" button does
  // not show up, even if configured to.

  /** @var \Drupal\user\RoleInterface $role */
  $role = Role::load('authenticated');
  $role
    ->revokePermission('bypass node access')
    ->trustData()
    ->save();
  $this
    ->drupalGet('node/add/article');
  $open_iframe_link = $this
    ->assertSession()
    ->elementExists('css', 'a[data-drupal-selector="edit-field-entity-reference1-entity-browser-entity-browser-link"]');
  $open_iframe_link
    ->click();
  $this
    ->waitForAjaxToFinish();
  $this
    ->getSession()
    ->switchToIFrame('entity_browser_iframe_test_entity_browser_iframe_node_view');
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->fieldExists('entity_browser_select[node:1]')
    ->check();
  $this
    ->assertSession()
    ->buttonExists('Select entities')
    ->press();
  $this
    ->getSession()
    ->switchToIFrame();
  $this
    ->waitForAjaxToFinish();
  $this
    ->assertSession()
    ->buttonNotExists('edit-field-entity-reference1-current-items-0-edit-button');
}