Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / link / tests / src / Functional / LinkFieldUITest.php
1 <?php
2
3 namespace Drupal\Tests\link\Functional;
4
5 use Drupal\Component\Utility\Html;
6 use Drupal\Core\Entity\Entity\EntityFormDisplay;
7 use Drupal\field\Entity\FieldConfig;
8 use Drupal\field\Entity\FieldStorageConfig;
9 use Drupal\link\LinkItemInterface;
10 use Drupal\Tests\BrowserTestBase;
11 use Drupal\Tests\field_ui\Traits\FieldUiTestTrait;
12
13 /**
14  * Tests link field UI functionality.
15  *
16  * @group link
17  */
18 class LinkFieldUITest extends BrowserTestBase {
19
20   use FieldUiTestTrait;
21
22   /**
23    * Modules to enable.
24    *
25    * @var array
26    */
27   public static $modules = ['node', 'link', 'field_ui', 'block'];
28
29   /**
30    * A user that can edit content types.
31    *
32    * @var \Drupal\user\UserInterface
33    */
34   protected $adminUser;
35
36   /**
37    * A user that should see the help texts.
38    *
39    * @var \Drupal\user\Entity\User
40    */
41   protected $helpTextUser;
42
43   /**
44    * The first content type to add fields to.
45    *
46    * @var \Drupal\node\Entity\NodeType
47    */
48   protected $firstContentType;
49
50   /**
51    * The second content type to add fields to.
52    *
53    * @var \Drupal\node\Entity\NodeType
54    */
55   protected $secondContentType;
56
57   /**
58    * {@inheritdoc}
59    */
60   protected function setUp() {
61     parent::setUp();
62
63     $this->firstContentType = $this->drupalCreateContentType();
64     $this->secondContentType = $this->drupalCreateContentType();
65     $this->adminUser = $this->drupalCreateUser(['administer content types', 'administer node fields', 'administer node display']);
66     $this->helpTextUser = $this->drupalCreateUser(['create ' . $this->secondContentType->id() . ' content']);
67     $this->drupalPlaceBlock('system_breadcrumb_block');
68   }
69
70   /**
71    * Tests the link field UI.
72    */
73   public function testFieldUI() {
74     foreach ($this->providerTestFieldUI() as $item) {
75       list($cardinality, $link_type, $title, $label, $field_name) = $item;
76       $this->runFieldUIItem($cardinality, $link_type, $title, $label, $field_name);
77     }
78   }
79
80   /**
81    * Provides test data for ::testFieldUI().
82    */
83   protected function providerTestFieldUI() {
84     // There are many combinations of field settings: where the description
85     // should show: variation on internal, external, both; cardinality (where
86     // the fieldset is hidden or used); and link text shown (required or
87     // optional) or disabled. There are two descriptions: field and URL help
88     // text.
89     $cardinalities = [1, 2];
90     $title_settings = [
91       DRUPAL_DISABLED,
92       DRUPAL_OPTIONAL,
93     ];
94     $link_types = [
95       LinkItemInterface::LINK_EXTERNAL,
96       LinkItemInterface::LINK_GENERIC,
97       LinkItemInterface::LINK_INTERNAL,
98     ];
99
100     // Test all variations of link types on all cardinalities.
101     foreach ($cardinalities as $cardinality) {
102       foreach ($link_types as $link_type) {
103         // Now, test this with both the title enabled and disabled.
104         foreach ($title_settings as $title_setting) {
105           // Test both empty and non-empty labels.
106           foreach ([TRUE, FALSE] as $label_provided) {
107             // Generate a unique machine name for the field so it can be
108             // identified in the test.
109             $id = implode('_', [
110               'link',
111               $cardinality,
112               $link_type,
113               $title_setting,
114               (int) $label_provided,
115             ]);
116
117             // Use a unique label that contains some HTML.
118             $label = '<img src="http://example.com">' . $id;
119
120             yield [
121               $cardinality,
122               $link_type,
123               $title_setting,
124               $label_provided ? $label : '',
125               $id,
126             ];
127           }
128         }
129       }
130     }
131   }
132
133   /**
134    * Tests one link field UI item.
135    *
136    * @param int $cardinality
137    *   The field cardinality.
138    * @param int $link_type
139    *   Determine if the link is external, internal or both.
140    * @param int $title
141    *   Determine if the field will display the link text field.
142    * @param string $label
143    *   The field label.
144    * @param string $field_name
145    *   The unique machine name for the field.
146    */
147   public function runFieldUIItem($cardinality, $link_type, $title, $label, $field_name) {
148     $this->drupalLogin($this->adminUser);
149     $type_path = 'admin/structure/types/manage/' . $this->firstContentType->id();
150
151     // Add a link field to the newly-created type. It defaults to allowing both
152     // internal and external links.
153     $field_label = str_replace('_', ' ', $field_name);
154     $description = 'link field description';
155     $field_edit = [
156       'description' => $description,
157     ];
158     $this->fieldUIAddNewField($type_path, $field_name, $field_label, 'link', [], $field_edit);
159
160     // Load the formatter page to check that the settings summary does not
161     // generate warnings.
162     // @todo Mess with the formatter settings a bit here.
163     $this->drupalGet("$type_path/display");
164     $this->assertText(t('Link text trimmed to @limit characters', ['@limit' => 80]));
165
166     $storage = FieldStorageConfig::create([
167       'field_name' => $field_name,
168       'entity_type' => 'node',
169       'type' => 'link',
170       'cardinality' => $cardinality,
171     ]);
172     $storage->save();
173
174     FieldConfig::create([
175       'field_storage' => $storage,
176       'label' => $label,
177       'bundle' => $this->secondContentType->id(),
178       'settings' => [
179         'title' => $title,
180         'link_type' => $link_type,
181       ],
182     ])->save();
183
184     // Make the fields visible in the form display.
185     $form_display_id = implode('.', ['node', $this->secondContentType->id(), 'default']);
186     $form_display = EntityFormDisplay::load($form_display_id);
187     $form_display->setComponent($field_name, ['region' => 'content']);
188     $form_display->save();
189
190     // Log in a user that is allowed to create this content type, see if
191     // the user can see the expected help text.
192     $this->drupalLogin($this->helpTextUser);
193
194     $add_path = 'node/add/' . $this->secondContentType->id();
195     $this->drupalGet($add_path);
196
197     $expected_help_texts = [
198       LinkItemInterface::LINK_EXTERNAL => 'This must be an external URL such as <em class="placeholder">http://example.com</em>.',
199       LinkItemInterface::LINK_GENERIC => 'You can also enter an internal path such as <em class="placeholder">/node/add</em> or an external URL such as <em class="placeholder">http://example.com</em>. Enter <em class="placeholder">&lt;front&gt;</em> to link to the front page.',
200       LinkItemInterface::LINK_INTERNAL => rtrim(\Drupal::url('<front>', [], ['absolute' => TRUE]), '/'),
201     ];
202
203     // Check that the help texts we assume should be there, is there.
204     $this->assertFieldContainsRawText($field_name, $expected_help_texts[$link_type]);
205     if ($link_type === LinkItemInterface::LINK_INTERNAL) {
206       // Internal links have no "system" description. Test that none
207       // of the other help texts show here.
208       $this->assertNoFieldContainsRawText($field_name, $expected_help_texts[LinkItemInterface::LINK_EXTERNAL]);
209       $this->assertNoFieldContainsRawText($field_name, $expected_help_texts[LinkItemInterface::LINK_GENERIC]);
210     }
211     // Also assert that the description we made is here, no matter what the
212     // cardinality or link setting.
213     if (!empty($label)) {
214       $this->assertFieldContainsRawText($field_name, $label);
215     }
216   }
217
218   /**
219    * Checks that given field contains the given raw text.
220    *
221    * @param string $field_name
222    *   The name of the field to check.
223    * @param string $text
224    *   The text to check.
225    */
226   protected function assertFieldContainsRawText($field_name, $text) {
227     $this->assertTrue((bool) preg_match('/' . preg_quote($text, '/') . '/ui', $this->getFieldHtml($field_name)));
228   }
229
230   /**
231    * Checks that given field does not contain the given raw text.
232    *
233    * @param string $field_name
234    *   The name of the field to check.
235    * @param string $text
236    *   The text to check.
237    */
238   protected function assertNoFieldContainsRawText($field_name, $text) {
239     $this->assertFalse((bool) preg_match('/' . preg_quote($text, '/') . '/ui', $this->getFieldHtml($field_name)));
240   }
241
242   /**
243    * Returns the raw HTML for the given field.
244    *
245    * @param $field_name
246    *   The name of the field for which to return the HTML.
247    *
248    * @return string
249    *   The raw HTML.
250    */
251   protected function getFieldHtml($field_name) {
252     $css_id = Html::cleanCssIdentifier('edit-' . $field_name . '-wrapper');
253     return $this->xpath('//*[@id=:id]', [':id' => $css_id])[0]->getHtml();
254   }
255
256 }