diff --git a/core/modules/book/tests/src/FunctionalJavascript/BookJavascriptTest.php b/core/modules/book/tests/src/FunctionalJavascript/BookJavascriptTest.php
index d8d406b440..33528cd2e3 100644
--- a/core/modules/book/tests/src/FunctionalJavascript/BookJavascriptTest.php
+++ b/core/modules/book/tests/src/FunctionalJavascript/BookJavascriptTest.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\Tests\book\FunctionalJavascript;
 
-use Behat\Mink\Exception\ExpectationException;
 use Drupal\Component\Render\FormattableMarkup;
 use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
 use Drupal\node\Entity\Node;
@@ -59,7 +58,7 @@ public function testBookOrdering() {
     $this->assertGreaterThan($weight_select1->getValue(), $weight_select2->getValue());
 
     // Check that '1st page' precedes the '2nd page'.
-    $this->assertOrderInPage(['1st page', '2nd page']);
+    $this->assertSession()->orderInPageText(['1st page', '2nd page']);
 
     // Check that the 'unsaved changes' text is not present in the message area.
     $this->assertSession()->pageTextNotContains('You have unsaved changes.');
@@ -79,7 +78,7 @@ public function testBookOrdering() {
     $this->assertSession()->pageTextContains('You have unsaved changes.');
 
     // Check that '2nd page' page precedes the '1st page'.
-    $this->assertOrderInPage(['2nd page', '1st page']);
+    $this->assertSession()->orderInPageText(['2nd page', '1st page']);
 
     $this->submitForm([], 'Save book pages');
     $this->assertSession()->pageTextContains(new FormattableMarkup('Updated book @book.', ['@book' => $book->getTitle()]));
@@ -90,7 +89,7 @@ public function testBookOrdering() {
     $this->assertGreaterThan($page2->book['weight'], $page1->book['weight']);
 
     // Check again that '2nd page' is on top after form submit in the UI.
-    $this->assertOrderInPage(['2nd page', '1st page']);
+    $this->assertSession()->orderInPageText(['2nd page', '1st page']);
 
     // Toggle row weight selects as visible.
     $page->findButton('Show row weights')->click();
@@ -120,7 +119,7 @@ public function testBookOrdering() {
     $this->assertSession()->pageTextContains(new FormattableMarkup('Updated book @book.', ['@book' => $book->getTitle()]));
 
     // Check that the '1st page' is first again.
-    $this->assertOrderInPage(['1st page', '2nd page']);
+    $this->assertSession()->orderInPageText(['1st page', '2nd page']);
 
     // Check that page reordering was done in the backend for manual weight
     // field usage.
@@ -129,32 +128,4 @@ public function testBookOrdering() {
     $this->assertGreaterThan($page2->book['weight'], $page1->book['weight']);
   }
 
-  /**
-   * Asserts that several pieces of markup are in a given order in the page.
-   *
-   * @param string[] $items
-   *   An ordered list of strings.
-   *
-   * @throws \Behat\Mink\Exception\ExpectationException
-   *   When any of the given string is not found.
-   *
-   * @todo Remove this once https://www.drupal.org/node/2817657 is committed.
-   */
-  protected function assertOrderInPage(array $items) {
-    $session = $this->getSession();
-    $text = $session->getPage()->getHtml();
-    $strings = [];
-    foreach ($items as $item) {
-      if (($pos = strpos($text, $item)) === FALSE) {
-        throw new ExpectationException("Cannot find '$item' in the page", $session->getDriver());
-      }
-      $strings[$pos] = $item;
-    }
-    ksort($strings);
-    $ordered = implode(', ', array_map(function ($item) {
-      return "'$item'";
-    }, $items));
-    $this->assertSame($items, array_values($strings), "Found strings, ordered as: $ordered.");
-  }
-
 }
diff --git a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php
index 2de84e9593..33f8a8d03e 100644
--- a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php
+++ b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php
@@ -108,4 +108,14 @@ public function renderPipeInLink() {
     return ['#markup' => '<a href="http://example.com">foo|bar|baz</a>'];
   }
 
+  /**
+   * Renders a page with strings in a specific order.
+   *
+   * @return array
+   *   A render array as expected by drupal_render()
+   */
+  public function renderOrderInPage() {
+    return ['#markup' => 'item3<p class="item1 item2 item3">item2</p>item1'];
+  }
+
 }
diff --git a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml
index 5d84695f8b..8edc37c352 100644
--- a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml
+++ b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml
@@ -82,3 +82,11 @@ test_page_test.field_xpath:
     _form: '\Drupal\test_page_test\Form\TestForm'
   requirements:
     _access: 'TRUE'
+
+test_page_test.order_in_page:
+  path: '/test-order-in-page'
+  defaults:
+    _title: 'Page with strings in a given order'
+    _controller: '\Drupal\test_page_test\Controller\Test::renderOrderInPage'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
index 9931804232..0d3c3bf95c 100644
--- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
+++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\FunctionalTests;
 
+use Behat\Mink\Exception\ElementNotFoundException;
 use Behat\Mink\Exception\ExpectationException;
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Url;
@@ -289,4 +290,19 @@ public function testInstall() {
     $this->assertTrue(file_exists($htaccess_filename), "$htaccess_filename exists");
   }
 
+  /**
+   * Tests assertion of string sequence in page content and page text.
+   */
+  public function testOrderInPage() {
+    $this->drupalGet('test-order-in-page');
+
+    // Check that asserting order in page markup and page works.
+    $this->assertSession()->orderInPageContent(['item3', 'item1', 'item2']);
+    $this->assertSession()->orderInPageText(['item3', 'item2', 'item1']);
+
+    // Check that passing non-existent search strings throws an exception.
+    $this->setExpectedException(ElementNotFoundException::class, "Cannot find item(s): 'item5', 'item8'.");
+    $this->assertSession()->orderInPageContent(['item5', 'item1', 'item8']);
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/WebAssert.php b/core/tests/Drupal/Tests/WebAssert.php
index ea42517818..4523ef3c17 100644
--- a/core/tests/Drupal/Tests/WebAssert.php
+++ b/core/tests/Drupal/Tests/WebAssert.php
@@ -501,4 +501,68 @@ public function hiddenFieldValueNotEquals($field, $value, TraversableElement $co
     $this->assert(!preg_match($regex, $actual), $message);
   }
 
+  /**
+   * Asserts that several strings are in a given order in the page content.
+   *
+   * @param string[] $items
+   *   An ordered list of strings.
+   */
+  public function orderInPageContent(array $items) {
+    $this->orderInPageHelper($items, $this->session->getPage()->getHtml());
+  }
+
+  /**
+   * Asserts that several strings are in a given order in the page text.
+   *
+   * @param string[] $items
+   *   An ordered list of strings.
+   */
+  public function orderInPageText(array $items) {
+    $this->orderInPageHelper($items, $this->session->getPage()->getText());
+  }
+
+  /**
+   * Provides a helper method for orderInPageText() and orderInPageContent().
+   *
+   * @param string[] $items
+   *   An ordered list of strings.
+   * @param string $string
+   *   The string to be searched.
+   *
+   * @throws \Behat\Mink\Exception\ElementNotFoundException
+   *   When one or more of passed items are not found.
+   *
+   * @see \Drupal\Tests\WebAssert::orderInPageContent()
+   * @see \Drupal\Tests\WebAssert::orderInPageText()
+   */
+  protected function orderInPageHelper(array $items, $string) {
+    $strings = $not_found = [];
+    foreach ($items as $item) {
+      if (($pos = strpos($string, $item)) === FALSE) {
+        if (!in_array($item, $not_found)) {
+          $not_found[] = $item;
+        }
+      }
+      else {
+        $strings[$pos] = $item;
+      }
+    }
+
+    $quote_string_list = function (array $list) {
+      return implode(', ', array_map(function ($string) {
+        return "'$string'";
+      }, $list));
+    };
+
+    if ($not_found) {
+      $not_found = $quote_string_list($not_found);
+      throw new ElementNotFoundException($this->session->getDriver(), "Cannot find item(s): $not_found.");
+    }
+
+    ksort($strings);
+    $ordered = $quote_string_list($items);
+
+    $this->assert($items === array_values($strings), "Strings correctly ordered as: $ordered.");
+  }
+
 }
