diff --git a/core/modules/block/src/Tests/BlockLanguageCacheTest.php b/core/modules/block/src/Tests/BlockLanguageCacheTest.php
index 543e65e..a11bdd6 100644
--- a/core/modules/block/src/Tests/BlockLanguageCacheTest.php
+++ b/core/modules/block/src/Tests/BlockLanguageCacheTest.php
@@ -62,7 +62,7 @@ public function testBlockLinks() {
// Create the block cache for all languages.
foreach ($this->langcodes as $langcode) {
$this->drupalGet('admin/structure/block', array('language' => $langcode));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
}
// Create a menu in the default language.
@@ -74,7 +74,7 @@ public function testBlockLinks() {
// Check that the block is listed for all languages.
foreach ($this->langcodes as $langcode) {
$this->drupalGet('admin/structure/block', array('language' => $langcode));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$this->assertText($edit['label']);
}
}
diff --git a/core/modules/block/src/Tests/BlockUiTest.php b/core/modules/block/src/Tests/BlockUiTest.php
index 1f26739..37fce6e 100644
--- a/core/modules/block/src/Tests/BlockUiTest.php
+++ b/core/modules/block/src/Tests/BlockUiTest.php
@@ -146,7 +146,7 @@ public function testCandidateBlockList() {
$pattern = '//tr[.//td/div[text()=:title] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]';
$this->drupalGet('admin/structure/block');
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in the category for its module.');
@@ -155,7 +155,7 @@ public function testCandidateBlockList() {
$this->container->get('plugin.manager.block')->clearCachedDefinitions();
$this->drupalGet('admin/structure/block');
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$arguments[':category'] = 'Custom category';
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in a custom category controlled by block_test_block_alter().');
diff --git a/core/modules/block/src/Tests/BlockXssTest.php b/core/modules/block/src/Tests/BlockXssTest.php
index 0baa67f..3d9bfd3 100644
--- a/core/modules/block/src/Tests/BlockXssTest.php
+++ b/core/modules/block/src/Tests/BlockXssTest.php
@@ -51,7 +51,7 @@ public function testXssInCategory() {
$this->drupalPlaceBlock('test_xss_title');
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
$this->drupalGet(Url::fromRoute('block.admin_display'));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$this->assertNoRaw("");
}
@@ -78,7 +78,7 @@ protected function doViewTest() {
$view->save();
$this->drupalGet(Url::fromRoute('block.admin_display'));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
// The block admin label is automatically XSS admin filtered.
$this->assertRaw('alert("view");');
$this->assertNoRaw('');
@@ -94,7 +94,7 @@ protected function doMenuTest() {
])->save();
$this->drupalGet(Url::fromRoute('block.admin_display'));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
// The block admin label is automatically XSS admin filtered.
$this->assertRaw('alert("menu");');
$this->assertNoRaw('');
@@ -115,7 +115,7 @@ protected function doBlockContentTest() {
])->save();
$this->drupalGet(Url::fromRoute('block.admin_display'));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
// The block admin label is automatically XSS admin filtered.
$this->assertRaw('alert("block_content");');
$this->assertNoRaw('');
diff --git a/core/modules/block/src/Tests/Views/DisplayBlockTest.php b/core/modules/block/src/Tests/Views/DisplayBlockTest.php
index d9f9196..880f68c 100644
--- a/core/modules/block/src/Tests/Views/DisplayBlockTest.php
+++ b/core/modules/block/src/Tests/Views/DisplayBlockTest.php
@@ -70,7 +70,7 @@ public function testBlockCategory() {
':category' => t('Lists (Views)'),
);
$this->drupalGet('admin/structure/block');
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in the category for its base table.');
@@ -95,7 +95,7 @@ public function testBlockCategory() {
// Test that the blocks are listed under the correct categories.
$arguments[':category'] = $category;
$this->drupalGet('admin/structure/block');
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in the custom category.');
diff --git a/core/modules/block_content/src/Tests/BlockContentTypeTest.php b/core/modules/block_content/src/Tests/BlockContentTypeTest.php
index 681c6ce..20dc1a2 100644
--- a/core/modules/block_content/src/Tests/BlockContentTypeTest.php
+++ b/core/modules/block_content/src/Tests/BlockContentTypeTest.php
@@ -189,7 +189,7 @@ public function testsBlockContentAddTypes() {
// block configure form.
$path = $theme == $default_theme ? 'admin/structure/block' : "admin/structure/block/list/$theme";
$this->drupalGet($path);
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$this->clickLink(t('Add custom block'));
// The seven theme has markup inside the link, we cannot use clickLink().
if ($default_theme == 'seven') {
diff --git a/core/modules/menu_ui/src/Tests/MenuTest.php b/core/modules/menu_ui/src/Tests/MenuTest.php
index 3c00e92..34dacc5 100644
--- a/core/modules/menu_ui/src/Tests/MenuTest.php
+++ b/core/modules/menu_ui/src/Tests/MenuTest.php
@@ -219,7 +219,7 @@ function addCustomMenu() {
// Confirm that the custom menu block is available.
$this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default'));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$this->assertText($label);
// Enable the block.
@@ -533,7 +533,7 @@ function testSystemMenuRename() {
// Make sure menu shows up with new name in block addition.
$default_theme = $this->config('system.theme')->get('default');
$this->drupalget('admin/structure/block/list/' . $default_theme);
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$this->assertText($edit['label']);
}
diff --git a/core/modules/search/src/Tests/SearchBlockTest.php b/core/modules/search/src/Tests/SearchBlockTest.php
index 2348ae0..4b774a1 100644
--- a/core/modules/search/src/Tests/SearchBlockTest.php
+++ b/core/modules/search/src/Tests/SearchBlockTest.php
@@ -36,7 +36,7 @@ public function testSearchFormBlock() {
// Test availability of the search block in the admin "Place blocks" list.
$this->drupalGet('admin/structure/block');
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$this->assertLinkByHref('/admin/structure/block/add/search_form_block/classy', 0,
'Did not find the search block in block candidate list.');
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index e17d703..c43888b 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -2324,7 +2324,7 @@ protected function handleForm(&$post, &$edit, &$upload, $submit, $form) {
}
/**
- * Follows a link by name.
+ * Follows a link by complete name.
*
* Will click the first link found with this link text by default, or a later
* one if an index is given. Match is case sensitive with normalized space.
@@ -2332,17 +2332,54 @@ protected function handleForm(&$post, &$edit, &$upload, $submit, $form) {
*
* If the link is discovered and clicked, the test passes. Fail otherwise.
*
- * @param $label
+ * @param string $label
* Text between the anchor tags.
- * @param $index
+ * @param int $index
* Link position counting from zero.
*
- * @return
+ * @return string|bool
* Page contents on success, or FALSE on failure.
*/
protected function clickLink($label, $index = 0) {
+ return $this->clickLinkHelper($label, $index, '//a[normalize-space()=:label]');
+ }
+
+ /**
+ * Follows a link by partial name.
+ *
+ *
+ * If the link is discovered and clicked, the test passes. Fail otherwise.
+ *
+ * @param string $label
+ * Text between the anchor tags, uses starts-with().
+ * @param int $index
+ * Link position counting from zero.
+ *
+ * @return string|bool
+ * Page contents on success, or FALSE on failure.
+ *
+ * @see ::clickLink()
+ */
+ protected function clickLinkPartialName($label, $index = 0) {
+ return $this->clickLinkHelper($label, $index, '//a[starts-with(normalize-space(), :label)]');
+ }
+
+ /**
+ * Provides a helper for ::clickLink() and ::clickLinkPartialName().
+ *
+ * @param string $label
+ * Text between the anchor tags, uses starts-with().
+ * @param int $index
+ * Link position counting from zero.
+ * @param string $pattern
+ * A pattern to use for the XPath.
+ *
+ * @return bool|string
+ * Page contents on success, or FALSE on failure.
+ */
+ protected function clickLinkHelper($label, $index, $pattern) {
$url_before = $this->getUrl();
- $urls = $this->xpath('//a[normalize-space()=:label]', array(':label' => $label));
+ $urls = $this->xpath($pattern, array(':label' => $label));
if (isset($urls[$index])) {
$url_target = $this->getAbsoluteUrl($urls[$index]['href']);
$this->pass(SafeMarkup::format('Clicked link %label (@url_target) from @url_before', array('%label' => $label, '@url_target' => $url_target, '@url_before' => $url_before)), 'Browser');
diff --git a/core/modules/views/src/Tests/Wizard/BasicTest.php b/core/modules/views/src/Tests/Wizard/BasicTest.php
index 2ba0dac..fe736de 100644
--- a/core/modules/views/src/Tests/Wizard/BasicTest.php
+++ b/core/modules/views/src/Tests/Wizard/BasicTest.php
@@ -133,7 +133,7 @@ function testViewsWizardAndListing() {
// Confirm that the block is available in the block administration UI.
$this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default'));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$this->assertText($view3['label']);
// Place the block.
diff --git a/core/modules/views/src/Tests/Wizard/ItemsPerPageTest.php b/core/modules/views/src/Tests/Wizard/ItemsPerPageTest.php
index 7fd06d0..132df58 100644
--- a/core/modules/views/src/Tests/Wizard/ItemsPerPageTest.php
+++ b/core/modules/views/src/Tests/Wizard/ItemsPerPageTest.php
@@ -71,7 +71,7 @@ function testItemsPerPage() {
// Confirm that the block is listed in the block administration UI.
$this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default'));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$this->assertText($view['label']);
// Place the block, visit a page that displays the block, and check that the
diff --git a/core/modules/views_ui/src/Tests/OverrideDisplaysTest.php b/core/modules/views_ui/src/Tests/OverrideDisplaysTest.php
index 15b6c88..2a693f7 100644
--- a/core/modules/views_ui/src/Tests/OverrideDisplaysTest.php
+++ b/core/modules/views_ui/src/Tests/OverrideDisplaysTest.php
@@ -50,7 +50,7 @@ function testOverrideDisplays() {
// Confirm that the view block is available in the block administration UI.
$this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default'));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$this->assertText($view['label']);
// Place the block.
@@ -110,7 +110,7 @@ function testWizardMixedDefaultOverriddenDisplays() {
// Confirm that the block is available in the block administration UI.
$this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default'));
- $this->clickLink('Place block');
+ $this->clickLinkPartialName('Place block');
$this->assertText($view['label']);
// Put the block into the first sidebar region, and make sure it will not