3 namespace Drupal\inline_entity_form\Tests;
5 use Drupal\Core\Field\FieldStorageDefinitionInterface;
6 use Drupal\node\NodeInterface;
9 * Tests the IEF simple widget.
11 * @group inline_entity_form
13 class SimpleWidgetWebTest extends InlineEntityFormTestBase {
20 public static $modules = ['inline_entity_form_test'];
23 * Prepares environment for
25 protected function setUp() {
28 $this->user = $this->createUser([
29 'create ief_simple_single content',
30 'create ief_test_custom content',
31 'edit any ief_simple_single content',
32 'edit own ief_test_custom content',
33 'view own unpublished content',
34 'create ief_simple_entity_no_bundle content',
35 'administer entity_test__without_bundle content',
40 * Tests simple IEF widget with different cardinality options.
44 protected function testSimpleCardinalityOptions() {
45 $this->drupalLogin($this->user);
46 $cardinality_options = [
49 FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED => 3,
51 /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
52 $field_storage = $this->fieldStorageConfigStorage->load('node.single');
53 foreach ($cardinality_options as $cardinality => $limit) {
54 $field_storage->setCardinality($cardinality);
55 $field_storage->save();
57 $this->drupalGet('node/add/ief_simple_single');
59 $this->assertText('Single node', 'Inline entity field widget title found.');
60 $this->assertText('Reference a single node.', 'Inline entity field description found.');
62 $add_more_xpath = '//input[@data-drupal-selector="edit-single-add-more"]';
63 if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
64 $this->assertFieldByXPath($add_more_xpath, NULL, 'Add more button exists');
67 $this->assertNoFieldByXPath($add_more_xpath, NULL, 'Add more button does NOT exist');
70 $host_title = 'Host node cardinality: ' . $cardinality;
71 $edit = ['title[0][value]' => $host_title];
72 for ($item_number = 0; $item_number < $limit; $item_number++) {
73 $edit["single[$item_number][inline_entity_form][title][0][value]"] = 'Child node nr.' . $item_number;
74 if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
75 $next_item_number = $item_number + 1;
76 $this->assertNoFieldByName("single[$next_item_number][inline_entity_form][title][0][value]", NULL, "Item $next_item_number does not appear before 'Add More' clicked");
77 if ($item_number < $limit - 1) {
78 $this->drupalPostAjaxForm(NULL, $edit, 'single_add_more');
79 $this->assertFieldByName("single[$next_item_number][inline_entity_form][title][0][value]", NULL, "Item $next_item_number does appear after 'Add More' clicked");
80 // Make sure only 1 item is added.
81 $unexpected_item_number = $next_item_number + 1;
82 $this->assertNoFieldByName("single[$unexpected_item_number][inline_entity_form][title][0][value]", NULL, "Extra Item $unexpected_item_number is not added after 'Add More' clicked");
86 $this->drupalPostForm(NULL, $edit, t('Save'));
88 for ($item_number = 0; $item_number < $limit; $item_number++) {
89 $this->assertText('Child node nr.' . $item_number, 'Label of referenced entity found.');
92 $host_node = $this->getNodeByTitle($host_title);
93 $this->checkEditAccess($host_node, $limit, $cardinality);
98 * Test Validation on Simple Widget.
102 protected function testSimpleValidation() {
103 $this->drupalLogin($this->user);
104 $host_node_title = 'Host Validation Node';
105 $this->drupalGet('node/add/ief_simple_single');
107 $this->assertText('Single node', 'Inline entity field widget title found.');
108 $this->assertText('Reference a single node.', 'Inline entity field description found.');
109 $this->assertText('Positive int', 'Positive int field found.');
111 $edit = ['title[0][value]' => $host_node_title];
112 $this->drupalPostForm(NULL, $edit, t('Save'));
114 $this->assertText('Title field is required.', 'Title validation fires on Inline Entity Form widget.');
115 $this->assertUrl('node/add/ief_simple_single', [], 'On add page after validation error.');
117 $child_title = 'Child node ' . $this->randomString();
118 $edit['single[0][inline_entity_form][title][0][value]'] = $child_title;
119 $edit['single[0][inline_entity_form][positive_int][0][value]'] = -1;
120 $this->drupalPostForm(NULL, $edit, t('Save'));
121 $this->assertNoText('Title field is required.', 'Title validation passes on Inline Entity Form widget.');
122 $this->assertText('Positive int must be higher than or equal to 1', 'Field validation fires on Inline Entity Form widget.');
123 $this->assertUrl('node/add/ief_simple_single', [], 'On add page after validation error.');
125 $edit['single[0][inline_entity_form][positive_int][0][value]'] = 1;
126 $this->drupalPostForm(NULL, $edit, t('Save'));
127 $this->assertNoText('Title field is required.', 'Title validation passes on Inline Entity Form widget.');
128 $this->assertNoText('Positive int must be higher than or equal to 1', 'Field validation fires on Inline Entity Form widget.');
130 // Check that nodes were created correctly.
131 $host_node = $this->getNodeByTitle($host_node_title);
132 if ($this->assertNotNull($host_node, 'Host node created.')) {
133 $this->assertUrl('node/' . $host_node->id(), [], 'On node view page after node add.');
134 $child_node = $this->getNodeByTitle($child_title);
135 if ($this->assertNotNull($child_node)) {
136 $this->assertEqual($host_node->single[0]->target_id, $child_node->id(), 'Child node is referenced');
137 $this->assertEqual($child_node->positive_int[0]->value, 1, 'Child node int field correct.');
138 $this->assertEqual($child_node->bundle(), 'ief_test_custom', 'Child node is correct bundle.');
144 * Tests if the entity create access works in simple widget.
146 public function testSimpleCreateAccess() {
147 // Create a user who does not have access to create ief_test_custom nodes.
148 $this->user = $this->createUser([
149 'create ief_simple_single content',
151 $this->drupalLogin($this->user);
152 $this->drupalGet('node/add/ief_simple_single');
153 $this->assertNoFieldByName('single[0][inline_entity_form][title][0][value]', NULL);
157 * Tests that user only has access to the their own nodes.
159 * @param \Drupal\node\Entity\Node $host_node
160 * The node of the type of ief_simple_single
161 * @param int $child_count
162 * The number of entity reference values in the "single" field.
164 protected function checkEditAccess(NodeInterface $host_node, $child_count, $cardinality) {
165 $other_user = $this->createUser([
166 'edit own ief_test_custom content',
167 'edit any ief_simple_single content',
169 /** @var \Drupal\node\Entity\Node $first_child_node */
170 $first_child_node = $host_node->single[0]->entity;
171 $first_child_node->setOwner($other_user);
172 $first_child_node->save();
173 $this->drupalGet("node/{$host_node->id()}/edit");
174 $this->assertText($first_child_node->label());
175 $this->assertNoFieldByName('single[0][inline_entity_form][title][0][value]', NULL, 'Form of child node with no edit access is not found.');
176 // Check that the forms for other child nodes(if any) appear on the form.
178 while ($delta < $child_count) {
179 /** @var \Drupal\node\Entity\Node $child_node */
180 $child_node = $host_node->single[$delta]->entity;
181 $this->assertFieldByName("single[$delta][inline_entity_form][title][0][value]", $child_node->label(), 'Form of child node with edit access is found.');
184 // Check that there is NOT an extra "add" form when editing.
185 $unexpected_item_number = $child_count;
186 $this->assertNoFieldByName("single[$unexpected_item_number][inline_entity_form][title][0][value]", NULL, 'No empty "add" entity form is found on edit.');
187 if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
188 $next_item_number = $child_count;
189 $this->drupalPostAjaxForm(NULL, [], 'single_add_more');
190 $this->assertFieldByName("single[$next_item_number][inline_entity_form][title][0][value]", NULL, "Item $next_item_number does appear after 'Add More' clicked");
191 // Make sure only 1 item is added.
192 $unexpected_item_number = $next_item_number + 1;
193 $this->assertNoFieldByName("single[$unexpected_item_number][inline_entity_form][title][0][value]", NULL, "Extra Item $unexpected_item_number is not added after 'Add More' clicked");
196 // Now that we have confirmed the correct fields appear, lets update the
197 // values and save them. We do not have access to form for delta 0 because
198 // it is owned by another user.
202 // Loop through an update all child node titles.
203 while ($delta < $child_count) {
204 /** @var \Drupal\node\Entity\Node $child_node */
205 $child_node = $host_node->single[$delta]->entity;
206 $new_titles[$delta] = $child_node->label() . ' - updated';
207 $edit["single[$delta][inline_entity_form][title][0][value]"] = $new_titles[$delta];
210 // If CARDINALITY_UNLIMITED then we should have 1 extra form open.
211 if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
212 $new_titles[$delta] = 'Title for new child';
213 $edit["single[$delta][inline_entity_form][title][0][value]"] = $new_titles[$delta];
215 $this->drupalPostForm(NULL, $edit, t('Save'));
216 $this->assertText("IEF single simple {$host_node->label()} has been updated.");
218 // Reset cache for nodes.
219 $node_ids = [$host_node->id()];
220 foreach ($host_node->single as $item) {
221 $node_ids[] = $item->entity->id();
223 $this->nodeStorage->resetCache($node_ids);
224 $host_node = $this->nodeStorage->load($host_node->id());
225 // Check that titles were updated.
226 foreach ($new_titles as $delta => $new_title) {
227 $child_node = $host_node->single[$delta]->entity;
228 $this->assertEqual($child_node->label(), $new_title, "Child $delta node title updated");
233 * Ensures that an entity without bundles can be used with the simple widget.
235 public function testEntityWithoutBundle() {
236 $this->drupalLogin($this->user);
239 'title[0][value]' => 'Node title',
240 'field_ief_entity_no_bundle[0][inline_entity_form][name][0][value]' => 'Entity title',
242 $this->drupalPostForm('node/add/ief_simple_entity_no_bundle', $edit, 'Save');
244 $this->assertNodeByTitle('Node title', 'ief_simple_entity_no_bundle');
245 $this->assertEntityByLabel('Entity title', 'entity_test__without_bundle');