Mercurial > hg > isophonics-drupal-site
comparison core/modules/path/tests/src/Functional/PathAliasTest.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 129ea1e6d783 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Tests\path\Functional; | |
4 | |
5 use Drupal\Component\Utility\Unicode; | |
6 use Drupal\Core\Cache\Cache; | |
7 use Drupal\Core\Database\Database; | |
8 | |
9 /** | |
10 * Add, edit, delete, and change alias and verify its consistency in the | |
11 * database. | |
12 * | |
13 * @group path | |
14 */ | |
15 class PathAliasTest extends PathTestBase { | |
16 | |
17 /** | |
18 * Modules to enable. | |
19 * | |
20 * @var array | |
21 */ | |
22 public static $modules = ['path']; | |
23 | |
24 protected function setUp() { | |
25 parent::setUp(); | |
26 | |
27 // Create test user and log in. | |
28 $web_user = $this->drupalCreateUser(['create page content', 'edit own page content', 'administer url aliases', 'create url aliases']); | |
29 $this->drupalLogin($web_user); | |
30 } | |
31 | |
32 /** | |
33 * Tests the path cache. | |
34 */ | |
35 public function testPathCache() { | |
36 // Create test node. | |
37 $node1 = $this->drupalCreateNode(); | |
38 | |
39 // Create alias. | |
40 $edit = []; | |
41 $edit['source'] = '/node/' . $node1->id(); | |
42 $edit['alias'] = '/' . $this->randomMachineName(8); | |
43 $this->drupalPostForm('admin/config/search/path/add', $edit, t('Save')); | |
44 | |
45 // Check the path alias whitelist cache. | |
46 $whitelist = \Drupal::cache('bootstrap')->get('path_alias_whitelist'); | |
47 $this->assertTrue($whitelist->data['node']); | |
48 $this->assertFalse($whitelist->data['admin']); | |
49 | |
50 // Visit the system path for the node and confirm a cache entry is | |
51 // created. | |
52 \Drupal::cache('data')->deleteAll(); | |
53 // Make sure the path is not converted to the alias. | |
54 $this->drupalGet(trim($edit['source'], '/'), ['alias' => TRUE]); | |
55 $this->assertTrue(\Drupal::cache('data')->get('preload-paths:' . $edit['source']), 'Cache entry was created.'); | |
56 | |
57 // Visit the alias for the node and confirm a cache entry is created. | |
58 \Drupal::cache('data')->deleteAll(); | |
59 // @todo Remove this once https://www.drupal.org/node/2480077 lands. | |
60 Cache::invalidateTags(['rendered']); | |
61 $this->drupalGet(trim($edit['alias'], '/')); | |
62 $this->assertTrue(\Drupal::cache('data')->get('preload-paths:' . $edit['source']), 'Cache entry was created.'); | |
63 } | |
64 | |
65 /** | |
66 * Tests alias functionality through the admin interfaces. | |
67 */ | |
68 public function testAdminAlias() { | |
69 // Create test node. | |
70 $node1 = $this->drupalCreateNode(); | |
71 | |
72 // Create alias. | |
73 $edit = []; | |
74 $edit['source'] = '/node/' . $node1->id(); | |
75 $edit['alias'] = '/' . $this->getRandomGenerator()->word(8); | |
76 $this->drupalPostForm('admin/config/search/path/add', $edit, t('Save')); | |
77 | |
78 // Confirm that the alias works. | |
79 $this->drupalGet($edit['alias']); | |
80 $this->assertText($node1->label(), 'Alias works.'); | |
81 $this->assertResponse(200); | |
82 // Confirm that the alias works in a case-insensitive way. | |
83 $this->assertTrue(ctype_lower(ltrim($edit['alias'], '/'))); | |
84 $this->drupalGet($edit['alias']); | |
85 $this->assertText($node1->label(), 'Alias works lower case.'); | |
86 $this->assertResponse(200); | |
87 $this->drupalGet(Unicode::strtoupper($edit['alias'])); | |
88 $this->assertText($node1->label(), 'Alias works upper case.'); | |
89 $this->assertResponse(200); | |
90 | |
91 // Change alias to one containing "exotic" characters. | |
92 $pid = $this->getPID($edit['alias']); | |
93 | |
94 $previous = $edit['alias']; | |
95 // Lower-case letters. | |
96 $edit['alias'] = '/alias' . | |
97 // "Special" ASCII characters. | |
98 "- ._~!$'\"()*@[]?&+%#,;=:" . | |
99 // Characters that look like a percent-escaped string. | |
100 "%23%25%26%2B%2F%3F" . | |
101 // Characters from various non-ASCII alphabets. | |
102 "中國書۞"; | |
103 $connection = Database::getConnection(); | |
104 if ($connection->databaseType() != 'sqlite') { | |
105 // When using LIKE for case-insensitivity, the SQLite driver is | |
106 // currently unable to find the upper-case versions of non-ASCII | |
107 // characters. | |
108 // @todo fix this in https://www.drupal.org/node/2607432 | |
109 $edit['alias'] .= "ïвβéø"; | |
110 } | |
111 $this->drupalPostForm('admin/config/search/path/edit/' . $pid, $edit, t('Save')); | |
112 | |
113 // Confirm that the alias works. | |
114 $this->drupalGet(Unicode::strtoupper($edit['alias'])); | |
115 $this->assertText($node1->label(), 'Changed alias works.'); | |
116 $this->assertResponse(200); | |
117 | |
118 $this->container->get('path.alias_manager')->cacheClear(); | |
119 // Confirm that previous alias no longer works. | |
120 $this->drupalGet($previous); | |
121 $this->assertNoText($node1->label(), 'Previous alias no longer works.'); | |
122 $this->assertResponse(404); | |
123 | |
124 // Create second test node. | |
125 $node2 = $this->drupalCreateNode(); | |
126 | |
127 // Set alias to second test node. | |
128 $edit['source'] = '/node/' . $node2->id(); | |
129 // leave $edit['alias'] the same | |
130 $this->drupalPostForm('admin/config/search/path/add', $edit, t('Save')); | |
131 | |
132 // Confirm no duplicate was created. | |
133 $this->assertRaw(t('The alias %alias is already in use in this language.', ['%alias' => $edit['alias']]), 'Attempt to move alias was rejected.'); | |
134 | |
135 $edit_upper = $edit; | |
136 $edit_upper['alias'] = Unicode::strtoupper($edit['alias']); | |
137 $this->drupalPostForm('admin/config/search/path/add', $edit_upper, t('Save')); | |
138 $this->assertRaw(t('The alias %alias could not be added because it is already in use in this language with different capitalization: %stored_alias.', [ | |
139 '%alias' => $edit_upper['alias'], | |
140 '%stored_alias' => $edit['alias'], | |
141 ]), 'Attempt to move upper-case alias was rejected.'); | |
142 | |
143 // Delete alias. | |
144 $this->drupalGet('admin/config/search/path/edit/' . $pid); | |
145 $this->clickLink(t('Delete')); | |
146 $this->assertRaw(t('Are you sure you want to delete path alias %name?', ['%name' => $edit['alias']])); | |
147 $this->drupalPostForm(NULL, [], t('Confirm')); | |
148 | |
149 // Confirm that the alias no longer works. | |
150 $this->drupalGet($edit['alias']); | |
151 $this->assertNoText($node1->label(), 'Alias was successfully deleted.'); | |
152 $this->assertResponse(404); | |
153 | |
154 // Create a really long alias. | |
155 $edit = []; | |
156 $edit['source'] = '/node/' . $node1->id(); | |
157 $alias = '/' . $this->randomMachineName(128); | |
158 $edit['alias'] = $alias; | |
159 // The alias is shortened to 50 characters counting the ellipsis. | |
160 $truncated_alias = substr($alias, 0, 47); | |
161 $this->drupalPostForm('admin/config/search/path/add', $edit, t('Save')); | |
162 $this->assertNoText($alias, 'The untruncated alias was not found.'); | |
163 // The 'truncated' alias will always be found. | |
164 $this->assertText($truncated_alias, 'The truncated alias was found.'); | |
165 | |
166 // Create third test node. | |
167 $node3 = $this->drupalCreateNode(); | |
168 | |
169 // Create absolute path alias. | |
170 $edit = []; | |
171 $edit['source'] = '/node/' . $node3->id(); | |
172 $node3_alias = '/' . $this->randomMachineName(8); | |
173 $edit['alias'] = $node3_alias; | |
174 $this->drupalPostForm('admin/config/search/path/add', $edit, t('Save')); | |
175 | |
176 // Create fourth test node. | |
177 $node4 = $this->drupalCreateNode(); | |
178 | |
179 // Create alias with trailing slash. | |
180 $edit = []; | |
181 $edit['source'] = '/node/' . $node4->id(); | |
182 $node4_alias = '/' . $this->randomMachineName(8); | |
183 $edit['alias'] = $node4_alias . '/'; | |
184 $this->drupalPostForm('admin/config/search/path/add', $edit, t('Save')); | |
185 | |
186 // Confirm that the alias with trailing slash is not found. | |
187 $this->assertNoText($edit['alias'], 'The absolute alias was not found.'); | |
188 // The alias without trailing flash is found. | |
189 $this->assertText(trim($edit['alias'], '/'), 'The alias without trailing slash was found.'); | |
190 | |
191 // Update an existing alias to point to a different source. | |
192 $pid = $this->getPID($node4_alias); | |
193 $edit = []; | |
194 $edit['alias'] = $node4_alias; | |
195 $edit['source'] = '/node/' . $node2->id(); | |
196 $this->drupalPostForm('admin/config/search/path/edit/' . $pid, $edit, t('Save')); | |
197 $this->assertText('The alias has been saved.'); | |
198 $this->drupalGet($edit['alias']); | |
199 $this->assertNoText($node4->label(), 'Previous alias no longer works.'); | |
200 $this->assertText($node2->label(), 'Alias works.'); | |
201 $this->assertResponse(200); | |
202 | |
203 // Update an existing alias to use a duplicate alias. | |
204 $pid = $this->getPID($node3_alias); | |
205 $edit = []; | |
206 $edit['alias'] = $node4_alias; | |
207 $edit['source'] = '/node/' . $node3->id(); | |
208 $this->drupalPostForm('admin/config/search/path/edit/' . $pid, $edit, t('Save')); | |
209 $this->assertRaw(t('The alias %alias is already in use in this language.', ['%alias' => $edit['alias']])); | |
210 | |
211 // Create an alias without a starting slash. | |
212 $node5 = $this->drupalCreateNode(); | |
213 | |
214 $edit = []; | |
215 $edit['source'] = 'node/' . $node5->id(); | |
216 $node5_alias = $this->randomMachineName(8); | |
217 $edit['alias'] = $node5_alias . '/'; | |
218 $this->drupalPostForm('admin/config/search/path/add', $edit, t('Save')); | |
219 | |
220 $this->assertUrl('admin/config/search/path/add'); | |
221 $this->assertText('The source path has to start with a slash.'); | |
222 $this->assertText('The alias path has to start with a slash.'); | |
223 } | |
224 | |
225 /** | |
226 * Tests alias functionality through the node interfaces. | |
227 */ | |
228 public function testNodeAlias() { | |
229 // Create test node. | |
230 $node1 = $this->drupalCreateNode(); | |
231 | |
232 // Create alias. | |
233 $edit = []; | |
234 $edit['path[0][alias]'] = '/' . $this->randomMachineName(8); | |
235 $this->drupalPostForm('node/' . $node1->id() . '/edit', $edit, t('Save')); | |
236 | |
237 // Confirm that the alias works. | |
238 $this->drupalGet($edit['path[0][alias]']); | |
239 $this->assertText($node1->label(), 'Alias works.'); | |
240 $this->assertResponse(200); | |
241 | |
242 // Confirm the 'canonical' and 'shortlink' URLs. | |
243 $elements = $this->xpath("//link[contains(@rel, 'canonical') and contains(@href, '" . $edit['path[0][alias]'] . "')]"); | |
244 $this->assertTrue(!empty($elements), 'Page contains canonical link URL.'); | |
245 $elements = $this->xpath("//link[contains(@rel, 'shortlink') and contains(@href, 'node/" . $node1->id() . "')]"); | |
246 $this->assertTrue(!empty($elements), 'Page contains shortlink URL.'); | |
247 | |
248 $previous = $edit['path[0][alias]']; | |
249 // Change alias to one containing "exotic" characters. | |
250 // Lower-case letters. | |
251 $edit['path[0][alias]'] = '/alias' . | |
252 // "Special" ASCII characters. | |
253 "- ._~!$'\"()*@[]?&+%#,;=:" . | |
254 // Characters that look like a percent-escaped string. | |
255 "%23%25%26%2B%2F%3F" . | |
256 // Characters from various non-ASCII alphabets. | |
257 "中國書۞"; | |
258 $connection = Database::getConnection(); | |
259 if ($connection->databaseType() != 'sqlite') { | |
260 // When using LIKE for case-insensitivity, the SQLite driver is | |
261 // currently unable to find the upper-case versions of non-ASCII | |
262 // characters. | |
263 // @todo fix this in https://www.drupal.org/node/2607432 | |
264 $edit['path[0][alias]'] .= "ïвβéø"; | |
265 } | |
266 $this->drupalPostForm('node/' . $node1->id() . '/edit', $edit, t('Save')); | |
267 | |
268 // Confirm that the alias works. | |
269 $this->drupalGet(Unicode::strtoupper($edit['path[0][alias]'])); | |
270 $this->assertText($node1->label(), 'Changed alias works.'); | |
271 $this->assertResponse(200); | |
272 | |
273 // Make sure that previous alias no longer works. | |
274 $this->drupalGet($previous); | |
275 $this->assertNoText($node1->label(), 'Previous alias no longer works.'); | |
276 $this->assertResponse(404); | |
277 | |
278 // Create second test node. | |
279 $node2 = $this->drupalCreateNode(); | |
280 | |
281 // Set alias to second test node. | |
282 // Leave $edit['path[0][alias]'] the same. | |
283 $this->drupalPostForm('node/' . $node2->id() . '/edit', $edit, t('Save')); | |
284 | |
285 // Confirm that the alias didn't make a duplicate. | |
286 $this->assertText(t('The alias is already in use.'), 'Attempt to moved alias was rejected.'); | |
287 | |
288 // Delete alias. | |
289 $this->drupalPostForm('node/' . $node1->id() . '/edit', ['path[0][alias]' => ''], t('Save')); | |
290 | |
291 // Confirm that the alias no longer works. | |
292 $this->drupalGet($edit['path[0][alias]']); | |
293 $this->assertNoText($node1->label(), 'Alias was successfully deleted.'); | |
294 $this->assertResponse(404); | |
295 | |
296 // Create third test node. | |
297 $node3 = $this->drupalCreateNode(); | |
298 | |
299 // Set its path alias to an absolute path. | |
300 $edit = ['path[0][alias]' => '/' . $this->randomMachineName(8)]; | |
301 $this->drupalPostForm('node/' . $node3->id() . '/edit', $edit, t('Save')); | |
302 | |
303 // Confirm that the alias was converted to a relative path. | |
304 $this->drupalGet(trim($edit['path[0][alias]'], '/')); | |
305 $this->assertText($node3->label(), 'Alias became relative.'); | |
306 $this->assertResponse(200); | |
307 | |
308 // Create fourth test node. | |
309 $node4 = $this->drupalCreateNode(); | |
310 | |
311 // Set its path alias to have a trailing slash. | |
312 $edit = ['path[0][alias]' => '/' . $this->randomMachineName(8) . '/']; | |
313 $this->drupalPostForm('node/' . $node4->id() . '/edit', $edit, t('Save')); | |
314 | |
315 // Confirm that the alias was converted to a relative path. | |
316 $this->drupalGet(trim($edit['path[0][alias]'], '/')); | |
317 $this->assertText($node4->label(), 'Alias trimmed trailing slash.'); | |
318 $this->assertResponse(200); | |
319 | |
320 // Create fifth test node. | |
321 $node5 = $this->drupalCreateNode(); | |
322 | |
323 // Set a path alias. | |
324 $edit = ['path[0][alias]' => '/' . $this->randomMachineName(8)]; | |
325 $this->drupalPostForm('node/' . $node5->id() . '/edit', $edit, t('Save')); | |
326 | |
327 // Delete the node and check that the path alias is also deleted. | |
328 $node5->delete(); | |
329 $path_alias = \Drupal::service('path.alias_storage')->lookupPathAlias('/node/' . $node5->id(), $node5->language()->getId()); | |
330 $this->assertFalse($path_alias, 'Alias was successfully deleted when the referenced node was deleted.'); | |
331 } | |
332 | |
333 /** | |
334 * Returns the path ID. | |
335 * | |
336 * @param string $alias | |
337 * A string containing an aliased path. | |
338 * | |
339 * @return int | |
340 * Integer representing the path ID. | |
341 */ | |
342 public function getPID($alias) { | |
343 return db_query("SELECT pid FROM {url_alias} WHERE alias = :alias", [':alias' => $alias])->fetchField(); | |
344 } | |
345 | |
346 /** | |
347 * Tests that duplicate aliases fail validation. | |
348 */ | |
349 public function testDuplicateNodeAlias() { | |
350 // Create one node with a random alias. | |
351 $node_one = $this->drupalCreateNode(); | |
352 $edit = []; | |
353 $edit['path[0][alias]'] = '/' . $this->randomMachineName(); | |
354 $this->drupalPostForm('node/' . $node_one->id() . '/edit', $edit, t('Save')); | |
355 | |
356 // Now create another node and try to set the same alias. | |
357 $node_two = $this->drupalCreateNode(); | |
358 $this->drupalPostForm('node/' . $node_two->id() . '/edit', $edit, t('Save')); | |
359 $this->assertText(t('The alias is already in use.')); | |
360 $this->assertFieldByXPath("//input[@name='path[0][alias]' and contains(@class, 'error')]", $edit['path[0][alias]'], 'Textfield exists and has the error class.'); | |
361 | |
362 // Behavior here differs with the inline_form_errors module enabled. | |
363 // Enable the inline_form_errors module and try this again. This module | |
364 // improves validation with a link in the error message(s) to the fields | |
365 // which have invalid input. | |
366 $this->assertTrue($this->container->get('module_installer')->install(['inline_form_errors'], TRUE), 'Installed inline_form_errors.'); | |
367 // Attempt to edit the second node again, as before. | |
368 $this->drupalPostForm('node/' . $node_two->id() . '/edit', $edit, t('Preview')); | |
369 // This error should still be present next to the field. | |
370 $this->assertSession()->pageTextContains(t('The alias is already in use.'), 'Field error found with expected text.'); | |
371 // The validation error set for the page should include this text. | |
372 $this->assertSession()->pageTextContains(t('1 error has been found: URL alias'), 'Form error found with expected text.'); | |
373 // The text 'URL alias' should be a link. | |
374 $this->assertSession()->linkExists('URL alias'); | |
375 // The link should be to the ID of the URL alias field. | |
376 $this->assertSession()->linkByHrefExists('#edit-path-0-alias'); | |
377 } | |
378 | |
379 } |