diff -u b/core/lib/Drupal/Core/Render/Element/MachineName.php b/core/lib/Drupal/Core/Render/Element/MachineName.php --- b/core/lib/Drupal/Core/Render/Element/MachineName.php +++ b/core/lib/Drupal/Core/Render/Element/MachineName.php @@ -213,9 +213,6 @@ /** * Form element validation handler for machine_name elements. * - * Note that #maxlength is validated by the form validator already, in - * \Drupal\Core\Form\FormValidatorInterface::validateForm(). - * * This checks that the submitted value: * - Does not contain the replacement character only. * - Does not contain disallowed characters. @@ -247,13 +244,10 @@ } } - // Verify that the machine name is unique. Check form state if we need to - // explicitly validate the element. This happens every time when an error - // has been set, since this breaks on AJAX requests - if ($form_state->get('needs_revalidation') === $element['#name'] || $element['#default_value'] !== $element['#value']) { + // Verify that the machine name is unique. + if (isset($element['#value'])) { $function = $element['#machine_name']['exists']; if (call_user_func($function, $element['#value'], $element, $form_state)) { - $form_state->set('needs_revalidation', $element['#name']); $form_state->setError($element, t('The machine-readable name is already in use. It must be unique.')); } } diff -u b/core/modules/media/tests/src/FunctionalJavascript/MediaTypeCreationTest.php b/core/modules/media/tests/src/FunctionalJavascript/MediaTypeCreationTest.php --- b/core/modules/media/tests/src/FunctionalJavascript/MediaTypeCreationTest.php +++ b/core/modules/media/tests/src/FunctionalJavascript/MediaTypeCreationTest.php @@ -99,9 +99,6 @@ // Create a new media type, which should create a new field we can reuse. $this->drupalGet('/admin/structure/media/add'); - // Choose the source plugin _before_ setting the label and machine name in - // order to guard against the regression in - // https://www.drupal.org/project/drupal/issues/2557299. $page->selectFieldOption('Media source', 'test'); $result = $assert_session->waitForElementVisible('css', 'fieldset[data-drupal-selector="edit-source-configuration"]'); $this->assertNotEmpty($result); @@ -113,10 +110,6 @@ $mediaTypeMachineName = str_replace(' ', '_', strtolower($label)); $this->drupalGet('admin/structure/media/add'); - - // Select the media source used by our media type. Do this before setting - // the label and machine name in order to guard against the regression in - // https://www.drupal.org/project/drupal/issues/2557299. $assert_session->fieldExists('Media source'); $assert_session->optionExists('Media source', 'test'); $page->selectFieldOption('Media source', 'test'); diff -u b/core/modules/system/tests/modules/form_test/src/Form/FormTestMachineNameValidationForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestMachineNameValidationForm.php --- b/core/modules/system/tests/modules/form_test/src/Form/FormTestMachineNameValidationForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestMachineNameValidationForm.php @@ -21,6 +21,10 @@ * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { + // Disable client-side validation so that we can test AJAX requests with + // invalid input. + $form['#attributes']['novalidate'] = 'novalidate'; + $form['name'] = [ '#type' => 'textfield', '#default_value' => $form_state->getValue('name'), @@ -57,7 +61,6 @@ ], '#required' => TRUE, '#ajax' => [ - 'trigger_as' => ['name' => 'snack_configure'], 'callback' => '::buildAjaxSnackConfigureForm', 'wrapper' => 'snack-config-form', 'method' => 'replace', @@ -71,30 +74,6 @@ ], '#tree' => TRUE, ]; - $form['snack_configure_button'] = [ - '#type' => 'submit', - '#name' => 'snack_configure', - '#value' => 'Configure snack', - '#limit_validation_errors' => [['snack']], - '#validate' => ['::buildAjaxSnackConfigureFormValidate'], - '#submit' => ['::buildAjaxSnackConfigureFormSubmit'], - '#executes_submit_callback' => TRUE, - '#ajax' => [ - 'callback' => '::buildAjaxSnackConfigureForm', - 'wrapper' => 'snack-config-form', - ], - '#attributes' => ['class' => ['js-hide']], - ]; - $form['snack_configs']['apple']['#type'] = 'details'; - $form['snack_configs']['apple']['#title'] = 'Configure Apple'; - $form['snack_configs']['apple']['#open'] = TRUE; - $form['snack_configs']['pear']['#type'] = 'details'; - $form['snack_configs']['pear']['#title'] = 'Configure pear'; - $form['snack_configs']['pear']['#open'] = TRUE; - $form['snack_configs']['potato']['#type'] = 'details'; - $form['snack_configs']['potato']['#title'] = 'Configure potato'; - $form['snack_configs']['potato']['#open'] = TRUE; - $form['submit'] = [ '#type' => 'submit', '#value' => 'Save', reverted: --- b/core/modules/system/tests/src/Functional/Form/FormTest.php +++ a/core/modules/system/tests/src/Functional/Form/FormTest.php @@ -770,36 +770,4 @@ $this->assertTrue(!empty($element), 'The textarea has the proper required attribute.'); } - /** - * Tests that a machine name is still required after an AJAX submit. - * - * This protects against the regression in https://www.drupal.org/node/2557299. - */ - public function testMachineNameRequiredFormAjaxSubmit() { - $this->drupalGet('/form-test/form-test-machine-name-validation'); - - $edit = []; - $this->submitForm($edit, 'Save'); - $this->assertResponse(200); - $this->assertText('Machine-readable name field is required.'); - - $edit = [ - 'name' => 'test 1', - 'id' => 'machine1', - 'snack' => 'apple' - ]; - $this->submitForm($edit, 'Save'); - $this->assertResponse(200); - $this->assertText('The form_test_machine_name_validation_form form has been submitted successfully.'); - - $edit = [ - 'name' => 'test 2', - 'id' => 'duplicate', - 'snack' => 'potato', - ]; - $this->submitForm($edit, 'snack_configure'); - $this->submitForm($edit, 'Save'); - $this->assertResponse(200); - $this->assertText('The machine-readable name is already in use. It must be unique.'); - } } only in patch2: unchanged: --- /dev/null +++ b/core/modules/system/tests/src/FunctionalJavascript/MachineNameValidationTest.php @@ -0,0 +1,46 @@ +assertSession(); + $this->drupalGet('/form-test/form-test-machine-name-validation'); + + $assert->buttonExists('Save')->press(); + $assert->pageTextContains('Machine-readable name field is required.'); + + $assert->fieldExists('Name')->setValue('test 1'); + $assert->fieldExists('id')->setValue('test_1'); + $assert->selectExists('snack')->selectOption('apple'); + $assert->assertWaitOnAjaxRequest(); + $assert->buttonExists('Save')->press(); + $assert->pageTextContains('The form_test_machine_name_validation_form form has been submitted successfully.'); + + $assert->fieldExists('Name')->setValue('duplicate'); + $this->assertJsCondition('document.forms[0].id.value === "duplicate"'); + $assert->selectExists('snack')->selectOption('potato'); + $assert->assertWaitOnAjaxRequest(); + $assert->buttonExists('Save')->press(); + $assert->pageTextContains('The machine-readable name is already in use. It must be unique.'); + } + +}