diff --git a/modules/webform_ui/src/Tests/WebformUiElementPropertiesTest.php b/modules/webform_ui/src/Tests/WebformUiElementPropertiesTest.php
index 5070eb82..64f76187 100644
--- a/modules/webform_ui/src/Tests/WebformUiElementPropertiesTest.php
+++ b/modules/webform_ui/src/Tests/WebformUiElementPropertiesTest.php
@@ -24,7 +24,7 @@ class WebformUiElementPropertiesTest extends WebformTestBase {
    *
    * @var array
    */
-  protected static $testWebforms = ['example_layout_basic', 'test_element', 'test_element_access', 'test_element_extras', 'test_form_states_triggers'];
+  protected static $testWebforms = ['example_layout_basic', 'example_elements', 'example_elements_composite', 'test_element', 'test_element_access', 'test_form_states_triggers'];
 
   /**
    * {@inheritdoc}
@@ -45,12 +45,11 @@ class WebformUiElementPropertiesTest extends WebformTestBase {
   public function testElementProperties() {
     $this->drupalLogin($this->adminWebformUser);
 
-    // Loops through all the elements, edits them via the UI, and check that
-    // the element's render array has not be altered.
-    // This verifies that the edit element webform is not unexpectedly altering
-    // an element's render array.
-    $webform_ids = ['example_layout_basic', 'test_element', 'test_element_access', 'test_element_extras', 'test_form_states_triggers'];
-    foreach ($webform_ids as $webform_id) {
+    // Loops through all the elements, edits them via the UI, and checks that
+    // the element's render array has not been altered.
+    // This verifies that the edit element (via UI) form is not unexpectedly
+    // altering an element's render array.
+    foreach (static::$testWebforms as $webform_id) {
       /** @var \Drupal\webform\WebformInterface $webform_elements */
       $webform_elements = Webform::load($webform_id);
       $original_elements = $webform_elements->getElementsDecodedAndFlattened();
diff --git a/src/Plugin/WebformElement/DateBase.php b/src/Plugin/WebformElement/DateBase.php
index bfd7d6d9..40d9d27c 100644
--- a/src/Plugin/WebformElement/DateBase.php
+++ b/src/Plugin/WebformElement/DateBase.php
@@ -160,7 +160,7 @@ abstract class DateBase extends WebformElementBase {
     $properties = $this->getConfigurationFormProperties($form, $form_state);
 
     // Validate #default_value GNU Date Input Format.
-    if ($properties['#default_value'] && strtotime($properties['#default_value']) === FALSE) {
+    if (isset($properties['#default_value']) && strtotime($properties['#default_value']) === FALSE) {
       $this->setInputFormatError($form['properties']['element']['default_value'], $form_state);
     }
 
diff --git a/src/Plugin/WebformElement/OptionsBase.php b/src/Plugin/WebformElement/OptionsBase.php
index 62d769e6..be4fa20f 100644
--- a/src/Plugin/WebformElement/OptionsBase.php
+++ b/src/Plugin/WebformElement/OptionsBase.php
@@ -320,8 +320,8 @@ abstract class OptionsBase extends WebformElementBase {
   public function form(array $form, FormStateInterface $form_state) {
     $form = parent::form($form, $form_state);
 
-    $form['general']['default_value']['#description'] = $this->t('The default value of the field identified by its key.');
-    $form['general']['default_value']['#description'] .= ' ' . $this->t('For multiple options, use commas to separate multiple defaults.');
+    $form['element']['default_value']['#description'] = $this->t('The default value of the field identified by its key.');
+    $form['element']['default_value']['#description'] .= ' ' . $this->t('For multiple options, use commas to separate multiple defaults.');
 
     // Issue #2836374: Wrapper attributes are not supported by composite
     // elements, this includes radios, checkboxes, and buttons.
diff --git a/src/Plugin/WebformElement/Textarea.php b/src/Plugin/WebformElement/Textarea.php
index b2b640ed..1a9e26ef 100644
--- a/src/Plugin/WebformElement/Textarea.php
+++ b/src/Plugin/WebformElement/Textarea.php
@@ -68,7 +68,7 @@ class Textarea extends TextBase {
    */
   public function form(array $form, FormStateInterface $form_state) {
     $form = parent::form($form, $form_state);
-    $form['general']['default_value']['#type'] = 'textarea';
+    $form['element']['default_value']['#type'] = 'textarea';
     return $form;
   }
 
diff --git a/src/Plugin/WebformElement/WebformCompositeBase.php b/src/Plugin/WebformElement/WebformCompositeBase.php
index ead59787..22ca93d7 100644
--- a/src/Plugin/WebformElement/WebformCompositeBase.php
+++ b/src/Plugin/WebformElement/WebformCompositeBase.php
@@ -222,7 +222,7 @@ abstract class WebformCompositeBase extends WebformElementBase {
     $form = parent::form($form, $form_state);
 
     // Update #default_value description.
-    $form['general']['default_value']['#description'] = $this->t("The default value of the composite webform element as YAML.");
+    $form['element']['default_value']['#description'] = $this->t("The default value of the composite webform element as YAML.");
 
     // Update #required label.
     $form['validation']['required']['#description'] .= '<br/>' . $this->t("Checking this option only displays the required indicator next to this element's label. Please chose which elements should be required below.");
diff --git a/src/Plugin/WebformElement/WebformElement.php b/src/Plugin/WebformElement/WebformElement.php
index 89d38e8b..492eb176 100644
--- a/src/Plugin/WebformElement/WebformElement.php
+++ b/src/Plugin/WebformElement/WebformElement.php
@@ -28,7 +28,7 @@ class WebformElement extends WebformElementBase {
    * {@inheritdoc}
    */
   public function form(array $form, FormStateInterface $form_state) {
-    $form['general'] = [
+    $form['element'] = [
       '#type' => 'details',
       '#title' => $this->t('General settings'),
       '#open' => TRUE,
diff --git a/src/Plugin/WebformElement/WebformTime.php b/src/Plugin/WebformElement/WebformTime.php
index 48143a18..c6bfcef7 100644
--- a/src/Plugin/WebformElement/WebformTime.php
+++ b/src/Plugin/WebformElement/WebformTime.php
@@ -55,7 +55,7 @@ class WebformTime extends WebformElementBase {
     $form = parent::form($form, $form_state);
 
     // Append supported time input format to #default_value description.
-    $form['general']['default_value']['#description'] .= '<br />' . $this->t('Accepts any time in any <a href="https://www.gnu.org/software/tar/manual/html_chapter/tar_7.html#Date-input-formats">GNU Date Input Format</a>. Strings such as now, +2 hours, and 4:30 PM are all valid.');
+    $form['element']['default_value']['#description'] .= '<br />' . $this->t('Accepts any time in any <a href="https://www.gnu.org/software/tar/manual/html_chapter/tar_7.html#Date-input-formats">GNU Date Input Format</a>. Strings such as now, +2 hours, and 4:30 PM are all valid.');
 
     // Time.
     $form['time'] = [
diff --git a/src/Tests/Element/WebformElementCodeMirrorTest.php b/src/Tests/Element/WebformElementCodeMirrorTest.php
index b5cbc741..bc107d9c 100644
--- a/src/Tests/Element/WebformElementCodeMirrorTest.php
+++ b/src/Tests/Element/WebformElementCodeMirrorTest.php
@@ -5,7 +5,7 @@ namespace Drupal\webform\Tests\Element;
 use Drupal\webform\Tests\WebformTestBase;
 
 /**
- * Tests for webform (render) CodeMirror element .
+ * Tests for webform CodeMirror element.
  *
  * @group Webform
  */
@@ -22,29 +22,13 @@ class WebformElementCodeMirrorTest extends WebformTestBase  {
    * Tests CodeMirror element.
    */
   public function testWebformElementCodeMirror() {
-    $this->drupalGet('webform/test_element_codemirror');
-
-    /**************************************************************************/
-    // code:yaml
-    /**************************************************************************/
-
-    // Check YAML.
-    $this->assertRaw('<label for="edit-yaml-basic">YAML basic</label>');
-    $this->assertRaw('<textarea data-drupal-selector="edit-yaml-basic" class="js-webform-codemirror webform-codemirror yaml form-textarea resize-vertical" data-webform-codemirror-mode="text/x-yaml" id="edit-yaml-basic" name="yaml_basic" rows="5" cols="60"></textarea>');
-
-    /**************************************************************************/
-    // code:html
-    /**************************************************************************/
-
-    // Check HTML.
-    $this->assertRaw('<label for="edit-html-basic">HTML basic</label>');
-    $this->assertRaw('<textarea data-drupal-selector="edit-html-basic" class="js-webform-codemirror webform-codemirror html form-textarea resize-vertical" data-webform-codemirror-mode="text/html" id="edit-html-basic" name="html_basic" rows="5" cols="60"></textarea>');
 
     /**************************************************************************/
     // code:text
     /**************************************************************************/
 
     // Check Text.
+    $this->drupalGet('webform/test_element_codemirror');
     $this->assertRaw('<label for="edit-text-basic">Text basic</label>');
     $this->assertRaw('<textarea data-drupal-selector="edit-text-basic" class="js-webform-codemirror webform-codemirror text form-textarea resize-vertical" data-webform-codemirror-mode="text/plain" id="edit-text-basic" name="text_basic" rows="5" cols="60"></textarea>');
 
@@ -52,6 +36,11 @@ class WebformElementCodeMirrorTest extends WebformTestBase  {
     // code:yaml
     /**************************************************************************/
 
+    // Check YAML.
+    $this->drupalGet('webform/test_element_codemirror');
+    $this->assertRaw('<label for="edit-yaml-basic">YAML basic</label>');
+    $this->assertRaw('<textarea data-drupal-selector="edit-yaml-basic" class="js-webform-codemirror webform-codemirror yaml form-textarea resize-vertical" data-webform-codemirror-mode="text/x-yaml" id="edit-yaml-basic" name="yaml_basic" rows="5" cols="60"></textarea>');
+
     // Check associative array as the #default_value.
     $this->drupalPostForm('webform/test_element_codemirror', [], t('Submit'));
     $this->assertRaw('yaml_array:
@@ -77,6 +66,11 @@ class WebformElementCodeMirrorTest extends WebformTestBase  {
     // code:html
     /**************************************************************************/
 
+    // Check HTML.
+    $this->drupalGet('webform/test_element_codemirror');
+    $this->assertRaw('<label for="edit-html-basic">HTML basic</label>');
+    $this->assertRaw('<textarea data-drupal-selector="edit-html-basic" class="js-webform-codemirror webform-codemirror html form-textarea resize-vertical" data-webform-codemirror-mode="text/html" id="edit-html-basic" name="html_basic" rows="5" cols="60"></textarea>');
+
     // Check invalid HTML.
     $edit = [
       'html_basic' => "<b>bold</bold>",
diff --git a/src/Tests/Element/WebformElementCompositeTest.php b/src/Tests/Element/WebformElementCompositeTest.php
new file mode 100644
index 00000000..a044ea88
--- /dev/null
+++ b/src/Tests/Element/WebformElementCompositeTest.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace Drupal\webform\Tests\Element;
+
+use Drupal\webform\Tests\WebformTestBase;
+
+/**
+ * Tests for composite element.
+ *
+ * @group Webform
+ */
+class WebformElementCompositeTest extends WebformTestBase  {
+
+  /**
+   * Webforms to load.
+   *
+   * @var array
+   */
+  protected static $testWebforms = ['test_element_composite'];
+
+  /**
+   * Test composite element.
+   */
+  public function testCompositeElement() {
+
+    /* Display */
+
+    $this->drupalGet('webform/test_element_composite');
+
+    // Check webform contact basic.
+    $this->assertRaw('<fieldset data-drupal-selector="edit-contact-basic" id="edit-contact-basic--wrapper" class="fieldgroup form-composite js-webform-contact webform-contact required js-form-item form-item js-form-wrapper form-wrapper" required="required" aria-required="true">');
+    $this->assertNoRaw('<span class="fieldset-legend js-form-required form-required">Contact basic</span>');
+    $this->assertRaw('<label for="edit-contact-basic-name" class="js-form-required form-required">Name</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-contact-basic-name" type="text" id="edit-contact-basic-name" name="contact_basic[name]" value="John Smith" size="60" maxlength="128" class="form-text required" required="required" aria-required="true" />');
+
+    // Check custom name title, description, and required.
+    $this->assertRaw('<label for="edit-contact-advanced-name" class="js-form-required form-required">Custom contact name</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-contact-advanced-name" aria-describedby="edit-contact-advanced-name--description" type="text" id="edit-contact-advanced-name" name="contact_advanced[name]" value="John Smith" size="60" maxlength="128" class="form-text required" required="required" aria-required="true" />');
+    $this->assertRaw('Custom contact name description');
+
+    // Check custom state type and not required.
+    $this->assertRaw('<label for="edit-contact-advanced-state-province">State/Province</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-contact-advanced-state-province" type="text" id="edit-contact-advanced-state-province" name="contact_advanced[state_province]" value="New Jersey" size="60" maxlength="128" class="form-text" />');
+
+    // Check custom country access.
+    $this->assertNoRaw('edit-contact-advanced-country');
+
+    // Check credit card.
+    $this->assertRaw('<fieldset data-drupal-selector="edit-creditcard-basic" id="edit-creditcard-basic--wrapper" class="fieldgroup form-composite js-webform-creditcard webform-creditcard js-form-item form-item js-form-wrapper form-wrapper">');
+    $this->assertRaw('<span class="visually-hidden fieldset-legend">Credit Card</span>');
+    $this->assertNoRaw('<span class="fieldset-legend">Credit Card</span>');
+    $this->assertRaw('The credit card element is experimental and insecure because it stores submitted information as plain text.');
+    $this->assertRaw('<label for="edit-creditcard-basic-name">Name on Card</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-creditcard-basic-name" type="text" id="edit-creditcard-basic-name" name="creditcard_basic[name]" value="John Smith" size="60" maxlength="128" class="form-text" />');
+
+    /* Processing */
+
+    // Check contact composite value.
+    $this->drupalPostForm('webform/test_element_composite', [], t('Submit'));
+    $this->assertRaw("contact_basic:
+  name: 'John Smith'
+  company: Acme
+  email: example@example.com
+  phone: 123-456-7890
+  address: '100 Main Street'
+  address_2: 'PO BOX 999'
+  city: 'Hill Valley'
+  state_province: 'New Jersey'
+  postal_code: 11111-1111
+  country: 'United States'");
+
+    // Check contact validate required composite elements.
+    $edit = [
+      'contact_basic[name]' => '',
+    ];
+    $this->drupalPostForm('webform/test_element_composite', $edit, t('Submit'));
+    $this->assertRaw('Name field is required.');
+
+    // Check creditcard composite value.
+    $this->drupalPostForm('webform/test_element_composite', [], t('Submit'));
+    $this->assertRaw("creditcard_basic:
+  name: 'John Smith'
+  type: VI
+  number: '4111111111111111'
+  civ: '111'
+  expiration_month: '1'
+  expiration_year: '2025'");
+  }
+
+}
diff --git a/src/Tests/Element/WebformElementEmailTest.php b/src/Tests/Element/WebformElementEmailTest.php
new file mode 100644
index 00000000..08e0abd6
--- /dev/null
+++ b/src/Tests/Element/WebformElementEmailTest.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace Drupal\webform\Tests\Element;
+
+use Drupal\webform\Tests\WebformTestBase;
+
+/**
+ * Tests for email_confirm and email_multiple element.
+ *
+ * @group Webform
+ */
+class WebformElementEmailTest extends WebformTestBase  {
+
+  /**
+   * Webforms to load.
+   *
+   * @var array
+   */
+  protected static $testWebforms = ['test_element_email'];
+
+  /**
+   * Test email_confirm and email_multiple element.
+   */
+  public function testEmailElement() {
+
+    /**************************************************************************/
+    // email_multiple
+    /**************************************************************************/
+
+    // Check basic email multiple.
+    $this->drupalGet('webform/test_element_email');
+    $this->assertRaw('<label for="edit-email-multiple-basic">Multiple email addresses (basic)</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-email-multiple-basic" aria-describedby="edit-email-multiple-basic--description" type="text" id="edit-email-multiple-basic" name="email_multiple_basic" value="" size="60" class="form-textfield form-email-multiple" />');
+    $this->assertRaw('Multiple email addresses may be separated by commas.');
+
+    // Check email multiple invalid second email address.
+    $edit = [
+      'email_multiple_basic' => 'example@example.com, Not a valid email address',
+    ];
+    $this->drupalPostForm('webform/test_element_email', $edit, t('Submit'));
+    $this->assertRaw('The email address <em class="placeholder">Not a valid email address</em> is not valid.');
+
+    // Check email multiple invalid token email address.
+    $edit = [
+      'email_multiple_basic' => 'example@example.com, [token]',
+    ];
+    $this->drupalPostForm('webform/test_element_email', $edit, t('Submit'));
+    $this->assertRaw('The email address <em class="placeholder">[token]</em> is not valid.');
+
+    // Check email multiple valid second email address.
+    $edit = [
+      'email_multiple_basic' => 'example@example.com, other@other.com',
+    ];
+    $this->drupalPostForm('webform/test_element_email', $edit, t('Submit'));
+    $this->assertRaw("email_multiple_basic: 'example@example.com, other@other.com'");
+
+    // Check email multiple valid token email address (via #allow_tokens).
+    $edit = [
+      'email_multiple_advanced' => 'example@example.com, [token]',
+    ];
+    $this->drupalPostForm('webform/test_element_email', $edit, t('Submit'));
+    $this->assertRaw("email_multiple_advanced: 'example@example.com, [token]'");
+
+    /**************************************************************************/
+    // email_confirm
+    /**************************************************************************/
+
+    $this->drupalGet('webform/test_element_email');
+
+    // Check basic email confirm.
+    $this->assertRaw('<div data-drupal-selector="edit-email-confirm-basic" id="edit-email-confirm-basic" class="js-form-wrapper form-wrapper">');
+    $this->assertRaw('<div class="js-form-item form-item js-form-type-email form-type-email js-form-item-email-confirm-basic-mail-1 form-item-email-confirm-basic-mail-1">');
+    $this->assertRaw('<label for="edit-email-confirm-basic-mail-1">Email confirm basic</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-email-confirm-basic-mail-1" class="webform-email form-email" type="email" id="edit-email-confirm-basic-mail-1" name="email_confirm_basic[mail_1]" value="" size="60" maxlength="254" />');
+    $this->assertRaw('<div class="js-form-item form-item js-form-type-email form-type-email js-form-item-email-confirm-basic-mail-2 form-item-email-confirm-basic-mail-2">');
+    $this->assertRaw('<label for="edit-email-confirm-basic-mail-2">Confirm email</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-email-confirm-basic-mail-2" class="webform-email-confirm form-email" type="email" id="edit-email-confirm-basic-mail-2" name="email_confirm_basic[mail_2]" value="" size="60" maxlength="254" />');
+
+    // Check advanced email confirm w/ custom label.
+    $this->assertRaw('<div data-drupal-selector="edit-email-confirm-advanced" aria-describedby="edit-email-confirm-advanced--description" id="edit-email-confirm-advanced" class="js-form-wrapper form-wrapper">');
+    $this->assertRaw('<div class="js-form-item form-item js-form-type-email form-type-email js-form-item-email-confirm-advanced-mail-1 form-item-email-confirm-advanced-mail-1">');
+    $this->assertRaw('<label for="edit-email-confirm-advanced-mail-1">Email confirm advanced</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-email-confirm-advanced-mail-1" aria-describedby="edit-email-confirm-advanced-mail-1--description" class="webform-email form-email" type="email" id="edit-email-confirm-advanced-mail-1" name="email_confirm_advanced[mail_1]" value="" size="60" maxlength="254" placeholder="Enter email address" />');
+    $this->assertRaw('<div id="edit-email-confirm-advanced-mail-1--description" class="description">');
+    $this->assertRaw('Please make sure to review your email address');
+    $this->assertRaw('<div class="js-form-item form-item js-form-type-email form-type-email js-form-item-email-confirm-advanced-mail-2 form-item-email-confirm-advanced-mail-2">');
+    $this->assertRaw('<label for="edit-email-confirm-advanced-mail-2">Please confirm your email address</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-email-confirm-advanced-mail-2" aria-describedby="edit-email-confirm-advanced-mail-2--description" class="webform-email-confirm form-email" type="email" id="edit-email-confirm-advanced-mail-2" name="email_confirm_advanced[mail_2]" value="" size="60" maxlength="254" placeholder="Enter confirmation email address" />');
+    $this->assertRaw('<div id="edit-email-confirm-advanced-mail-2--description" class="description">');
+    $this->assertRaw('Please make sure to review your confirmation email address');
+
+    // Check email confirm invalid email addresses.
+    $edit = [
+      'email_confirm_advanced[mail_1]' => 'Not a valid email address',
+      'email_confirm_advanced[mail_2]' => 'Not a valid email address, again',
+    ];
+    $this->drupalPostForm('webform/test_element_email', $edit, t('Submit'));
+    $this->assertRaw('The email address <em class="placeholder">Not a valid email address</em> is not valid.');
+    $this->assertRaw('The email address <em class="placeholder">Not a valid email address, again</em> is not valid.');
+
+    // Check email confirm non-matching email addresses.
+    $edit = [
+      'email_confirm_advanced[mail_1]' => 'example01@example.com',
+      'email_confirm_advanced[mail_2]' => 'example02@example.com',
+    ];
+    $this->drupalPostForm('webform/test_element_email', $edit, t('Submit'));
+    $this->assertRaw('The specified email addresses do not match.');
+
+    // Check email confirm matching email addresses.
+    $edit = [
+      'email_confirm_advanced[mail_1]' => 'example@example.com',
+      'email_confirm_advanced[mail_2]' => 'example@example.com',
+    ];
+    $this->drupalPostForm('webform/test_element_email', $edit, t('Submit'));
+    $this->assertNoRaw('<li class="messages__item">The specified email addresses do not match.</li>');
+    $this->assertRaw('email_confirm_advanced: example@example.com');
+
+    // Check email confirm empty confirm email address.
+    $edit = [
+      'email_confirm_advanced[mail_1]' => '',
+      'email_confirm_advanced[mail_2]' => '',
+    ];
+    $this->drupalPostForm('webform/test_element_email', $edit, t('Submit'));
+    $this->assertNoRaw('<li class="messages__item">Confirm Email field is required.</li>');
+  }
+
+}
diff --git a/src/Tests/Element/WebformElementExtrasTest.php b/src/Tests/Element/WebformElementExtrasTest.php
deleted file mode 100644
index 6833b686..00000000
--- a/src/Tests/Element/WebformElementExtrasTest.php
+++ /dev/null
@@ -1,394 +0,0 @@
-<?php
-
-namespace Drupal\webform\Tests\Element;
-
-use Drupal\webform\Tests\WebformTestBase;
-
-/**
- * Tests for webform (render) element extras.
- *
- * @group Webform
- */
-class WebformElementExtrasTest extends WebformTestBase  {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  protected static $modules = ['filter', 'node', 'webform'];
-
-  /**
-   * Webforms to load.
-   *
-   * @var array
-   */
-  protected static $testWebforms = ['test_element_extras', 'test_element_markup'];
-
-  /**
-   * Tests building of custom elements.
-   */
-  public function testBuildElements() {
-    $this->drupalGet('webform/test_element_extras');
-
-    /**************************************************************************/
-    // text_format
-    /**************************************************************************/
-
-    // Check that formats and tips are removed and/or hidden.
-    $this->assertRaw('<div class="filter-wrapper js-form-wrapper form-wrapper" data-drupal-selector="edit-text-format-format" style="display: none" id="edit-text-format-format">');
-    $this->assertRaw('<div class="filter-help js-form-wrapper form-wrapper" data-drupal-selector="edit-text-format-format-help" style="display: none" id="edit-text-format-format-help">');
-
-    /**************************************************************************/
-    // counter
-    /**************************************************************************/
-
-    $this->assertRaw('<input data-counter-type="character" data-counter-limit="10" class="js-webform-counter webform-counter form-text" data-drupal-selector="edit-counter-characters" type="text" id="edit-counter-characters" name="counter_characters" value="" size="60" maxlength="255" />');
-    $this->assertRaw('<textarea data-counter-type="word" data-counter-limit="3" data-counter-message="word(s) left. This is a custom message" class="js-webform-counter webform-counter form-textarea resize-vertical" data-drupal-selector="edit-counter-words" id="edit-counter-words" name="counter_words" rows="5" cols="60"></textarea>');
-
-    /**************************************************************************/
-    // creditcard_number
-    /**************************************************************************/
-
-    // Check basic creditcard_number.
-    $this->assertRaw('<label for="edit-creditcard-number-basic">Credit card number basic</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-creditcard-number-basic" type="text" id="edit-creditcard-number-basic" name="creditcard_number_basic" value="" size="16" maxlength="16" class="form-textfield form-creditcard-number" />');
-
-    /**************************************************************************/
-    // email_multiple
-    /**************************************************************************/
-
-    // Check basic email_multiple.
-    $this->assertRaw('<label for="edit-email-multiple-basic">Multiple email addresses (basic)</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-email-multiple-basic" aria-describedby="edit-email-multiple-basic--description" type="text" id="edit-email-multiple-basic" name="email_multiple_basic" value="" size="60" class="form-textfield form-email-multiple" />');
-    $this->assertRaw('Multiple email addresses may be separated by commas.');
-
-    /**************************************************************************/
-    // email_confirm
-    /**************************************************************************/
-
-    // Check basic email_confirm.
-    $this->assertRaw('<div data-drupal-selector="edit-email-confirm-basic" id="edit-email-confirm-basic" class="js-form-wrapper form-wrapper">');
-    $this->assertRaw('<div class="js-form-item form-item js-form-type-email form-type-email js-form-item-email-confirm-basic-mail-1 form-item-email-confirm-basic-mail-1">');
-    $this->assertRaw('<label for="edit-email-confirm-basic-mail-1">Email confirm basic</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-email-confirm-basic-mail-1" class="webform-email form-email" type="email" id="edit-email-confirm-basic-mail-1" name="email_confirm_basic[mail_1]" value="" size="60" maxlength="254" />');
-    $this->assertRaw('<div class="js-form-item form-item js-form-type-email form-type-email js-form-item-email-confirm-basic-mail-2 form-item-email-confirm-basic-mail-2">');
-    $this->assertRaw('<label for="edit-email-confirm-basic-mail-2">Confirm email</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-email-confirm-basic-mail-2" class="webform-email-confirm form-email" type="email" id="edit-email-confirm-basic-mail-2" name="email_confirm_basic[mail_2]" value="" size="60" maxlength="254" />');
-
-    // Check advanced email_confirm w/ custom label.
-    $this->assertRaw('<div data-drupal-selector="edit-email-confirm-advanced" aria-describedby="edit-email-confirm-advanced--description" id="edit-email-confirm-advanced" class="js-form-wrapper form-wrapper">');
-    $this->assertRaw('<div class="js-form-item form-item js-form-type-email form-type-email js-form-item-email-confirm-advanced-mail-1 form-item-email-confirm-advanced-mail-1">');
-    $this->assertRaw('<label for="edit-email-confirm-advanced-mail-1">Email confirm advanced</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-email-confirm-advanced-mail-1" aria-describedby="edit-email-confirm-advanced-mail-1--description" class="webform-email form-email" type="email" id="edit-email-confirm-advanced-mail-1" name="email_confirm_advanced[mail_1]" value="" size="60" maxlength="254" placeholder="Enter email address" />');
-    $this->assertRaw('<div id="edit-email-confirm-advanced-mail-1--description" class="description">');
-    $this->assertRaw('Please make sure to review your email address');
-    $this->assertRaw('<div class="js-form-item form-item js-form-type-email form-type-email js-form-item-email-confirm-advanced-mail-2 form-item-email-confirm-advanced-mail-2">');
-    $this->assertRaw('<label for="edit-email-confirm-advanced-mail-2">Please confirm your email address</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-email-confirm-advanced-mail-2" aria-describedby="edit-email-confirm-advanced-mail-2--description" class="webform-email-confirm form-email" type="email" id="edit-email-confirm-advanced-mail-2" name="email_confirm_advanced[mail_2]" value="" size="60" maxlength="254" placeholder="Enter confirmation email address" />');
-    $this->assertRaw('<div id="edit-email-confirm-advanced-mail-2--description" class="description">');
-    $this->assertRaw('Please make sure to review your confirmation email address');
-
-    /**************************************************************************/
-    // signature
-    /**************************************************************************/
-
-    $this->assertRaw('<input data-drupal-selector="edit-signature-basic" aria-describedby="edit-signature-basic--description" type="hidden" name="signature_basic" value="" class="js-webform-signature form-webform-signature" /><div class="js-webform-signature-pad webform-signature-pad">');
-    $this->assertRaw('<input type="submit" name="op" value="Reset" class="button js-form-submit form-submit" />');
-    $this->assertRaw('<canvas></canvas>');
-    $this->assertRaw('</div>');
-    $this->assertRaw('<div id="edit-signature-basic--description" class="description">');
-    $this->assertRaw('Sign above');
-
-    /**************************************************************************/
-    // toggle
-    /**************************************************************************/
-
-    // Check basic toggle.
-    $this->assertRaw('<div class="js-form-item form-item js-form-type-webform-toggle form-type-webform-toggle js-form-item-toggle-basic form-item-toggle-basic">');
-    $this->assertRaw('<input data-drupal-selector="edit-toggle-basic" type="checkbox" id="edit-toggle-basic" name="toggle_basic" value="1" class="form-checkbox" />');
-    $this->assertRaw('<div class="js-webform-toggle webform-toggle toggle toggle-medium toggle-light" data-toggle-height="24" data-toggle-width="48" data-toggle-text-on="" data-toggle-text-off=""></div>');
-    $this->assertRaw('<label for="edit-toggle-basic" class="option">Basic toggle</label>');
-
-    // Check advanced toggle.
-    $this->assertRaw('<div class="js-form-item form-item js-form-type-webform-toggle form-type-webform-toggle js-form-item-toggle-advanced form-item-toggle-advanced">');
-    $this->assertRaw('<label for="edit-toggle-advanced">Advanced toggle</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-toggle-advanced" type="checkbox" id="edit-toggle-advanced" name="toggle_advanced" value="1" class="form-checkbox" />');
-    $this->assertRaw('<div class="js-webform-toggle webform-toggle toggle toggle-large toggle-iphone" data-toggle-height="36" data-toggle-width="108" data-toggle-text-on="Yes" data-toggle-text-off="No"></div>');
-
-    // Check basic toggles.
-    $this->assertRaw('<fieldset data-drupal-selector="edit-toggles-basic" id="edit-toggles-basic--wrapper" class="fieldgroup form-composite js-form-item form-item js-form-wrapper form-wrapper">');
-    $this->assertRaw('<span class="fieldset-legend">Basic toggles</span>');
-    $this->assertRaw('<div id="edit-toggles-basic" class="webform-options-display-one-column form-checkboxes"><div class="js-form-item form-item js-form-type-webform-toggle form-type-webform-toggle js-form-item-toggles-basic-one form-item-toggles-basic-one">');
-    $this->assertRaw('<input data-drupal-selector="edit-toggles-basic-one" type="checkbox" id="edit-toggles-basic-one" name="toggles_basic[one]" value="one" class="form-checkbox" /><div class="js-webform-toggle webform-toggle toggle toggle-medium toggle-light" data-toggle-height="24" data-toggle-width="48" data-toggle-text-on="" data-toggle-text-off=""></div>');
-    $this->assertRaw('<label for="edit-toggles-basic-one" class="option">One</label>');
-
-    // Check advanced toggles.
-    $this->assertRaw('<fieldset data-drupal-selector="edit-toggles-advanced" id="edit-toggles-advanced--wrapper" class="fieldgroup form-composite js-form-item form-item js-form-wrapper form-wrapper">');
-    $this->assertRaw('<span class="fieldset-legend">Advanced toggles</span>');
-    $this->assertRaw('<div id="edit-toggles-advanced" class="webform-options-display-one-column form-checkboxes"><div class="js-form-item form-item js-form-type-webform-toggle form-type-webform-toggle js-form-item-toggles-advanced-one form-item-toggles-advanced-one">');
-    $this->assertRaw('<input data-drupal-selector="edit-toggles-advanced-one" type="checkbox" id="edit-toggles-advanced-one" name="toggles_advanced[one]" value="one" class="form-checkbox" /><div class="js-webform-toggle webform-toggle toggle toggle-large toggle-iphone" data-toggle-height="36" data-toggle-width="108" data-toggle-text-on="Yes" data-toggle-text-off="No"></div>');
-
-    /**************************************************************************/
-    // rating
-    /**************************************************************************/
-
-    // Check basic.
-    $this->assertRaw('<label for="edit-rating-basic">Rating basic</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-rating-basic" type="range" id="edit-rating-basic" name="rating_basic" value="0" step="1" min="0" max="5" class="form-webform-rating" />');
-    $this->assertRaw('<div class="rateit svg rateit-medium" data-rateit-min="0" data-rateit-max="5" data-rateit-step="1" data-rateit-resetable="false" data-rateit-readonly="false" data-rateit-backingfld="#edit-rating-basic" data-rateit-value="" data-rateit-starheight="24" data-rateit-starwidth="24">');
-
-    // Check advanced.
-    $this->assertRaw('<label for="edit-rating-advanced">Rating advanced</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-rating-advanced" type="range" id="edit-rating-advanced" name="rating_advanced" value="0" step="0.1" min="0" max="10" class="form-webform-rating" />');
-    $this->assertRaw('<div class="rateit svg rateit-large" data-rateit-min="0" data-rateit-max="10" data-rateit-step="0.1" data-rateit-resetable="true" data-rateit-readonly="false" data-rateit-backingfld="#edit-rating-advanced" data-rateit-value="" data-rateit-starheight="32" data-rateit-starwidth="32">');
-
-    /**************************************************************************/
-    // contact (composite element)
-    /**************************************************************************/
-
-    // Check webform contact basic.
-    $this->assertRaw('<fieldset data-drupal-selector="edit-contact-basic" id="edit-contact-basic--wrapper" class="fieldgroup form-composite js-webform-contact webform-contact required js-form-item form-item js-form-wrapper form-wrapper" required="required" aria-required="true">');
-    $this->assertNoRaw('<span class="fieldset-legend js-form-required form-required">Contact basic</span>');
-    $this->assertRaw('<label for="edit-contact-basic-name" class="js-form-required form-required">Name</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-contact-basic-name" type="text" id="edit-contact-basic-name" name="contact_basic[name]" value="John Smith" size="60" maxlength="128" class="form-text required" required="required" aria-required="true" />');
-
-    // Check custom name title, description, and required.
-    $this->assertRaw('<label for="edit-contact-advanced-name" class="js-form-required form-required">Custom contact name</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-contact-advanced-name" aria-describedby="edit-contact-advanced-name--description" type="text" id="edit-contact-advanced-name" name="contact_advanced[name]" value="John Smith" size="60" maxlength="128" class="form-text required" required="required" aria-required="true" />');
-    $this->assertRaw('Custom contact name description');
-
-    // Check custom state type and not required.
-    $this->assertRaw('<label for="edit-contact-advanced-state-province">State/Province</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-contact-advanced-state-province" type="text" id="edit-contact-advanced-state-province" name="contact_advanced[state_province]" value="New Jersey" size="60" maxlength="128" class="form-text" />');
-
-    // Check custom country access.
-    $this->assertNoRaw('edit-contact-advanced-country');
-
-    /**************************************************************************/
-    // creditcard (composite element)
-    /**************************************************************************/
-
-    $this->assertRaw('<fieldset data-drupal-selector="edit-creditcard" id="edit-creditcard--wrapper" class="fieldgroup form-composite js-webform-creditcard webform-creditcard js-form-item form-item js-form-wrapper form-wrapper">');
-    $this->assertNoRaw('<span class="fieldset-legend">Credit Card</span>');
-    $this->assertRaw('The credit card element is experimental and insecure because it stores submitted information as plain text.');
-    $this->assertRaw('<label for="edit-creditcard-name">Name on Card</label>');
-    $this->assertRaw('<input data-drupal-selector="edit-creditcard-name" type="text" id="edit-creditcard-name" name="creditcard[name]" value="John Smith" size="60" maxlength="128" class="form-text" />');
-    $this->assertRaw('<select data-drupal-selector="edit-creditcard-expiration-month" id="edit-creditcard-expiration-month" name="creditcard[expiration_month]" class="form-select">');
-
-    /**************************************************************************/
-    // table
-    /**************************************************************************/
-
-    $this->assertRaw('<table class="js-form-wrapper responsive-enabled" data-drupal-selector="edit-table" id="edit-table" data-striping="1">');
-    $this->assertRaw('<th>First Name</th>');
-    $this->assertRaw('<th>Last Name</th>');
-    $this->assertRaw('<th>Gender</th>');
-    $this->assertRaw('<tr data-drupal-selector="edit-table-1" class="odd">');
-    $this->assertRaw('<td><div class="js-form-item form-item js-form-type-textfield form-type-textfield js-form-item-table__1__first-name form-item-table__1__first-name form-no-label">');
-    $this->assertRaw('<input data-drupal-selector="edit-table-1-first-name" type="text" id="edit-table-1-first-name" name="table__1__first_name" value="John" size="20" maxlength="255" class="form-text" />');
-
-  }
-
-  /**
-   * Tests value processing for custom elements.
-   */
-  public function testProcessingElements() {
-
-    /**************************************************************************/
-    // counter
-    /**************************************************************************/
-
-    // Check counter validation error.
-    $edit = [
-      'counter_characters' => '01234567890',
-      'counter_words' => 'one two three four',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertRaw('counter_characters</em> must be less than 10 characters.');
-    $this->assertRaw('counter_words</em> must be less than 3 words.');
-
-    // Check counter validation passes.
-    $edit = [
-      'counter_characters' => '0123456789',
-      'counter_words' => 'one two three',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertNoRaw('counter_characters</em> must be less than 10 characters.');
-    $this->assertNoRaw('counter_words</em> must be less than 3 words.');
-
-    /**************************************************************************/
-    // table
-    /**************************************************************************/
-
-    $this->drupalPostForm('webform/test_element_extras', [], t('Submit'));
-    $this->assertRaw('table__1__first_name: John');
-    $this->assertRaw('table__1__last_name: Smith');
-    $this->assertRaw('table__1__gender: Male');
-    $this->assertRaw('table__2__first_name: Jane');
-    $this->assertRaw('table__2__last_name: Doe');
-    $this->assertRaw('table__2__gender: Female');
-
-    /**************************************************************************/
-    // creditcard_number
-    /**************************************************************************/
-
-    // Check invalid credit card number.
-    $edit = [
-      'creditcard_number_basic' => 'not value',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertRaw('The credit card number is not valid.');
-
-    // Check valid credit card number.
-    $edit = [
-      'creditcard_number_basic' => '4111111111111111',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertNoRaw('The credit card number is not valid.');
-
-    // Check valid AmEx (15 digit).
-    $edit = [
-      'creditcard_number_basic' => '378282246310005',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertNoRaw('The credit card number is not valid.');
-
-    /**************************************************************************/
-    // email_multiple
-    /**************************************************************************/
-
-    // Check invalid second email address.
-    $edit = [
-      'email_multiple_basic' => 'example@example.com, Not a valid email address',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertRaw('The email address <em class="placeholder">Not a valid email address</em> is not valid.');
-
-    // Check invalid token email address.
-    $edit = [
-      'email_multiple_basic' => 'example@example.com, [token]',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertRaw('The email address <em class="placeholder">[token]</em> is not valid.');
-
-    // Check valid second email address.
-    $edit = [
-      'email_multiple_basic' => 'example@example.com, other@other.com',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertRaw("email_multiple_basic: 'example@example.com, other@other.com'");
-
-    // Check valid token email address (via #allow_tokens).
-    $edit = [
-      'email_multiple_advanced' => 'example@example.com, [token]',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertRaw("email_multiple_advanced: 'example@example.com, [token]'");
-
-    /**************************************************************************/
-    // email_confirm
-    /**************************************************************************/
-
-    // Check invalid email addresses.
-    $edit = [
-      'email_confirm_advanced[mail_1]' => 'Not a valid email address',
-      'email_confirm_advanced[mail_2]' => 'Not a valid email address, again',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertRaw('The email address <em class="placeholder">Not a valid email address</em> is not valid.');
-    $this->assertRaw('The email address <em class="placeholder">Not a valid email address, again</em> is not valid.');
-
-    // Check non-matching email addresses.
-    $edit = [
-      'email_confirm_advanced[mail_1]' => 'example01@example.com',
-      'email_confirm_advanced[mail_2]' => 'example02@example.com',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertRaw('The specified email addresses do not match.');
-
-    // Check matching email addresses.
-    $edit = [
-      'email_confirm_advanced[mail_1]' => 'example@example.com',
-      'email_confirm_advanced[mail_2]' => 'example@example.com',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertNoRaw('<li class="messages__item">The specified email addresses do not match.</li>');
-    $this->assertRaw('email_confirm_advanced: example@example.com');
-
-    // Check empty confirm email address.
-    $edit = [
-      'email_confirm_advanced[mail_1]' => '',
-      'email_confirm_advanced[mail_2]' => '',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertNoRaw('<li class="messages__item">Confirm Email field is required.</li>');
-
-    /**************************************************************************/
-    // rating
-    /**************************************************************************/
-
-    $edit = [
-      'rating_basic' => '4',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertRaw("rating_basic: '4'");
-
-    /**************************************************************************/
-    // markup
-    /**************************************************************************/
-
-    $this->drupalGet('webform/test_element_markup');
-    $this->assertRaw('<p>This is normal markup</p>');
-    $this->assertRaw('<p>This is only displayed on the form view.</p>');
-    $this->assertNoRaw('<p>This is only displayed on the submission view.</p>');
-    $this->assertRaw('<p>This is displayed on the both the form and submission view.</p>');
-
-    $this->drupalPostForm('webform/test_element_markup', [], t('Preview'));
-    $this->assertNoRaw('<p>This is normal markup</p>');
-    $this->assertNoRaw('<p>This is only displayed on the form view.</p>');
-    $this->assertRaw('<p>This is only displayed on the submission view.</p>');
-    $this->assertRaw('<p>This is displayed on the both the form and submission view.</p>');
-
-    /**************************************************************************/
-    // contact (composite element)
-    /**************************************************************************/
-
-    // Check composite value.
-    $this->drupalPostForm('webform/test_element_extras', [], t('Submit'));
-    $this->assertRaw("contact_basic:
-  name: 'John Smith'
-  company: Acme
-  email: example@example.com
-  phone: 123-456-7890
-  address: '100 Main Street'
-  address_2: 'PO BOX 999'
-  city: 'Hill Valley'
-  state_province: 'New Jersey'
-  postal_code: 11111-1111
-  country: 'United States'");
-
-    // Check validate required composite elements.
-    $edit = [
-      'contact_basic[name]' => '',
-    ];
-    $this->drupalPostForm('webform/test_element_extras', $edit, t('Submit'));
-    $this->assertRaw('Name field is required.');
-
-    /**************************************************************************/
-    // creditcard (composite element)
-    /**************************************************************************/
-
-    // Check composite value.
-    $this->drupalPostForm('webform/test_element_extras', [], t('Submit'));
-
-    $this->assertRaw("creditcard:
-  name: 'John Smith'
-  type: VI
-  number: '4111111111111111'
-  civ: '111'
-  expiration_month: '1'
-  expiration_year: '2025'");
-  }
-
-}
diff --git a/src/Tests/Element/WebformElementLikertTest.php b/src/Tests/Element/WebformElementLikertTest.php
index abced552..4694d67d 100644
--- a/src/Tests/Element/WebformElementLikertTest.php
+++ b/src/Tests/Element/WebformElementLikertTest.php
@@ -23,8 +23,6 @@ class WebformElementLikertTest extends WebformTestBase  {
    */
   public function testLikertElement() {
 
-    /* Display */
-
     $this->drupalGet('webform/test_element_likert');
 
     // Check default likert element.
@@ -41,8 +39,6 @@ class WebformElementLikertTest extends WebformTestBase  {
     $this->assertRaw('<input data-drupal-selector="edit-likert-advanced-q1" type="radio" id="edit-likert-advanced-q1--4" name="likert_advanced[q1]" value="N/A" class="form-radio" />');
     $this->assertRaw('<label for="edit-likert-advanced-q1--4" class="option">Not applicable</label>');
 
-    /* Processing */
-
     // Check likert required.
     $this->drupalPostForm('webform/test_element_likert', [], t('Submit'));
     $this->assertRaw('Question 1 field is required.');
diff --git a/src/Tests/Element/WebformElementMarkupTest.php b/src/Tests/Element/WebformElementMarkupTest.php
new file mode 100644
index 00000000..09a2a7e1
--- /dev/null
+++ b/src/Tests/Element/WebformElementMarkupTest.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Drupal\webform\Tests\Element;
+
+use Drupal\webform\Tests\WebformTestBase;
+
+/**
+ * Tests for markup element.
+ *
+ * @group Webform
+ */
+class WebformElementMarkupTest extends WebformTestBase  {
+
+  /**
+   * Webforms to load.
+   *
+   * @var array
+   */
+  protected static $testWebforms = ['test_element_markup'];
+
+  /**
+   * Test markup element.
+   */
+  public function testMarkupElement() {
+    $this->drupalGet('webform/test_element_markup');
+
+    $this->assertRaw('<p>This is normal markup</p>');
+    $this->assertRaw('<p>This is only displayed on the form view.</p>');
+    $this->assertNoRaw('<p>This is only displayed on the submission view.</p>');
+    $this->assertRaw('<p>This is displayed on the both the form and submission view.</p>');
+
+    $this->drupalPostForm('webform/test_element_markup', [], t('Preview'));
+    $this->assertNoRaw('<p>This is normal markup</p>');
+    $this->assertNoRaw('<p>This is only displayed on the form view.</p>');
+    $this->assertRaw('<p>This is only displayed on the submission view.</p>');
+    $this->assertRaw('<p>This is displayed on the both the form and submission view.</p>');
+  }
+
+}
diff --git a/src/Tests/Element/WebformElementOptionsTest.php b/src/Tests/Element/WebformElementOptionsTest.php
index 4d09de47..f1710320 100644
--- a/src/Tests/Element/WebformElementOptionsTest.php
+++ b/src/Tests/Element/WebformElementOptionsTest.php
@@ -23,10 +23,6 @@ class WebformElementOptionsTest extends WebformTestBase  {
    */
   public function testWebformElementOptions() {
 
-    /**************************************************************************/
-    // Processing.
-    /**************************************************************************/
-
     // Check default value handling.
     $this->drupalPostForm('webform/test_element_options', [], t('Submit'));
     $this->assertRaw("webform_options: {  }
diff --git a/src/Tests/Element/WebformElementRatingTest.php b/src/Tests/Element/WebformElementRatingTest.php
new file mode 100644
index 00000000..1315890f
--- /dev/null
+++ b/src/Tests/Element/WebformElementRatingTest.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Drupal\webform\Tests\Element;
+
+use Drupal\webform\Tests\WebformTestBase;
+
+/**
+ * Tests for rating element.
+ *
+ * @group Webform
+ */
+class WebformElementRatingTest extends WebformTestBase  {
+
+  /**
+   * Webforms to load.
+   *
+   * @var array
+   */
+  protected static $testWebforms = ['test_element_rating'];
+
+  /**
+   * Test rating element.
+   */
+  public function testRatingElement() {
+    $this->drupalGet('webform/test_element_rating');
+
+    // Check basic rating display.
+    $this->assertRaw('<label for="edit-rating-basic">Rating basic</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-rating-basic" type="range" id="edit-rating-basic" name="rating_basic" value="0" step="1" min="0" max="5" class="form-webform-rating" />');
+    $this->assertRaw('<div class="rateit svg rateit-medium" data-rateit-min="0" data-rateit-max="5" data-rateit-step="1" data-rateit-resetable="false" data-rateit-readonly="false" data-rateit-backingfld="#edit-rating-basic" data-rateit-value="" data-rateit-starheight="24" data-rateit-starwidth="24">');
+
+    // Check advanced rating display.
+    $this->assertRaw('<label for="edit-rating-advanced">Rating advanced</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-rating-advanced" type="range" id="edit-rating-advanced" name="rating_advanced" value="0" step="0.1" min="0" max="10" class="form-webform-rating" />');
+    $this->assertRaw('<div class="rateit svg rateit-large" data-rateit-min="0" data-rateit-max="10" data-rateit-step="0.1" data-rateit-resetable="true" data-rateit-readonly="false" data-rateit-backingfld="#edit-rating-advanced" data-rateit-value="" data-rateit-starheight="32" data-rateit-starwidth="32">');
+
+    // Check processing.
+    $edit = [
+      'rating_basic' => '4',
+    ];
+    $this->drupalPostForm('webform/test_element_rating', $edit, t('Submit'));
+    $this->assertRaw("rating_basic: '4'");
+  }
+
+}
diff --git a/src/Tests/Element/WebformElementSignatureTest.php b/src/Tests/Element/WebformElementSignatureTest.php
new file mode 100644
index 00000000..978e8877
--- /dev/null
+++ b/src/Tests/Element/WebformElementSignatureTest.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Drupal\webform\Tests\Element;
+
+use Drupal\webform\Tests\WebformTestBase;
+
+/**
+ * Tests for signature element.
+ *
+ * @group Webform
+ */
+class WebformElementSignatureTest extends WebformTestBase  {
+
+  /**
+   * Webforms to load.
+   *
+   * @var array
+   */
+  protected static $testWebforms = ['test_element_signature'];
+
+  /**
+   * Test signature element.
+   */
+  public function testSignatureElement() {
+    // Check signature display.
+    $this->drupalGet('webform/test_element_signature');
+    $this->assertRaw('<input data-drupal-selector="edit-signature-basic" aria-describedby="edit-signature-basic--description" type="hidden" name="signature_basic" value="" class="js-webform-signature form-webform-signature" /><div class="js-webform-signature-pad webform-signature-pad">');
+    $this->assertRaw('<input type="submit" name="op" value="Reset" class="button js-form-submit form-submit" />');
+    $this->assertRaw('<canvas></canvas>');
+    $this->assertRaw('</div>');
+    $this->assertRaw('<div id="edit-signature-basic--description" class="description">');
+    $this->assertRaw('Sign above');
+  }
+
+}
diff --git a/src/Tests/Element/WebformElementTableTest.php b/src/Tests/Element/WebformElementTableTest.php
index 464a173e..40677a61 100644
--- a/src/Tests/Element/WebformElementTableTest.php
+++ b/src/Tests/Element/WebformElementTableTest.php
@@ -37,6 +37,20 @@ class WebformElementTableTest extends WebformTestBase {
     $webform = Webform::load('test_element_table');
 
     /**************************************************************************/
+    // table
+    /**************************************************************************/
+
+    // Check display elements withing a table.
+    $this->drupalGet('webform/test_element_table');
+    $this->assertRaw('<table class="js-form-wrapper responsive-enabled" data-drupal-selector="edit-table" id="edit-table" data-striping="1">');
+    $this->assertRaw('<th>First Name</th>');
+    $this->assertRaw('<th>Last Name</th>');
+    $this->assertRaw('<th>Gender</th>');
+    $this->assertRaw('<tr data-drupal-selector="edit-table-1" class="odd">');
+    $this->assertRaw('<td><div class="js-form-item form-item js-form-type-textfield form-type-textfield js-form-item-table__1__first-name form-item-table__1__first-name form-no-label">');
+    $this->assertRaw('<input data-drupal-selector="edit-table-1-first-name" type="text" id="edit-table-1-first-name" name="table__1__first_name" value="John" size="20" maxlength="255" class="form-text" />');
+
+    /**************************************************************************/
     // Table select sort.
     /**************************************************************************/
 
diff --git a/src/Tests/Element/WebformElementTextTest.php b/src/Tests/Element/WebformElementTextTest.php
new file mode 100644
index 00000000..6e5f5d18
--- /dev/null
+++ b/src/Tests/Element/WebformElementTextTest.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace Drupal\webform\Tests\Element;
+
+use Drupal\webform\Tests\WebformTestBase;
+
+/**
+ * Tests for webform text elements.
+ *
+ * @group Webform
+ */
+class WebformElementTextTest extends WebformTestBase  {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  protected static $modules = ['filter', 'webform'];
+
+  /**
+   * Webforms to load.
+   *
+   * @var array
+   */
+  protected static $testWebforms = ['test_element_text'];
+
+  /**
+   * Tests building of custom elements.
+   */
+  public function testTextElements() {
+
+    /**************************************************************************/
+    // text format
+    /**************************************************************************/
+
+    // Check that formats and tips are removed and/or hidden.
+    $this->drupalGet('webform/test_element_text');
+    $this->assertRaw('<div class="filter-wrapper js-form-wrapper form-wrapper" data-drupal-selector="edit-text-format-format" style="display: none" id="edit-text-format-format">');
+    $this->assertRaw('<div class="filter-help js-form-wrapper form-wrapper" data-drupal-selector="edit-text-format-format-help" style="display: none" id="edit-text-format-format-help">');
+
+    /**************************************************************************/
+    // counter
+    /**************************************************************************/
+
+    // Check counters
+    $this->drupalGet('webform/test_element_text');
+    $this->assertRaw('<input data-counter-type="character" data-counter-limit="10" class="js-webform-counter webform-counter form-text" data-drupal-selector="edit-counter-characters" type="text" id="edit-counter-characters" name="counter_characters" value="" size="60" maxlength="255" />');
+    $this->assertRaw('<textarea data-counter-type="word" data-counter-limit="3" data-counter-message="word(s) left. This is a custom message" class="js-webform-counter webform-counter form-textarea resize-vertical" data-drupal-selector="edit-counter-words" id="edit-counter-words" name="counter_words" rows="5" cols="60"></textarea>');
+
+    // Check counter validation error.
+    $edit = [
+      'counter_characters' => '01234567890',
+      'counter_words' => 'one two three four',
+    ];
+    $this->drupalPostForm('webform/test_element_text', $edit, t('Submit'));
+    $this->assertRaw('counter_characters</em> must be less than 10 characters.');
+    $this->assertRaw('counter_words</em> must be less than 3 words.');
+
+    // Check counter validation passes.
+    $edit = [
+      'counter_characters' => '0123456789',
+      'counter_words' => 'one two three',
+    ];
+    $this->drupalPostForm('webform/test_element_text', $edit, t('Submit'));
+    $this->assertNoRaw('counter_characters</em> must be less than 10 characters.');
+    $this->assertNoRaw('counter_words</em> must be less than 3 words.');
+
+    /**************************************************************************/
+    // creditcard_number
+    /**************************************************************************/
+
+    // Check basic creditcard_number.
+    $this->drupalGet('webform/test_element_text');
+    $this->assertRaw('<label for="edit-creditcard-number-basic">Credit card number basic</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-creditcard-number-basic" type="text" id="edit-creditcard-number-basic" name="creditcard_number_basic" value="" size="16" maxlength="16" class="form-textfield form-creditcard-number" />');
+
+    // Check invalid credit card number.
+    $edit = [
+      'creditcard_number_basic' => 'not value',
+    ];
+    $this->drupalPostForm('webform/test_element_text', $edit, t('Submit'));
+    $this->assertRaw('The credit card number is not valid.');
+
+    // Check valid credit card number.
+    $edit = [
+      'creditcard_number_basic' => '4111111111111111',
+    ];
+    $this->drupalPostForm('webform/test_element_text', $edit, t('Submit'));
+    $this->assertNoRaw('The credit card number is not valid.');
+
+    // Check valid AmEx (15 digit).
+    $edit = [
+      'creditcard_number_basic' => '378282246310005',
+    ];
+    $this->drupalPostForm('webform/test_element_text', $edit, t('Submit'));
+    $this->assertNoRaw('The credit card number is not valid.');
+  }
+
+}
diff --git a/src/Tests/Element/WebformElementToggleTest.php b/src/Tests/Element/WebformElementToggleTest.php
new file mode 100644
index 00000000..329e684b
--- /dev/null
+++ b/src/Tests/Element/WebformElementToggleTest.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Drupal\webform\Tests\Element;
+
+use Drupal\webform\Tests\WebformTestBase;
+
+/**
+ * Tests for toggle element.
+ *
+ * @group Webform
+ */
+class WebformElementToggleTest extends WebformTestBase  {
+
+  /**
+   * Webforms to load.
+   *
+   * @var array
+   */
+  protected static $testWebforms = ['test_element_toggle'];
+
+  /**
+   * Test toggle element.
+   */
+  public function testToggleElement() {
+    $this->drupalGet('webform/test_element_toggle');
+
+    // Check basic toggle.
+    $this->assertRaw('<div class="js-form-item form-item js-form-type-webform-toggle form-type-webform-toggle js-form-item-toggle-basic form-item-toggle-basic">');
+    $this->assertRaw('<input data-drupal-selector="edit-toggle-basic" type="checkbox" id="edit-toggle-basic" name="toggle_basic" value="1" class="form-checkbox" />');
+    $this->assertRaw('<div class="js-webform-toggle webform-toggle toggle toggle-medium toggle-light" data-toggle-height="24" data-toggle-width="48" data-toggle-text-on="" data-toggle-text-off=""></div>');
+    $this->assertRaw('<label for="edit-toggle-basic" class="option">Basic toggle</label>');
+
+    // Check advanced toggle.
+    $this->assertRaw('<div class="js-form-item form-item js-form-type-webform-toggle form-type-webform-toggle js-form-item-toggle-advanced form-item-toggle-advanced">');
+    $this->assertRaw('<label for="edit-toggle-advanced">Advanced toggle</label>');
+    $this->assertRaw('<input data-drupal-selector="edit-toggle-advanced" type="checkbox" id="edit-toggle-advanced" name="toggle_advanced" value="1" class="form-checkbox" />');
+    $this->assertRaw('<div class="js-webform-toggle webform-toggle toggle toggle-large toggle-iphone" data-toggle-height="36" data-toggle-width="108" data-toggle-text-on="Yes" data-toggle-text-off="No"></div>');
+
+    // Check basic toggles.
+    $this->assertRaw('<fieldset data-drupal-selector="edit-toggles-basic" id="edit-toggles-basic--wrapper" class="fieldgroup form-composite js-form-item form-item js-form-wrapper form-wrapper">');
+    $this->assertRaw('<span class="fieldset-legend">Basic toggles</span>');
+    $this->assertRaw('<div id="edit-toggles-basic" class="webform-options-display-one-column form-checkboxes"><div class="js-form-item form-item js-form-type-webform-toggle form-type-webform-toggle js-form-item-toggles-basic-one form-item-toggles-basic-one">');
+    $this->assertRaw('<input data-drupal-selector="edit-toggles-basic-one" type="checkbox" id="edit-toggles-basic-one" name="toggles_basic[one]" value="one" class="form-checkbox" /><div class="js-webform-toggle webform-toggle toggle toggle-medium toggle-light" data-toggle-height="24" data-toggle-width="48" data-toggle-text-on="" data-toggle-text-off=""></div>');
+    $this->assertRaw('<label for="edit-toggles-basic-one" class="option">One</label>');
+
+    // Check advanced toggles.
+    $this->assertRaw('<fieldset data-drupal-selector="edit-toggles-advanced" id="edit-toggles-advanced--wrapper" class="fieldgroup form-composite js-form-item form-item js-form-wrapper form-wrapper">');
+    $this->assertRaw('<span class="fieldset-legend">Advanced toggles</span>');
+    $this->assertRaw('<div id="edit-toggles-advanced" class="webform-options-display-one-column form-checkboxes"><div class="js-form-item form-item js-form-type-webform-toggle form-type-webform-toggle js-form-item-toggles-advanced-one form-item-toggles-advanced-one">');
+    $this->assertRaw('<input data-drupal-selector="edit-toggles-advanced-one" type="checkbox" id="edit-toggles-advanced-one" name="toggles_advanced[one]" value="one" class="form-checkbox" /><div class="js-webform-toggle webform-toggle toggle toggle-large toggle-iphone" data-toggle-height="36" data-toggle-width="108" data-toggle-text-on="Yes" data-toggle-text-off="No"></div>');
+  }
+
+}
diff --git a/tests/modules/webform_test/config/install/webform.webform.test_element_composite.yml b/tests/modules/webform_test/config/install/webform.webform.test_element_composite.yml
index ddc4e74e..7ce7155c 100644
--- a/tests/modules/webform_test/config/install/webform.webform.test_element_composite.yml
+++ b/tests/modules/webform_test/config/install/webform.webform.test_element_composite.yml
@@ -12,22 +12,76 @@ id: test_element_composite
 title: 'Test: Element: Composite'
 description: 'Test composite elements, includes address, contact, name, and credit card.'
 elements: |
-  address:
-    '#type': address
-    '#title': 'Address'
-    '#flexbox': true
-  contact:
-    '#type': contact
-    '#title': 'Contact'
-    '#flexbox': true
-  name:
-    '#type': name
-    '#title': 'Name'
-    '#flexbox': true
-  creditcard:
-    '#type': creditcard
-    '#title': 'Credit card'
-    '#flexbox': true
+  composite_flexbox:
+    '#type': details
+    '#title': 'Composite Flexbox'
+    '#open': true
+    address:
+      '#type': address
+      '#title': 'Address'
+      '#flexbox': true
+    contact:
+      '#type': contact
+      '#title': 'Contact'
+      '#flexbox': true
+    name:
+      '#type': name
+      '#title': 'Name'
+      '#flexbox': true
+    creditcard:
+      '#type': creditcard
+      '#title': 'Credit card'
+      '#flexbox': true
+  composite_elements:
+    '#type': details
+    '#title': 'Composite Elements'
+    '#open': true
+    contact_basic:
+      '#type': contact
+      '#title': 'Contact basic'
+      '#required': true
+      '#name__required': true
+      '#default_value':
+        name: John Smith
+        company: Acme
+        address: '100 Main Street'
+        address_2: 'PO BOX 999'
+        city: 'Hill Valley'
+        state_province: 'New Jersey'
+        country: 'United States'
+        postal_code: '11111-1111'
+        email: example@example.com
+        phone: 123-456-7890
+    contact_advanced:
+      '#type': contact
+      '#title': 'Contact advanced'
+      '#default_value':
+        name: John Smith
+        company: Acme
+        address: '100 Main Street'
+        address_2: 'PO BOX 999'
+        city: 'Hill Valley'
+        state_province: 'New Jersey'
+        country: 'United States'
+        postal_code: '11111-1111'
+        email: example@example.com
+        phone: 123-456-7890
+      '#name__required': true
+      '#name__title': 'Custom contact name'
+      '#name__description': 'Custom contact name description'
+      '#state_province__type': textfield
+      '#country__required': true
+      '#country__access': false
+    creditcard_basic:
+      '#type': creditcard
+      '#title': 'Credit Card'
+      '#default_value':
+        name: John Smith
+        number: 4111111111111111
+        type: VI
+        civ: 111
+        expiration_month: 1
+        expiration_year: 2025
 css: ''
 javascript: ''
 settings:
diff --git a/tests/modules/webform_test/config/install/webform.webform.test_element_email.yml b/tests/modules/webform_test/config/install/webform.webform.test_element_email.yml
new file mode 100644
index 00000000..741b7871
--- /dev/null
+++ b/tests/modules/webform_test/config/install/webform.webform.test_element_email.yml
@@ -0,0 +1,137 @@
+langcode: en
+status: true
+dependencies:
+  enforced:
+    module:
+      - webform_test
+  module:
+    - webform_test
+uid: null
+template: false
+id: test_element_email
+title: 'Test: Element: Email'
+description: 'Tests email_confirm and email_multiple elements.'
+elements: |
+  '#attributes':
+    novalidate: novalidate
+  email_multiple:
+    '#type': details
+    '#title': 'Email multiple (email_multiple)'
+    '#open': true
+    email_multiple_basic:
+      '#type': email_multiple
+      '#title': 'Multiple email addresses (basic)'
+    email_multiple_advanced:
+      '#type': email_multiple
+      '#title': 'Multiple email addresses (advanced)'
+      '#allow_tokens': true
+      '#description': 'Allows tokens to be included in the comma delimited list of emails'
+  email_confirm:
+    '#type': details
+    '#title': 'Email confirmation (email_confirm)'
+    '#open': true
+    email_confirm_basic:
+      '#type': email_confirm
+      '#title': 'Email confirm basic'
+    email_confirm_advanced:
+      '#type': email_confirm
+      '#title': 'Email confirm advanced'
+      '#description': 'Please make sure to review your email address'
+      '#placeholder': 'Enter email address'
+      '#confirm__title': 'Please confirm your email address'
+      '#confirm__description': 'Please make sure to review your confirmation email address'
+      '#confirm__placeholder': 'Enter confirmation email address'
+css: ''
+javascript: ''
+settings:
+  page: true
+  page_submit_path: ''
+  page_confirm_path: ''
+  form_submit_label: ''
+  form_submit_once: false
+  form_submit_attributes: {  }
+  form_exception_message: ''
+  form_closed_message: ''
+  form_previous_submissions: true
+  form_confidential: false
+  form_confidential_message: ''
+  form_prepopulate: false
+  form_prepopulate_source_entity: false
+  form_novalidate: false
+  form_unsaved: false
+  form_disable_back: false
+  form_autofocus: false
+  form_details_toggle: false
+  wizard_progress_bar: true
+  wizard_progress_pages: false
+  wizard_progress_percentage: false
+  wizard_next_button_label: ''
+  wizard_next_button_attributes: {  }
+  wizard_prev_button_label: ''
+  wizard_prev_button_attributes: {  }
+  wizard_start_label: ''
+  wizard_complete: true
+  wizard_complete_label: ''
+  preview: 0
+  preview_next_button_label: ''
+  preview_next_button_attributes: {  }
+  preview_prev_button_label: ''
+  preview_prev_button_attributes: {  }
+  preview_message: ''
+  draft: false
+  draft_auto_save: false
+  draft_button_label: ''
+  draft_button_attributes: {  }
+  draft_saved_message: ''
+  draft_loaded_message: ''
+  confirmation_type: message
+  confirmation_message: ''
+  confirmation_url: ''
+  confirmation_attributes: {  }
+  confirmation_back: true
+  confirmation_back_label: ''
+  confirmation_back_attributes: {  }
+  limit_total: null
+  limit_total_message: ''
+  limit_user: null
+  limit_user_message: ''
+  entity_limit_total: null
+  entity_limit_user: null
+  results_disabled: true
+  results_disabled_ignore: false
+  token_update: false
+access:
+  create:
+    roles:
+      - anonymous
+      - authenticated
+    users: {  }
+  view_any:
+    roles: {  }
+    users: {  }
+  update_any:
+    roles: {  }
+    users: {  }
+  delete_any:
+    roles: {  }
+    users: {  }
+  purge_any:
+    roles: {  }
+    users: {  }
+  view_own:
+    roles: {  }
+    users: {  }
+  update_own:
+    roles: {  }
+    users: {  }
+  delete_own:
+    roles: {  }
+    users: {  }
+handlers:
+  debug:
+    id: debug
+    label: Debug
+    handler_id: debug
+    status: true
+    weight: 1
+    settings: {  }
diff --git a/tests/modules/webform_test/config/install/webform.webform.test_element_extras.yml b/tests/modules/webform_test/config/install/webform.webform.test_element_extras.yml
deleted file mode 100644
index 1e292703..00000000
--- a/tests/modules/webform_test/config/install/webform.webform.test_element_extras.yml
+++ /dev/null
@@ -1,323 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  enforced:
-    module:
-      - webform_test
-  module:
-    - webform_test
-uid: null
-template: false
-id: test_element_extras
-title: 'Test: Element: Extras'
-description: 'Tests extra elements, includes code(mirror), creditcard_number, email_confirm, and likert.'
-elements: |
-  '#attributes':
-    novalidate: novalidate
-  drupal:
-    '#type': details
-    '#title': 'Drupal elements'
-    '#open': true
-    text_format:
-      '#type': text_format
-      '#title': 'text_format'
-      '#hide_help': TRUE
-  counter:
-    '#type': details
-    '#title': 'Word and character counter'
-    '#open': true
-    counter_characters:
-      '#type': textfield
-      '#title': 'Character counter'
-      '#counter_type': character
-      '#counter_maximum': 10
-    counter_words:
-      '#type': textarea
-      '#title': 'Word counter'
-      '#counter_type': word
-      '#counter_maximum': 3
-      '#counter_message': 'word(s) left. This is a custom message'
-  email_multiple:
-    '#type': details
-    '#title': 'Email multiple (email_multiple)'
-    '#open': true
-    email_multiple_basic:
-      '#type': email_multiple
-      '#title': 'Multiple email addresses (basic)'
-    email_multiple_advanced:
-      '#type': email_multiple
-      '#title': 'Multiple email addresses (advanced)'
-      '#allow_tokens': true
-      '#description': 'Allows tokens to be included in the comma delimited list of emails'
-  email_confirm:
-    '#type': details
-    '#title': 'Email confirmation (email_confirm)'
-    '#open': true
-    email_confirm_basic:
-      '#type': email_confirm
-      '#title': 'Email confirm basic'
-    email_confirm_advanced:
-      '#type': email_confirm
-      '#title': 'Email confirm advanced'
-      '#description': 'Please make sure to review your email address'
-      '#placeholder': 'Enter email address'
-      '#confirm__title': 'Please confirm your email address'
-      '#confirm__description': 'Please make sure to review your confirmation email address'
-      '#confirm__placeholder': 'Enter confirmation email address'
-  creditcard_number:
-    '#type': details
-    '#title': 'Credit card number (creditcard_number)'
-    '#open': true
-    creditcard_number_basic:
-      '#type': creditcard_number
-      '#title': 'Credit card number basic'
-  toggle_elements:
-    '#type': details
-    '#title': 'Toggle Elements'
-    '#open': true
-    toggle_basic:
-      '#type': toggle
-      '#title': 'Basic toggle'
-    toggle_advanced:
-      '#type': toggle
-      '#title': 'Advanced toggle'
-      '#title_display': before
-      '#toggle_theme': iphone
-      '#toggle_size': large
-      '#on_text': Yes
-      '#off_text': No
-    toggles_basic:
-      '#type': toggles
-      '#title': 'Basic toggles'
-      '#options':
-        one: One
-        two: Two
-        three: Three
-    toggles_advanced:
-      '#type': toggles
-      '#title': 'Advanced toggles'
-      '#title_display': before
-      '#toggle_theme': iphone
-      '#toggle_size': large
-      '#on_text': Yes
-      '#off_text': No
-      '#options':
-        one: One
-        two: Two
-        three: Three
-  rating_elements:
-    '#type': details
-    '#title': 'Rating Elements'
-    '#open': true
-    rating_basic:
-      '#type': rating
-      '#title': 'Rating basic'
-    rating_advanced:
-      '#type': rating
-      '#title': 'Rating advanced'
-      '#star_size': large
-      '#reset': true
-      '#max': '10'
-      '#step': '0.1'
-  signature_elements:
-    '#type': details
-    '#title': 'Signature Elements'
-    '#open': true
-    signature_basic:
-      '#type': signature
-      '#title': 'Signature basic'
-  codemirror_elements:
-    '#type': details
-    '#title': 'CodeMirror Elements'
-    '#open': true
-    text_basic:
-      '#type': codemirror
-      '#title': 'Text basic'
-    yaml_basic:
-      '#type': codemirror
-      '#mode': yaml
-      '#title': 'YAML basic'
-    html_basic:
-      '#type': codemirror
-      '#mode': html
-      '#title': 'HTML basic'
-  table_elements:
-    '#type': 'details'
-    '#title': 'Table'
-    '#open': true
-    table:
-      '#type': table
-      '#header':
-        - 'First Name'
-        - 'Last Name'
-        - 'Gender'
-      table__1:
-        table__1__first_name:
-          '#type': 'textfield'
-          '#size': 20
-          '#default_value': 'John'
-        table__1__last_name:
-          '#type': 'textfield'
-          '#size': 20
-          '#default_value': 'Smith'
-        table__1__gender:
-          '#type': 'select'
-          '#options': gender
-          '#default_value': 'Male'
-      table__2:
-        table__2__first_name:
-          '#type': 'textfield'
-          '#size': 20
-          '#default_value': 'Jane'
-        table__2__last_name:
-          '#type': 'textfield'
-          '#size': 20
-          '#default_value': 'Doe'
-        table__2__gender:
-          '#type': 'select'
-          '#options': gender
-          '#default_value': 'Female'
-  composite_elements:
-    '#type': details
-    '#title': 'Composite Elements'
-    '#open': true
-    contact_basic:
-      '#type': contact
-      '#title': 'Contact basic'
-      '#required': true
-      '#name__required': true
-      '#default_value':
-        name: John Smith
-        company: Acme
-        address: '100 Main Street'
-        address_2: 'PO BOX 999'
-        city: 'Hill Valley'
-        state_province: 'New Jersey'
-        country: 'United States'
-        postal_code: '11111-1111'
-        email: example@example.com
-        phone: 123-456-7890
-    contact_advanced:
-      '#type': contact
-      '#title': 'Contact advanced'
-      '#default_value':
-        name: John Smith
-        company: Acme
-        address: '100 Main Street'
-        address_2: 'PO BOX 999'
-        city: 'Hill Valley'
-        state_province: 'New Jersey'
-        country: 'United States'
-        postal_code: '11111-1111'
-        email: example@example.com
-        phone: 123-456-7890
-      '#name__required': true
-      '#name__title': 'Custom contact name'
-      '#name__description': 'Custom contact name description'
-      '#state_province__type': textfield
-      '#country__required': true
-      '#country__access': false
-    creditcard:
-      '#type': creditcard
-      '#title': 'Credit Card'
-      '#default_value':
-        name: John Smith
-        number: 4111111111111111
-        type: VI
-        civ: 111
-        expiration_month: 1
-        expiration_year: 2025
-css: ''
-javascript: ''
-settings:
-  page: true
-  page_submit_path: ''
-  page_confirm_path: ''
-  form_submit_label: ''
-  form_submit_once: false
-  form_submit_attributes: {  }
-  form_exception_message: ''
-  form_closed_message: ''
-  form_previous_submissions: true
-  form_confidential: false
-  form_confidential_message: ''
-  form_prepopulate: false
-  form_prepopulate_source_entity: false
-  form_novalidate: false
-  form_unsaved: false
-  form_disable_back: false
-  form_autofocus: false
-  form_details_toggle: false
-  wizard_progress_bar: true
-  wizard_progress_pages: false
-  wizard_progress_percentage: false
-  wizard_next_button_label: ''
-  wizard_next_button_attributes: {  }
-  wizard_prev_button_label: ''
-  wizard_prev_button_attributes: {  }
-  wizard_start_label: ''
-  wizard_complete: true
-  wizard_complete_label: ''
-  preview: 0
-  preview_next_button_label: ''
-  preview_next_button_attributes: {  }
-  preview_prev_button_label: ''
-  preview_prev_button_attributes: {  }
-  preview_message: ''
-  draft: false
-  draft_auto_save: false
-  draft_button_label: ''
-  draft_button_attributes: {  }
-  draft_saved_message: ''
-  draft_loaded_message: ''
-  confirmation_type: message
-  confirmation_message: ''
-  confirmation_url: ''
-  confirmation_attributes: {  }
-  confirmation_back: true
-  confirmation_back_label: ''
-  confirmation_back_attributes: {  }
-  limit_total: null
-  limit_total_message: ''
-  limit_user: null
-  limit_user_message: ''
-  entity_limit_total: null
-  entity_limit_user: null
-  results_disabled: true
-  results_disabled_ignore: false
-  token_update: false
-access:
-  create:
-    roles:
-      - anonymous
-      - authenticated
-    users: {  }
-  view_any:
-    roles: {  }
-    users: {  }
-  update_any:
-    roles: {  }
-    users: {  }
-  delete_any:
-    roles: {  }
-    users: {  }
-  purge_any:
-    roles: {  }
-    users: {  }
-  view_own:
-    roles: {  }
-    users: {  }
-  update_own:
-    roles: {  }
-    users: {  }
-  delete_own:
-    roles: {  }
-    users: {  }
-handlers:
-  debug:
-    id: debug
-    label: Debug
-    handler_id: debug
-    status: true
-    weight: 1
-    settings: {  }
diff --git a/tests/modules/webform_test/config/install/webform.webform.test_element_rating.yml b/tests/modules/webform_test/config/install/webform.webform.test_element_rating.yml
new file mode 100644
index 00000000..217cf6e4
--- /dev/null
+++ b/tests/modules/webform_test/config/install/webform.webform.test_element_rating.yml
@@ -0,0 +1,122 @@
+langcode: en
+status: true
+dependencies:
+  enforced:
+    module:
+      - webform_test
+  module:
+    - webform_test
+uid: null
+template: false
+id: test_element_rating
+title: 'Test: Element: Rating'
+description: 'Test the rating element.'
+elements: |
+  rating_elements:
+    '#type': details
+    '#title': 'Rating Elements'
+    '#open': true
+    rating_basic:
+      '#type': rating
+      '#title': 'Rating basic'
+    rating_advanced:
+      '#type': rating
+      '#title': 'Rating advanced'
+      '#star_size': large
+      '#reset': true
+      '#max': '10'
+      '#step': '0.1'
+css: ''
+javascript: ''
+settings:
+  page: true
+  page_submit_path: ''
+  page_confirm_path: ''
+  form_submit_label: ''
+  form_submit_once: false
+  form_submit_attributes: {  }
+  form_exception_message: ''
+  form_closed_message: ''
+  form_previous_submissions: true
+  form_confidential: false
+  form_confidential_message: ''
+  form_prepopulate: false
+  form_prepopulate_source_entity: false
+  form_novalidate: false
+  form_unsaved: false
+  form_disable_back: false
+  form_autofocus: false
+  form_details_toggle: false
+  wizard_progress_bar: true
+  wizard_progress_pages: false
+  wizard_progress_percentage: false
+  wizard_next_button_label: ''
+  wizard_next_button_attributes: {  }
+  wizard_prev_button_label: ''
+  wizard_prev_button_attributes: {  }
+  wizard_start_label: ''
+  wizard_complete: true
+  wizard_complete_label: ''
+  preview: 0
+  preview_next_button_label: ''
+  preview_next_button_attributes: {  }
+  preview_prev_button_label: ''
+  preview_prev_button_attributes: {  }
+  preview_message: ''
+  draft: false
+  draft_auto_save: false
+  draft_button_label: ''
+  draft_button_attributes: {  }
+  draft_saved_message: ''
+  draft_loaded_message: ''
+  confirmation_type: message
+  confirmation_message: ''
+  confirmation_url: ''
+  confirmation_attributes: {  }
+  confirmation_back: true
+  confirmation_back_label: ''
+  confirmation_back_attributes: {  }
+  limit_total: null
+  limit_total_message: ''
+  limit_user: null
+  limit_user_message: ''
+  entity_limit_total: null
+  entity_limit_user: null
+  results_disabled: false
+  results_disabled_ignore: false
+  token_update: false
+access:
+  create:
+    roles:
+      - anonymous
+      - authenticated
+    users: {  }
+  view_any:
+    roles: {  }
+    users: {  }
+  update_any:
+    roles: {  }
+    users: {  }
+  delete_any:
+    roles: {  }
+    users: {  }
+  purge_any:
+    roles: {  }
+    users: {  }
+  view_own:
+    roles: {  }
+    users: {  }
+  update_own:
+    roles: {  }
+    users: {  }
+  delete_own:
+    roles: {  }
+    users: {  }
+handlers:
+  debug:
+    id: debug
+    label: Debug
+    handler_id: debug
+    status: true
+    weight: 1
+    settings: {  }
diff --git a/tests/modules/webform_test/config/install/webform.webform.test_element_signature.yml b/tests/modules/webform_test/config/install/webform.webform.test_element_signature.yml
new file mode 100644
index 00000000..511c5571
--- /dev/null
+++ b/tests/modules/webform_test/config/install/webform.webform.test_element_signature.yml
@@ -0,0 +1,115 @@
+langcode: en
+status: true
+dependencies:
+  enforced:
+    module:
+      - webform_test
+  module:
+    - webform_test
+uid: null
+template: false
+id: test_element_signature
+title: 'Test: Element: Signature'
+description: 'Test the signature element.'
+elements: |
+  signature_elements:
+    '#type': details
+    '#title': 'Signature Elements'
+    '#open': true
+    signature_basic:
+      '#type': signature
+      '#title': 'Signature basic'
+css: ''
+javascript: ''
+settings:
+  page: true
+  page_submit_path: ''
+  page_confirm_path: ''
+  form_submit_label: ''
+  form_submit_once: false
+  form_submit_attributes: {  }
+  form_exception_message: ''
+  form_closed_message: ''
+  form_previous_submissions: true
+  form_confidential: false
+  form_confidential_message: ''
+  form_prepopulate: false
+  form_prepopulate_source_entity: false
+  form_novalidate: false
+  form_unsaved: false
+  form_disable_back: false
+  form_autofocus: false
+  form_details_toggle: false
+  wizard_progress_bar: true
+  wizard_progress_pages: false
+  wizard_progress_percentage: false
+  wizard_next_button_label: ''
+  wizard_next_button_attributes: {  }
+  wizard_prev_button_label: ''
+  wizard_prev_button_attributes: {  }
+  wizard_start_label: ''
+  wizard_complete: true
+  wizard_complete_label: ''
+  preview: 0
+  preview_next_button_label: ''
+  preview_next_button_attributes: {  }
+  preview_prev_button_label: ''
+  preview_prev_button_attributes: {  }
+  preview_message: ''
+  draft: false
+  draft_auto_save: false
+  draft_button_label: ''
+  draft_button_attributes: {  }
+  draft_saved_message: ''
+  draft_loaded_message: ''
+  confirmation_type: message
+  confirmation_message: ''
+  confirmation_url: ''
+  confirmation_attributes: {  }
+  confirmation_back: true
+  confirmation_back_label: ''
+  confirmation_back_attributes: {  }
+  limit_total: null
+  limit_total_message: ''
+  limit_user: null
+  limit_user_message: ''
+  entity_limit_total: null
+  entity_limit_user: null
+  results_disabled: false
+  results_disabled_ignore: false
+  token_update: false
+access:
+  create:
+    roles:
+      - anonymous
+      - authenticated
+    users: {  }
+  view_any:
+    roles: {  }
+    users: {  }
+  update_any:
+    roles: {  }
+    users: {  }
+  delete_any:
+    roles: {  }
+    users: {  }
+  purge_any:
+    roles: {  }
+    users: {  }
+  view_own:
+    roles: {  }
+    users: {  }
+  update_own:
+    roles: {  }
+    users: {  }
+  delete_own:
+    roles: {  }
+    users: {  }
+handlers:
+  debug:
+    id: debug
+    label: Debug
+    handler_id: debug
+    status: true
+    weight: 1
+    settings: {  }
diff --git a/tests/modules/webform_test/config/install/webform.webform.test_element_table.yml b/tests/modules/webform_test/config/install/webform.webform.test_element_table.yml
index 297e35f2..8596d50b 100644
--- a/tests/modules/webform_test/config/install/webform.webform.test_element_table.yml
+++ b/tests/modules/webform_test/config/install/webform.webform.test_element_table.yml
@@ -12,6 +12,42 @@ id: test_element_table
 title: 'Test: Element: Table'
 description: 'Test table elements.'
 elements: |
+  table_elements:
+    '#type': 'details'
+    '#title': 'Table'
+    '#open': true
+    table:
+      '#type': table
+      '#header':
+        - 'First Name'
+        - 'Last Name'
+        - 'Gender'
+      table__1:
+        table__1__first_name:
+          '#type': 'textfield'
+          '#size': 20
+          '#default_value': 'John'
+        table__1__last_name:
+          '#type': 'textfield'
+          '#size': 20
+          '#default_value': 'Smith'
+        table__1__gender:
+          '#type': 'select'
+          '#options': gender
+          '#default_value': 'Male'
+      table__2:
+        table__2__first_name:
+          '#type': 'textfield'
+          '#size': 20
+          '#default_value': 'Jane'
+        table__2__last_name:
+          '#type': 'textfield'
+          '#size': 20
+          '#default_value': 'Doe'
+        table__2__gender:
+          '#type': 'select'
+          '#options': gender
+          '#default_value': 'Female'
   tableselect_sort_elements:
     '#type': details
     '#title': 'Table Select Elements'
diff --git a/tests/modules/webform_test/config/install/webform.webform.test_element_text.yml b/tests/modules/webform_test/config/install/webform.webform.test_element_text.yml
new file mode 100644
index 00000000..32fbb3ab
--- /dev/null
+++ b/tests/modules/webform_test/config/install/webform.webform.test_element_text.yml
@@ -0,0 +1,140 @@
+langcode: en
+status: true
+dependencies:
+  enforced:
+    module:
+      - webform_test
+  module:
+    - webform_test
+uid: null
+template: false
+id: test_element_text
+title: 'Test: Element: Text'
+description: 'Tests text field and text area based elements.'
+elements: |
+  '#attributes':
+    novalidate: novalidate
+  text_format_element:
+    '#type': details
+    '#title': 'Text format elements'
+    '#open': true
+    text_format:
+      '#type': text_format
+      '#title': 'text_format'
+      '#hide_help': TRUE
+  counter_elements:
+    '#type': details
+    '#title': 'Word and character counter'
+    '#open': true
+    counter_characters:
+      '#type': textfield
+      '#title': 'Character counter'
+      '#counter_type': character
+      '#counter_maximum': 10
+    counter_words:
+      '#type': textarea
+      '#title': 'Word counter'
+      '#counter_type': word
+      '#counter_maximum': 3
+      '#counter_message': 'word(s) left. This is a custom message'
+  creditcard_number_elements:
+    '#type': details
+    '#title': 'Credit card number (creditcard_number)'
+    '#open': true
+    creditcard_number_basic:
+      '#type': creditcard_number
+      '#title': 'Credit card number basic'
+css: ''
+javascript: ''
+settings:
+  page: true
+  page_submit_path: ''
+  page_confirm_path: ''
+  form_submit_label: ''
+  form_submit_once: false
+  form_submit_attributes: {  }
+  form_exception_message: ''
+  form_closed_message: ''
+  form_previous_submissions: true
+  form_confidential: false
+  form_confidential_message: ''
+  form_prepopulate: false
+  form_prepopulate_source_entity: false
+  form_novalidate: false
+  form_unsaved: false
+  form_disable_back: false
+  form_autofocus: false
+  form_details_toggle: false
+  wizard_progress_bar: true
+  wizard_progress_pages: false
+  wizard_progress_percentage: false
+  wizard_next_button_label: ''
+  wizard_next_button_attributes: {  }
+  wizard_prev_button_label: ''
+  wizard_prev_button_attributes: {  }
+  wizard_start_label: ''
+  wizard_complete: true
+  wizard_complete_label: ''
+  preview: 0
+  preview_next_button_label: ''
+  preview_next_button_attributes: {  }
+  preview_prev_button_label: ''
+  preview_prev_button_attributes: {  }
+  preview_message: ''
+  draft: false
+  draft_auto_save: false
+  draft_button_label: ''
+  draft_button_attributes: {  }
+  draft_saved_message: ''
+  draft_loaded_message: ''
+  confirmation_type: message
+  confirmation_message: ''
+  confirmation_url: ''
+  confirmation_attributes: {  }
+  confirmation_back: true
+  confirmation_back_label: ''
+  confirmation_back_attributes: {  }
+  limit_total: null
+  limit_total_message: ''
+  limit_user: null
+  limit_user_message: ''
+  entity_limit_total: null
+  entity_limit_user: null
+  results_disabled: true
+  results_disabled_ignore: false
+  token_update: false
+access:
+  create:
+    roles:
+      - anonymous
+      - authenticated
+    users: {  }
+  view_any:
+    roles: {  }
+    users: {  }
+  update_any:
+    roles: {  }
+    users: {  }
+  delete_any:
+    roles: {  }
+    users: {  }
+  purge_any:
+    roles: {  }
+    users: {  }
+  view_own:
+    roles: {  }
+    users: {  }
+  update_own:
+    roles: {  }
+    users: {  }
+  delete_own:
+    roles: {  }
+    users: {  }
+handlers:
+  debug:
+    id: debug
+    label: Debug
+    handler_id: debug
+    status: true
+    weight: 1
+    settings: {  }
diff --git a/tests/modules/webform_test/config/install/webform.webform.test_element_toggle.yml b/tests/modules/webform_test/config/install/webform.webform.test_element_toggle.yml
new file mode 100644
index 00000000..df7b3f15
--- /dev/null
+++ b/tests/modules/webform_test/config/install/webform.webform.test_element_toggle.yml
@@ -0,0 +1,142 @@
+langcode: en
+status: true
+dependencies:
+  enforced:
+    module:
+      - webform_test
+  module:
+    - webform_test
+uid: null
+template: false
+id: test_element_toggle
+title: 'Test: Element: Toggle'
+description: 'Test the toggle element.'
+elements: |
+  toggle_elements:
+    '#type': details
+    '#title': 'Toggle Elements'
+    '#open': true
+    toggle_basic:
+      '#type': toggle
+      '#title': 'Basic toggle'
+    toggle_advanced:
+      '#type': toggle
+      '#title': 'Advanced toggle'
+      '#title_display': before
+      '#toggle_theme': iphone
+      '#toggle_size': large
+      '#on_text': Yes
+      '#off_text': No
+    toggles_basic:
+      '#type': toggles
+      '#title': 'Basic toggles'
+      '#options':
+        one: One
+        two: Two
+        three: Three
+    toggles_advanced:
+      '#type': toggles
+      '#title': 'Advanced toggles'
+      '#title_display': before
+      '#toggle_theme': iphone
+      '#toggle_size': large
+      '#on_text': Yes
+      '#off_text': No
+      '#options':
+        one: One
+        two: Two
+        three: Three
+css: ''
+javascript: ''
+settings:
+  page: true
+  page_submit_path: ''
+  page_confirm_path: ''
+  form_submit_label: ''
+  form_submit_once: false
+  form_submit_attributes: {  }
+  form_exception_message: ''
+  form_closed_message: ''
+  form_previous_submissions: true
+  form_confidential: false
+  form_confidential_message: ''
+  form_prepopulate: false
+  form_prepopulate_source_entity: false
+  form_novalidate: false
+  form_unsaved: false
+  form_disable_back: false
+  form_autofocus: false
+  form_details_toggle: false
+  wizard_progress_bar: true
+  wizard_progress_pages: false
+  wizard_progress_percentage: false
+  wizard_next_button_label: ''
+  wizard_next_button_attributes: {  }
+  wizard_prev_button_label: ''
+  wizard_prev_button_attributes: {  }
+  wizard_start_label: ''
+  wizard_complete: true
+  wizard_complete_label: ''
+  preview: 0
+  preview_next_button_label: ''
+  preview_next_button_attributes: {  }
+  preview_prev_button_label: ''
+  preview_prev_button_attributes: {  }
+  preview_message: ''
+  draft: false
+  draft_auto_save: false
+  draft_button_label: ''
+  draft_button_attributes: {  }
+  draft_saved_message: ''
+  draft_loaded_message: ''
+  confirmation_type: message
+  confirmation_message: ''
+  confirmation_url: ''
+  confirmation_attributes: {  }
+  confirmation_back: true
+  confirmation_back_label: ''
+  confirmation_back_attributes: {  }
+  limit_total: null
+  limit_total_message: ''
+  limit_user: null
+  limit_user_message: ''
+  entity_limit_total: null
+  entity_limit_user: null
+  results_disabled: false
+  results_disabled_ignore: false
+  token_update: false
+access:
+  create:
+    roles:
+      - anonymous
+      - authenticated
+    users: {  }
+  view_any:
+    roles: {  }
+    users: {  }
+  update_any:
+    roles: {  }
+    users: {  }
+  delete_any:
+    roles: {  }
+    users: {  }
+  purge_any:
+    roles: {  }
+    users: {  }
+  view_own:
+    roles: {  }
+    users: {  }
+  update_own:
+    roles: {  }
+    users: {  }
+  delete_own:
+    roles: {  }
+    users: {  }
+handlers:
+  debug:
+    id: debug
+    label: Debug
+    handler_id: debug
+    status: true
+    weight: 1
+    settings: {  }
