Pull merge.
[yaffs-website] / web / core / modules / field / tests / src / FunctionalJavascript / EntityReference / EntityReferenceAdminTest.php
1 <?php
2
3 namespace Drupal\Tests\field\FunctionalJavascript\EntityReference;
4
5 use Behat\Mink\Element\NodeElement;
6 use Drupal\Component\Render\FormattableMarkup;
7 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
8 use Drupal\Tests\field_ui\Traits\FieldUiTestTrait;
9
10 /**
11  * Tests for the administrative UI.
12  *
13  * @group entity_reference
14  */
15 class EntityReferenceAdminTest extends WebDriverTestBase {
16
17   use FieldUiTestTrait;
18
19   /**
20    * Modules to install.
21    *
22    * Enable path module to ensure that the selection handler does not fail for
23    * entities with a path field.
24    *
25    * @var array
26    */
27   public static $modules = ['node', 'field_ui', 'path', 'taxonomy', 'block', 'views_ui'];
28
29   /**
30    * The name of the content type created for testing purposes.
31    *
32    * @var string
33    */
34   protected $type;
35
36   /**
37    * {@inheritdoc}
38    */
39   protected function setUp() {
40     parent::setUp();
41     $this->drupalPlaceBlock('system_breadcrumb_block');
42
43     // Create a content type, with underscores.
44     $type_name = strtolower($this->randomMachineName(8)) . '_test';
45     $type = $this->drupalCreateContentType(['name' => $type_name, 'type' => $type_name]);
46     $this->type = $type->id();
47
48     // Create test user.
49     $admin_user = $this->drupalCreateUser([
50       'access content',
51       'administer node fields',
52       'administer node display',
53       'administer views',
54       'create ' . $type_name . ' content',
55       'edit own ' . $type_name . ' content',
56     ]);
57     $this->drupalLogin($admin_user);
58   }
59
60   /**
61    * Tests the Entity Reference Admin UI.
62    */
63   public function testFieldAdminHandler() {
64     $bundle_path = 'admin/structure/types/manage/' . $this->type;
65
66     $page = $this->getSession()->getPage();
67     $assert_session = $this->assertSession();
68
69     // First step: 'Add new field' on the 'Manage fields' page.
70     $this->drupalGet($bundle_path . '/fields/add-field');
71
72     // Check if the commonly referenced entity types appear in the list.
73     $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:node');
74     $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:user');
75
76     $page->findField('new_storage_type')->setValue('entity_reference');
77     $assert_session->waitForField('label')->setValue('Test');
78     $machine_name = $assert_session->waitForElement('xpath', '//*[@id="edit-label-machine-name-suffix"]/span[2]/span[contains(text(), "field_test")]');
79     $this->assertNotEmpty($machine_name);
80     $page->pressButton('Save and continue');
81
82     // Node should be selected by default.
83     $this->assertFieldByName('settings[target_type]', 'node');
84
85     // Check that all entity types can be referenced.
86     $this->assertFieldSelectOptions('settings[target_type]', array_keys(\Drupal::entityManager()->getDefinitions()));
87
88     // Second step: 'Field settings' form.
89     $this->drupalPostForm(NULL, [], t('Save field settings'));
90
91     // The base handler should be selected by default.
92     $this->assertFieldByName('settings[handler]', 'default:node');
93
94     // The base handler settings should be displayed.
95     $entity_type_id = 'node';
96     // Check that the type label is correctly displayed.
97     $assert_session->pageTextContains('Content type');
98     $bundles = $this->container->get('entity_type.bundle.info')->getBundleInfo($entity_type_id);
99     foreach ($bundles as $bundle_name => $bundle_info) {
100       $this->assertFieldByName('settings[handler_settings][target_bundles][' . $bundle_name . ']');
101     }
102
103     reset($bundles);
104
105     // Test the sort settings.
106     // Option 0: no sort.
107     $this->assertFieldByName('settings[handler_settings][sort][field]', '_none');
108     $this->assertNoFieldByName('settings[handler_settings][sort][direction]');
109     // Option 1: sort by field.
110     $page->findField('settings[handler_settings][sort][field]')->setValue('nid');
111     $assert_session->waitForField('settings[handler_settings][sort][direction]');
112     $this->assertFieldByName('settings[handler_settings][sort][direction]', 'ASC');
113
114     // Test that a non-translatable base field is a sort option.
115     $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='nid']");
116     // Test that a translatable base field is a sort option.
117     $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='title']");
118     // Test that a configurable field is a sort option.
119     $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='body.value']");
120
121     // Set back to no sort.
122     $page->findField('settings[handler_settings][sort][field]')->setValue('_none');
123     $assert_session->assertWaitOnAjaxRequest();
124     $this->assertNoFieldByName('settings[handler_settings][sort][direction]');
125
126     // Third step: confirm.
127     $page->findField('settings[handler_settings][target_bundles][' . key($bundles) . ']')->setValue(key($bundles));
128     $assert_session->assertWaitOnAjaxRequest();
129     $this->drupalPostForm(NULL, [
130       'required' => '1',
131     ], t('Save settings'));
132
133     // Check that the field appears in the overview form.
134     $this->assertFieldByXPath('//table[@id="field-overview"]//tr[@id="field-test"]/td[1]', 'Test', 'Field was created and appears in the overview page.');
135
136     // Check that the field settings form can be submitted again, even when the
137     // field is required.
138     // The first 'Edit' link is for the Body field.
139     $this->clickLink(t('Edit'), 1);
140     $this->drupalPostForm(NULL, [], t('Save settings'));
141
142     // Switch the target type to 'taxonomy_term' and check that the settings
143     // specific to its selection handler are displayed.
144     $field_name = 'node.' . $this->type . '.field_test';
145     $edit = [
146       'settings[target_type]' => 'taxonomy_term',
147     ];
148     $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings'));
149     $this->drupalGet($bundle_path . '/fields/' . $field_name);
150     $this->assertFieldByName('settings[handler_settings][auto_create]');
151
152     // Switch the target type to 'user' and check that the settings specific to
153     // its selection handler are displayed.
154     $field_name = 'node.' . $this->type . '.field_test';
155     $edit = [
156       'settings[target_type]' => 'user',
157     ];
158     $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings'));
159     $this->drupalGet($bundle_path . '/fields/' . $field_name);
160     $this->assertFieldByName('settings[handler_settings][filter][type]', '_none');
161
162     // Switch the target type to 'node'.
163     $field_name = 'node.' . $this->type . '.field_test';
164     $edit = [
165       'settings[target_type]' => 'node',
166     ];
167     $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings'));
168
169     // Try to select the views handler.
170     $this->drupalGet($bundle_path . '/fields/' . $field_name);
171     $page->findField('settings[handler]')->setValue('views');
172     $views_text = (string) new FormattableMarkup('No eligible views were found. <a href=":create">Create a view</a> with an <em>Entity Reference</em> display, or add such a display to an <a href=":existing">existing view</a>.', [
173       ':create' => \Drupal::url('views_ui.add'),
174       ':existing' => \Drupal::url('entity.view.collection'),
175     ]);
176     $assert_session->waitForElement('xpath', '//a[contains(text(), "Create a view")]');
177     $assert_session->responseContains($views_text);
178
179     $this->drupalPostForm(NULL, [], t('Save settings'));
180     // If no eligible view is available we should see a message.
181     $assert_session->pageTextContains('The views entity selection mode requires a view.');
182
183     // Enable the entity_reference_test module which creates an eligible view.
184     $this->container->get('module_installer')
185       ->install(['entity_reference_test']);
186     $this->resetAll();
187     $this->drupalGet($bundle_path . '/fields/' . $field_name);
188     $page->findField('settings[handler]')->setValue('views');
189     $assert_session
190       ->waitForField('settings[handler_settings][view][view_and_display]')
191       ->setValue('test_entity_reference:entity_reference_1');
192     $this->drupalPostForm(NULL, [], t('Save settings'));
193     $assert_session->pageTextContains('Saved Test configuration.');
194
195     // Switch the target type to 'entity_test'.
196     $edit = [
197       'settings[target_type]' => 'entity_test',
198     ];
199     $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings'));
200     $this->drupalGet($bundle_path . '/fields/' . $field_name);
201     $page->findField('settings[handler]')->setValue('views');
202     $assert_session
203       ->waitForField('settings[handler_settings][view][view_and_display]')
204       ->setValue('test_entity_reference_entity_test:entity_reference_1');
205     $edit = [
206       'required' => FALSE,
207     ];
208     $this->drupalPostForm(NULL, $edit, t('Save settings'));
209     $assert_session->pageTextContains('Saved Test configuration.');
210   }
211
212   /**
213    * Checks if a select element contains the specified options.
214    *
215    * @param string $name
216    *   The field name.
217    * @param array $expected_options
218    *   An array of expected options.
219    */
220   protected function assertFieldSelectOptions($name, array $expected_options) {
221     $xpath = $this->buildXPathQuery('//select[@name=:name]', [':name' => $name]);
222     $fields = $this->xpath($xpath);
223     if ($fields) {
224       $field = $fields[0];
225       $options = $field->findAll('xpath', 'option');
226       $optgroups = $field->findAll('xpath', 'optgroup');
227       foreach ($optgroups as $optgroup) {
228         $options = array_merge($options, $optgroup->findAll('xpath', 'option'));
229       }
230       array_walk($options, function (NodeElement &$option) {
231         $option = $option->getAttribute('value');
232       });
233
234       sort($options);
235       sort($expected_options);
236
237       $this->assertIdentical($options, $expected_options);
238     }
239     else {
240       $this->fail('Unable to find field ' . $name);
241     }
242   }
243
244 }