diff --git a/core/modules/block/src/Tests/Views/DisplayBlockTest.php b/core/modules/block/src/Tests/Views/DisplayBlockTest.php index 7f3665a..d3fcf28 100644 --- a/core/modules/block/src/Tests/Views/DisplayBlockTest.php +++ b/core/modules/block/src/Tests/Views/DisplayBlockTest.php @@ -288,8 +288,13 @@ public function testBlockContextualLinks() { $response = $this->drupalPost('contextual/render', 'application/json', $post, array('query' => array('destination' => 'test-page'))); $this->assertResponse(200); $json = Json::decode($response); - $this->assertIdentical($json[$id], ''); - $this->assertIdentical($json[$cached_id], ''); + $this->setRawContent($json[$id]); + $result = $this->xpath('//ul/li/a[contains(@href, :href) and text()="Configure block"] | /li/a[contains(@href, "admin/structure/views/view/test_view_block/edit/block_1") and text()="Edit view"]', [':href' => "admin/structure/block/manage/" . $block->id()]); + $this->assertTrue($result, 'The contextual link is present.'); + $this->setRawContent($json[$cached_id]); + $result = $this->xpath('//ul/li/a[contains(@href, :href) and text()="Configure block"] | /li/a[contains(@href, "admin/structure/views/view/test_view_block/edit/block_1") and text()="Edit view"]', [':href' => "admin/structure/block/manage/" . $cached_block->id()]); + $this->assertTrue($result, 'The contextual link is present.'); + } } diff --git a/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php b/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php index 20d55cd..8b7ea7b 100644 --- a/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php +++ b/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php @@ -95,9 +95,13 @@ function testDifferentPermissions() { $response = $this->renderContextualLinks($ids, 'node'); $this->assertResponse(200); $json = Json::decode($response); - $this->assertIdentical($json[$ids[0]], ''); + $this->setRawContent($json[$ids[0]]); + $result = $this->xpath('//ul/li/a[contains(@href, :href) and text()="Edit"]', [':href' => "node/1/edit"]); + $this->assertTrue($result, 'The contextual link is present.'); $this->assertIdentical($json[$ids[1]], ''); - $this->assertIdentical($json[$ids[2]], ''); + $this->setRawContent($json[$ids[2]]); + $result = $this->xpath('//ul/li/a[contains(@href, :href) and text()="Edit"]', [':href' => "node/3/edit"]); + $this->assertTrue($result, 'The contextual link is present.'); $this->assertIdentical($json[$ids[3]], ''); // Authenticated user: can access contextual links, cannot edit articles. diff --git a/core/modules/menu_ui/src/Tests/MenuTest.php b/core/modules/menu_ui/src/Tests/MenuTest.php index 722548f..039281f 100644 --- a/core/modules/menu_ui/src/Tests/MenuTest.php +++ b/core/modules/menu_ui/src/Tests/MenuTest.php @@ -577,7 +577,9 @@ public function testBlockContextualLinks() { $response = $this->drupalPost('contextual/render', 'application/json', $post, array('query' => array('destination' => 'test-page'))); $this->assertResponse(200); $json = Json::decode($response); - $this->assertIdentical($json[$id], ''); + $this->setRawContent($json[$id]); + $result = $this->xpath('//ul/li/a[contains(@href, :block_id) and text()="Configure block"] | /li/a[contains(@href, :custom_menu) and text()="Edit menu"]', [':block_id' => "admin/structure/block/manage/" . $block->id(), ':custom_menu' => "admin/structure/block/manage/" . $custom_menu->id()]); + $this->assertTrue($result, 'The contextual link is present.'); } /** diff --git a/core/modules/simpletest/src/AssertContentTrait.php b/core/modules/simpletest/src/AssertContentTrait.php index 100a1c9..2622853 100644 --- a/core/modules/simpletest/src/AssertContentTrait.php +++ b/core/modules/simpletest/src/AssertContentTrait.php @@ -822,6 +822,39 @@ protected function assertThemeOutput($callback, array $variables = array(), $exp } /** + * Asserts themed output. + * + * @param string $callback + * The name of the theme hook to invoke; e.g. 'links' for links.html.twig. + * @param string $variables + * An array of variables to pass to the theme function. + * @param string $expected + * The expected themed output string formatted for XPath. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertThemeOutputByXPath($callback, array $variables = array(), $expected = '', $message = '', $group = 'Other') { + $output = \Drupal::theme()->render($callback, $variables); + if (!$message) { + $message = '%callback rendered correctly.'; + } + $message = format_string($message, array('%callback' => 'theme_' . $callback . '()')); + $this->setRawContent($output); + $result = $this->xpath($expected); + return $this->assertTrue($result, $message, $group); + } + + /** * Asserts that a field exists in the current page by the given XPath. * * @param string $xpath diff --git a/core/modules/system/src/Tests/Theme/FunctionsTest.php b/core/modules/system/src/Tests/Theme/FunctionsTest.php index a9a3dae..6d18ad6 100644 --- a/core/modules/system/src/Tests/Theme/FunctionsTest.php +++ b/core/modules/system/src/Tests/Theme/FunctionsTest.php @@ -217,21 +217,20 @@ function testLinks() { ); $expected_links = ''; - $expected_links .= ''; + $expected_links .= '/li/a[contains(@href, "' . \Drupal::urlGenerator()->generate('router_test.1', $query) . '") and text()="' . SafeMarkup::checkPlain('Query test route') . '"]'; // Verify that passing a string as heading works. $variables['heading'] = 'Links heading'; - $expected_heading = '

Links heading

'; + $expected_heading = '//h2[text()="Links heading"] | '; $expected = $expected_heading . $expected_links; - $this->assertThemeOutput('links', $variables, $expected); + $this->assertThemeOutputByXPath('links', $variables, $expected); // Restore the original request's query. \Drupal::request()->query->replace($original_query); @@ -242,49 +241,47 @@ function testLinks() { 'level' => 'h3', 'attributes' => array('class' => array('heading')), ); - $expected_heading = '

Links heading

'; + $expected_heading = '//h3[text()="Links heading"] | '; $expected = $expected_heading . $expected_links; - $this->assertThemeOutput('links', $variables, $expected); + $this->assertThemeOutputByXPath('links', $variables, $expected); // Verify that passing attributes for the heading works. $variables['heading'] = array('text' => 'Links heading', 'level' => 'h3', 'attributes' => array('id' => 'heading')); - $expected_heading = '

Links heading

'; + $expected_heading = '//h3[contains(@id, "heading") and text()="Links heading"] | '; $expected = $expected_heading . $expected_links; - $this->assertThemeOutput('links', $variables, $expected); + $this->assertThemeOutputByXPath('links', $variables, $expected); // Verify that passing attributes for the links work. $variables['links']['plain text']['attributes'] = array( 'class' => array('a/class'), ); $expected_links = ''; - $expected_links .= ''; + $expected_links .= '/li/a[contains(@href, "' . \Drupal::urlGenerator()->generate('router_test.1', $query) . '") and text()="' . SafeMarkup::checkPlain('Query test route') . '"]'; $expected = $expected_heading . $expected_links; - $this->assertThemeOutput('links', $variables, $expected); + $this->assertThemeOutputByXPath('links', $variables, $expected); // Verify the data- attributes for setting the "active" class on links. \Drupal::currentUser()->setAccount(new UserSession(array('uid' => 1))); $variables['set_active_class'] = TRUE; $expected_links = ''; - $expected_links .= ''; + $expected_links .= '/li[contains(@data-drupal-link-query, "'.$encoded_query.'") and contains(@data-drupal-link-system-path, "router_test/test1")]/a[contains(@href, "' . \Drupal::urlGenerator()->generate('router_test.1', $query) . '") and contains(@data-drupal-link-query, "'.$encoded_query.'") and contains(@data-drupal-link-system-path, "router_test/test1") and text()="' . SafeMarkup::checkPlain('Query test route') . '"]'; $expected = $expected_heading . $expected_links; - $this->assertThemeOutput('links', $variables, $expected); + $this->assertThemeOutputByXPath('links', $variables, $expected); } /** @@ -353,9 +350,9 @@ function testDrupalPreRenderLinks() { $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered HTML.'); $list_elements = $dom->getElementsByTagName('li'); $this->assertEqual($list_elements->length, 3, 'Three "li" tags found in the rendered HTML.'); - $this->assertEqual($list_elements->item(0)->nodeValue, 'Parent link original', 'First expected link found.'); - $this->assertEqual($list_elements->item(1)->nodeValue, 'First child link', 'Second expected link found.'); - $this->assertEqual($list_elements->item(2)->nodeValue, 'Second child link', 'Third expected link found.'); + $this->assertEqual(trim($list_elements->item(0)->nodeValue), 'Parent link original', 'First expected link found.'); + $this->assertEqual(trim($list_elements->item(1)->nodeValue), 'First child link', 'Second expected link found.'); + $this->assertEqual(trim($list_elements->item(2)->nodeValue), 'Second child link', 'Third expected link found.'); $this->assertIdentical(strpos($html, 'Parent link copy'), FALSE, '"Parent link copy" link not found.'); $this->assertIdentical(strpos($html, 'Third child link'), FALSE, '"Third child link" link not found.'); @@ -371,16 +368,16 @@ function testDrupalPreRenderLinks() { $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered child HTML.'); $list_elements = $dom->getElementsByTagName('li'); $this->assertEqual($list_elements->length, 2, 'Two "li" tags found in the rendered child HTML.'); - $this->assertEqual($list_elements->item(0)->nodeValue, 'Parent link copy', 'First expected link found.'); - $this->assertEqual($list_elements->item(1)->nodeValue, 'First child link', 'Second expected link found.'); + $this->assertEqual(trim($list_elements->item(0)->nodeValue), 'Parent link copy', 'First expected link found.'); + $this->assertEqual(trim($list_elements->item(1)->nodeValue), 'First child link', 'Second expected link found.'); // Then check the parent HTML. $dom = new \DOMDocument(); $dom->loadHTML($parent_html); $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered parent HTML.'); $list_elements = $dom->getElementsByTagName('li'); $this->assertEqual($list_elements->length, 2, 'Two "li" tags found in the rendered parent HTML.'); - $this->assertEqual($list_elements->item(0)->nodeValue, 'Parent link original', 'First expected link found.'); - $this->assertEqual($list_elements->item(1)->nodeValue, 'Second child link', 'Second expected link found.'); + $this->assertEqual(trim($list_elements->item(0)->nodeValue), 'Parent link original', 'First expected link found.'); + $this->assertEqual(trim($list_elements->item(1)->nodeValue), 'Second child link', 'Second expected link found.'); $this->assertIdentical(strpos($parent_html, 'First child link'), FALSE, '"First child link" link not found.'); $this->assertIdentical(strpos($parent_html, 'Third child link'), FALSE, '"Third child link" link not found.'); } diff --git a/core/modules/system/templates/links.html.twig b/core/modules/system/templates/links.html.twig index 21ab95d..479f0dd 100644 --- a/core/modules/system/templates/links.html.twig +++ b/core/modules/system/templates/links.html.twig @@ -36,25 +36,25 @@ * @ingroup themeable */ #} -{% if links -%} - {%- if heading -%} - {%- if heading.level -%} +{% if links %} + {% if heading %} + {% if heading.level %} <{{ heading.level }}{{ heading.attributes }}>{{ heading.text }} - {%- else -%} + {% else %} {{ heading.text }} - {%- endif -%} - {%- endif -%} + {% endif %} + {% endif %} - {%- for key, item in links -%} + {% for key, item in links %} - {%- if item.link -%} + {% if item.link %} {{ item.link }} - {%- elseif item.text_attributes -%} + {% elseif item.text_attributes %} {{ item.text }} - {%- else -%} + {% else %} {{ item.text }} - {%- endif -%} + {% endif %} - {%- endfor -%} + {% endfor %} -{%- endif %} +{% endif %} diff --git a/core/modules/views_ui/src/Tests/DisplayTest.php b/core/modules/views_ui/src/Tests/DisplayTest.php index 12c06bd..9807187 100644 --- a/core/modules/views_ui/src/Tests/DisplayTest.php +++ b/core/modules/views_ui/src/Tests/DisplayTest.php @@ -191,7 +191,9 @@ public function testPageContextualLinks() { $response = $this->drupalPost('contextual/render', 'application/json', $post, array('query' => array('destination' => 'test-display'))); $this->assertResponse(200); $json = Json::decode($response); - $this->assertIdentical($json[$id], ''); + $this->setRawContent($json[$id]); + $result = $this->xpath('//ul/li/a[contains(@href, :href) and text()="Edit view"]', [':href' => "admin/structure/views/view/test_display/edit/page_1"]); + $this->assertTrue($result, 'The contextual link is present.'); } /** diff --git a/core/themes/classy/templates/navigation/links.html.twig b/core/themes/classy/templates/navigation/links.html.twig index 5f62ac3..1d91953 100644 --- a/core/themes/classy/templates/navigation/links.html.twig +++ b/core/themes/classy/templates/navigation/links.html.twig @@ -34,25 +34,25 @@ * @see template_preprocess_links() */ #} -{% if links -%} - {%- if heading -%} - {%- if heading.level -%} +{% if links %} + {% if heading %} + {% if heading.level %} <{{ heading.level }}{{ heading.attributes }}>{{ heading.text }} - {%- else -%} + {% else %} {{ heading.text }} - {%- endif -%} - {%- endif -%} + {% endif %} + {% endif %} - {%- for key, item in links -%} + {% for key, item in links %} - {%- if item.link -%} + {% if item.link %} {{ item.link }} - {%- elseif item.text_attributes -%} + {% elseif item.text_attributes %} {{ item.text }} - {%- else -%} + {% else %} {{ item.text }} - {%- endif -%} + {% endif %} - {%- endfor -%} + {% endfor %} -{%- endif %} +{% endif %}