diff --git a/core/modules/image/src/Tests/ImageAdminStylesTest.php b/core/modules/image/src/Tests/ImageAdminStylesTest.php
index 869e0c1..56d80fe 100644
--- a/core/modules/image/src/Tests/ImageAdminStylesTest.php
+++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
@@ -292,6 +292,47 @@ function testStyle() {
   }
 
   /**
+   * Tests editing Ajax-enabled image effect forms.
+   */
+  public function testAjaxEnabledEffectForm() {
+    $admin_path = 'admin/config/media/image-styles';
+
+    // Setup a style to be created and effects to add to it.
+    $style_name = strtolower($this->randomMachineName(10));
+    $style_label = $this->randomString();
+    $style_path = $admin_path . '/manage/' . $style_name;
+    $effect_edit = [
+      'data[test_parameter]' => 100,
+    ];
+
+    // Add style form.
+    $edit = [
+      'name' => $style_name,
+      'label' => $style_label,
+    ];
+    $this->drupalPostForm($admin_path . '/add', $edit, t('Create new style'));
+    $this->assertRaw(t('Style %name was created.', ['%name' => $style_label]));
+
+    // Add two Ajax-enabled test effects.
+    $this->drupalPostForm($style_path, ['new' => 'image_module_test_ajax'], t('Add'));
+    $this->drupalPostForm(NULL, $effect_edit, t('Add effect'));
+    $this->drupalPostForm($style_path, ['new' => 'image_module_test_ajax'], t('Add'));
+    $this->drupalPostForm(NULL, $effect_edit, t('Add effect'));
+
+    // Load the saved image style.
+    $style = ImageStyle::load($style_name);
+
+    // Edit back the effects.
+    foreach ($style->getEffects() as $uuid => $effect) {
+      $effect_path = $admin_path . '/manage/' . $style_name . '/effects/' . $uuid;
+      $this->drupalGet($effect_path);
+      $this->drupalPostAjaxForm(NULL, $effect_edit, ['op' => t('Ajax refresh')]);
+      $this->drupalPostForm(NULL, $effect_edit, t('Update effect'));
+    }
+
+  }
+
+  /**
    * Test deleting a style and choosing a replacement style.
    */
   function testStyleReplacement() {
diff --git a/core/modules/image/tests/modules/image_module_test/config/schema/image_module_test.schema.yml b/core/modules/image/tests/modules/image_module_test/config/schema/image_module_test.schema.yml
index b0e8ebf..9158f56 100644
--- a/core/modules/image/tests/modules/image_module_test/config/schema/image_module_test.schema.yml
+++ b/core/modules/image/tests/modules/image_module_test/config/schema/image_module_test.schema.yml
@@ -1,3 +1,11 @@
+image.effect.image_module_test_ajax:
+  type: mapping
+  label: 'Ajax test'
+  mapping:
+    test_parameter:
+      type: integer
+      label: 'Test Parameter'
+
 image.style.*.third_party.image_module_test:
   type: mapping
   label: 'Schema for image_module_test module additions to image_style entity'
diff --git a/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php b/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php
new file mode 100644
index 0000000..0fae539
--- /dev/null
+++ b/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image_module_test\Plugin\ImageEffect\AjaxTestImageEffect.
+ */
+
+namespace Drupal\image_module_test\Plugin\ImageEffect;
+
+use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Ajax\HtmlCommand;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Image\ImageInterface;
+use Drupal\image\ConfigurableImageEffectBase;
+
+/**
+ * Provides a test effect using Ajax in the configuration form.
+ *
+ * @ImageEffect(
+ *   id = "image_module_test_ajax",
+ *   label = @Translation("Ajax test")
+ * )
+ */
+class AjaxTestImageEffect extends ConfigurableImageEffectBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return [
+      'test_parameter' => 0,
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    $form['test_parameter'] = [
+      '#type' => 'number',
+      '#title' => t('Test parameter'),
+      '#default_value' => $this->configuration['test_parameter'],
+      '#min' => 0,
+    ];
+    $form['ajax_refresh'] = [
+      '#type' => 'button',
+      '#value' => $this->t('Ajax refresh'),
+      '#ajax' => ['callback' => [$this, 'ajaxCallback']],
+    ];
+    $form['ajax_value'] = [
+      '#id' => 'ajax-value',
+      '#type' => 'item',
+      '#title' => $this->t('Ajax value'),
+      '#markup' => 'bar',
+    ];
+    return $form;
+  }
+
+  /**
+   * AJAX callback.
+   */
+  public function ajaxCallback($form, FormStateInterface $form_state) {
+    $item = [
+      '#type' => 'item',
+      '#title' => $this->t('Ajax value'),
+      '#markup' => microtime(),
+    ];
+    $response = new AjaxResponse();
+    $response->addCommand(new HtmlCommand('#ajax-value', $item));
+    return $response;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+    parent::submitConfigurationForm($form, $form_state);
+
+    $this->configuration['test_parameter'] = $form_state->getValue('test_parameter');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function applyEffect(ImageInterface $image) {
+    return TRUE;
+  }
+
+}
