diff --git a/core/modules/system/tests/modules/test_page_test/src/Form/TestForm.php b/core/modules/system/tests/modules/test_page_test/src/Form/TestForm.php
index 5f25dd7..6ce4115 100644
--- a/core/modules/system/tests/modules/test_page_test/src/Form/TestForm.php
+++ b/core/modules/system/tests/modules/test_page_test/src/Form/TestForm.php
@@ -57,6 +57,18 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#value' => $this->t('Save'),
     ];
 
+    $form['duplicate_button'] = [
+      '#type' => 'submit',
+      '#name' => 'duplicate_button',
+      '#value' => 'Duplicate button 1',
+    ];
+
+    $form['duplicate_button_2'] = [
+      '#type' => 'submit',
+      '#name' => 'duplicate_button',
+      '#value' => 'Duplicate button 2',
+    ];
+
     return $form;
   }
 
diff --git a/core/tests/Drupal/FunctionalTests/AssertLegacyTrait.php b/core/tests/Drupal/FunctionalTests/AssertLegacyTrait.php
index c88949d..866bad4 100644
--- a/core/tests/Drupal/FunctionalTests/AssertLegacyTrait.php
+++ b/core/tests/Drupal/FunctionalTests/AssertLegacyTrait.php
@@ -223,10 +223,7 @@ protected function assertResponse($code) {
    *   $this->assertSession()->fieldValueEquals() instead.
    */
   protected function assertFieldByName($name, $value = NULL) {
-    $this->assertSession()->fieldExists($name);
-    if ($value !== NULL) {
-      $this->assertSession()->fieldValueEquals($name, (string) $value);
-    }
+    $this->assertFieldByXPath($this->constructFieldXpath('name', $name), $value);
   }
 
   /**
@@ -245,12 +242,7 @@ protected function assertFieldByName($name, $value = NULL) {
    *   $this->assertSession()->fieldValueNotEquals() instead.
    */
   protected function assertNoFieldByName($name, $value = '') {
-    if ($this->getSession()->getPage()->findField($name) && isset($value)) {
-      $this->assertSession()->fieldValueNotEquals($name, (string) $value);
-    }
-    else {
-      $this->assertSession()->fieldNotExists($name);
-    }
+    $this->assertNoFieldByXPath($this->constructFieldXpath('name', $name), $value);
   }
 
   /**
@@ -271,16 +263,7 @@ protected function assertNoFieldByName($name, $value = '') {
    *   $this->assertSession()->fieldValueEquals() instead.
    */
   protected function assertFieldById($id, $value = '') {
-    $xpath = $this->assertSession()->buildXPathQuery('//textarea[@id=:value]|//input[@id=:value]|//select[@id=:value]', [':value' => $id]);
-    $field = $this->getSession()->getPage()->find('xpath', $xpath);
-
-    if (empty($field)) {
-      throw new ElementNotFoundException($this->getSession()->getDriver(), 'form field', 'id', $field);
-    }
-
-    if ($value !== NULL) {
-      $this->assertEquals($value, $field->getValue());
-    }
+    $this->assertFieldByXPath($this->constructFieldXpath('id', $id), $value);
   }
 
   /**
@@ -293,7 +276,7 @@ protected function assertFieldById($id, $value = '') {
    *   Use $this->assertSession()->fieldExists() instead.
    */
   protected function assertField($field) {
-    $this->assertSession()->fieldExists($field);
+    $this->assertFieldByXPath($this->constructFieldXpath('name', $field) . '|' . $this->constructFieldXpath('id', $field));
   }
 
   /**
@@ -306,7 +289,7 @@ protected function assertField($field) {
    *   Use $this->assertSession()->fieldNotExists() instead.
    */
   protected function assertNoField($field) {
-    $this->assertSession()->fieldNotExists($field);
+    $this->assertNoFieldByXPath($this->constructFieldXpath('name', $field) . '|' . $this->constructFieldXpath('id', $field), NULL);
   }
 
   /**
@@ -430,20 +413,7 @@ protected function assertNoLinkByHref($href) {
    *   $this->assertSession()->fieldValueNotEquals() instead.
    */
   protected function assertNoFieldById($id, $value = '') {
-    $xpath = $this->assertSession()->buildXPathQuery('//textarea[@id=:value]|//input[@id=:value]|//select[@id=:value]', [':value' => $id]);
-    $field = $this->getSession()->getPage()->find('xpath', $xpath);
-
-    // Return early if the field could not be found as expected.
-    if ($field === NULL) {
-      return;
-    }
-
-    if (!isset($value)) {
-      throw new ExpectationException(sprintf('Id "%s" appears on this page, but it should not.', $id), $this->getSession()->getDriver());
-    }
-    elseif ($value === $field->getValue()) {
-      throw new ExpectationException(sprintf('Failed asserting that %s is not equal to %s', $field->getValue(), $value), $this->getSession()->getDriver());
-    }
+    $this->assertNoFieldByXPath($this->constructFieldXpath('id', $id), $value);
   }
 
   /**
@@ -564,13 +534,20 @@ protected function assertNoFieldChecked($id) {
    *   (optional) A message to display with the assertion. Do not translate
    *   messages with t().
    *
+   * @throws \Behat\Mink\Exception\ExpectationException
+   *
    * @deprecated Scheduled for removal in Drupal 9.0.0.
    *   Use $this->xpath() instead and check the values directly in the test.
    */
   protected function assertFieldByXPath($xpath, $value = NULL, $message = '') {
-    $fields = $this->xpath($xpath);
+    try {
+      $fields = $this->xpath($xpath);
 
-    $this->assertFieldsByValue($fields, $value, $message);
+      $this->assertFieldsByValue($fields, $value, $message);
+    }
+    catch (\PHPUnit_Framework_ExpectationFailedException $e) {
+      throw new ExpectationException($e->getMessage(), $this->getSession()->getDriver());
+    }
   }
 
   /**
@@ -585,25 +562,32 @@ protected function assertFieldByXPath($xpath, $value = NULL, $message = '') {
    *   (optional) A message to display with the assertion. Do not translate
    *   messages with t().
    *
+   * @throws \Behat\Mink\Exception\ExpectationException
+   *
    * @deprecated Scheduled for removal in Drupal 9.0.0.
    *   Use $this->xpath() instead and assert that the result is empty.
    */
   protected function assertNoFieldByXPath($xpath, $value = NULL, $message = '') {
-    $fields = $this->xpath($xpath);
-
-    // If value specified then check array for match.
-    $found = TRUE;
-    if (isset($value)) {
-      $found = FALSE;
-      if ($fields) {
-        foreach ($fields as $field) {
-          if ($field->getAttribute('value') == $value) {
-            $found = TRUE;
+    try {
+      $fields = $this->xpath($xpath);
+
+      // If value specified then check array for match.
+      $found = TRUE;
+      if (isset($value)) {
+        $found = FALSE;
+        if ($fields) {
+          foreach ($fields as $field) {
+            if ($field->getAttribute('value') == $value) {
+              $found = TRUE;
+            }
           }
         }
       }
+      $this->assertFalse($fields && $found, $message);
+    }
+    catch (\PHPUnit_Framework_ExpectationFailedException $e) {
+      throw new ExpectationException($e->getMessage(), $this->getSession()->getDriver());
     }
-    return $this->assertFalse($fields && $found, $message);
   }
 
   /**
@@ -637,7 +621,7 @@ protected function assertFieldsByValue($fields, $value = NULL, $message = '') {
             // Select element with an option.
             $found = TRUE;
           }
-          elseif ($field->getText() == $value) {
+          elseif ($field->getTagName() !== 'input' && $field->getText() == $value) {
             // Text area with correct text.
             $found = TRUE;
           }
@@ -773,6 +757,25 @@ protected function buildXPathQuery($xpath, array $args = []) {
   }
 
   /**
+   * Helper: Constructs an XPath for the given set of attributes and value.
+   *
+   * @param string $attribute
+   *   Field attributes.
+   * @param string $value
+   *   Value of field.
+   *
+   * @return string
+   *   XPath for specified values.
+   *
+   * @deprecated Scheduled for removal in Drupal 9.0.0.
+   *   Use $this->getSession()->getPage()->findField() instead.
+   */
+  protected function constructFieldXpath($attribute, $value) {
+    $xpath = '//textarea[@' . $attribute . '=:value]|//input[@' . $attribute . '=:value]|//select[@' . $attribute . '=:value]';
+    return $this->buildXPathQuery($xpath, [':value' => $value]);
+  }
+
+  /**
    * Gets the current raw content.
    *
    * @deprecated Scheduled for removal in Drupal 9.0.0.
diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
index 9931804..de70742 100644
--- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
+++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
@@ -165,6 +165,38 @@ public function testLegacyFieldAsserts() {
     $this->assertFieldsByValue($this->xpath("//select[@id = 'edit-options']"), '2');
     $this->assertFieldByXPath("//select[@id = 'edit-options']", '2');
 
+    $this->assertNoField('invalid_name_and_id');
+    $this->assertField('name');
+    $this->assertField('edit-name');
+
+    // Test that the assertion fails correctly when searching by name.
+    try {
+      $this->assertNoField('name');
+      $this->fail('The "name" field was not found based on name.');
+    }
+    catch (ExpectationException $e) {
+      $this->pass('The "name" field was found by name.');
+    }
+
+    // Test that the assertion fails correctly when searching by id.
+    try {
+      $this->assertNoField('edit-name');
+      $this->fail('The "name" field was not found based on id.');
+    }
+    catch (ExpectationException $e) {
+      $this->pass('The "name" field was found by id.');
+    }
+
+    // Assert that assertion correctly fails when searching for the name field
+    // without a value.
+    try {
+      $this->assertFieldsByValue($this->xpath("//input[@id = 'edit-name']"), '');
+      $this->fail('The "name" field, with no value was found.');
+    }
+    catch (\PHPUnit_Framework_ExpectationFailedException $e) {
+      $this->pass('The "name" field, with no value was found.');
+    }
+
     $this->assertNoFieldByXPath('//notexisting');
     $this->assertNoFieldByXPath("//input[@id = 'edit-name']", 'wrong value');
 
@@ -201,13 +233,13 @@ public function testLegacyFieldAsserts() {
       $this->assertFieldById('edit-name');
       $this->fail('The "edit-name" field with no value was found.');
     }
-    catch (\PHPUnit_Framework_ExpectationFailedException $e) {
+    catch (ExpectationException $e) {
       $this->pass('The "edit-name" field with no value was not found.');
     }
 
-    // Test that the assertion fails correctly if NULL is passed in.
+    // Test that the assertion fails correctly if another value is passed in.
     try {
-      $this->assertFieldById('name', NULL);
+      $this->assertFieldById('edit-name', 'not the value');
       $this->fail('The "name" field was found.');
     }
     catch (ExpectationException $e) {
@@ -237,6 +269,19 @@ public function testLegacyFieldAsserts() {
       $this->pass('The "name" field was found.');
     }
 
+    // Test that multiple fields with the same name are validated correctly.
+    $this->assertFieldByName('duplicate_button', 'Duplicate button 1');
+    $this->assertFieldByName('duplicate_button', 'Duplicate button 2');
+    $this->assertNoFieldByName('duplicate_button', 'Rabbit');
+
+    try {
+      $this->assertNoFieldByName('duplicate_button', 'Duplicate button 2');
+      $this->fail('The "duplicate_button" field with the value Duplicate button 2 was not found.');
+    }
+    catch (ExpectationException $e) {
+      $this->pass('The "duplicate_button" field with the value Duplicate button 2 was found.');
+    }
+
     $this->assertOptionByText('options', 'one');
     try {
       $this->assertOptionByText('options', 'four');
