diff --git a/commerce_pos.libraries.yml b/commerce_pos.libraries.yml
index 64d7f4e..43de9dc 100644
--- a/commerce_pos.libraries.yml
+++ b/commerce_pos.libraries.yml
@@ -4,4 +4,7 @@ form:
     layout:
       css/commerce_pos_style.css: {}
   js:
-    js/commerce_pos.js: {}
\ No newline at end of file
+    js/commerce_pos.js: {}
+  dependencies:
+    - core/jquery
+    - core/drupal
diff --git a/js/commerce_pos.js b/js/commerce_pos.js
index a4e8902..4d75817 100644
--- a/js/commerce_pos.js
+++ b/js/commerce_pos.js
@@ -1,4 +1,4 @@
-(function ($) {
+(function ($, Drupal) {
   Drupal.behaviors.commercePosSalePay = {
     attach: function (context, settings) {
       $('.commerce-pos-keypad-key', context).each(function () {
@@ -51,4 +51,4 @@
     }
   };
 
-} (jQuery));
+} (jQuery, Drupal));
diff --git a/modules/keypad/commerce_pos_keypad.libraries.yml b/modules/keypad/commerce_pos_keypad.libraries.yml
index 354228e..9ba0e8c 100644
--- a/modules/keypad/commerce_pos_keypad.libraries.yml
+++ b/modules/keypad/commerce_pos_keypad.libraries.yml
@@ -11,4 +11,6 @@ keypad:
         commercePosKeypadKeypad: null
   dependencies:
     - core/jquery
+    - core/jquery.once
+    - core/drupal
     - core/drupalSettings
diff --git a/modules/keypad/js/commerce_pos_keypad.js b/modules/keypad/js/commerce_pos_keypad.js
index 5c1bae5..0e9b73b 100644
--- a/modules/keypad/js/commerce_pos_keypad.js
+++ b/modules/keypad/js/commerce_pos_keypad.js
@@ -1,4 +1,4 @@
-(function ($) {
+(function ($, Drupal, drupalSettings) {
   var inputBox = null;
 
   Drupal.behaviors.commercePosKeypadKeypad = {
@@ -258,4 +258,4 @@
     });
   };
 
-}(jQuery));
+}(jQuery, Drupal, drupalSettings));
diff --git a/modules/keypad/tests/modules/keypad_test/commerce_pos_keypad_test.info.yml b/modules/keypad/tests/modules/keypad_test/commerce_pos_keypad_test.info.yml
new file mode 100644
index 0000000..7663674
--- /dev/null
+++ b/modules/keypad/tests/modules/keypad_test/commerce_pos_keypad_test.info.yml
@@ -0,0 +1,7 @@
+name: Commerce POS Keypad Test
+description: Test module for the keypad
+type: module
+package: Testing
+core: 8.x
+dependencies:
+  - commerce_pos_keypad
diff --git a/modules/keypad/tests/modules/keypad_test/commerce_pos_keypad_test.routing.yml b/modules/keypad/tests/modules/keypad_test/commerce_pos_keypad_test.routing.yml
new file mode 100644
index 0000000..a41a7e4
--- /dev/null
+++ b/modules/keypad/tests/modules/keypad_test/commerce_pos_keypad_test.routing.yml
@@ -0,0 +1,14 @@
+commerce_pos_keypad_test.commerce_pos_keypad_pos_test:
+  path: '/commerce_pos_keypad_pos_test'
+  defaults:
+    _form: '\Drupal\commerce_pos_keypad_test\Form\KeypadPosForm'
+    _title: 'Keypad POS test form'
+  requirements:
+    _access: 'TRUE'
+commerce_pos_keypad_test.commerce_pos_keypad_text_test:
+  path: '/commerce_pos_keypad_text_test'
+  defaults:
+    _form: '\Drupal\commerce_pos_keypad_test\Form\KeypadTextElementForm'
+    _title: 'Keypad text test form'
+  requirements:
+    _access: 'TRUE'
diff --git a/modules/keypad/tests/modules/keypad_test/src/Form/KeypadPosForm.php b/modules/keypad/tests/modules/keypad_test/src/Form/KeypadPosForm.php
new file mode 100644
index 0000000..65655eb
--- /dev/null
+++ b/modules/keypad/tests/modules/keypad_test/src/Form/KeypadPosForm.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Drupal\commerce_pos_keypad_test\Form;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Form for testing keypad themed containers.
+ */
+class KeypadPosForm extends FormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'commerce_pos_keypad_test_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['#attached']['library'][] = 'commerce_pos_keypad/keypad';
+    $form['#attached']['library'][] = 'commerce_pos/form';
+
+    $form['keypad'] = [
+      '#type' => 'container',
+      '#id' => 'commerce-pos-sale-keypad-wrapper',
+      '#tree' => TRUE,
+      '#theme' => 'commerce_pos_keypad',
+    ];
+    $form['keypad']['amount'] = [
+      '#type' => 'textfield',
+      '#title' => t('Enter amount'),
+      '#required' => TRUE,
+      '#default_value' => 100,
+      '#attributes' => [
+        'autofocus' => 'autofocus',
+        'autocomplete' => 'off',
+        'class' => [
+          'commerce-pos-payment-keypad-amount',
+        ],
+      ],
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+
+  }
+
+}
diff --git a/modules/keypad/tests/modules/keypad_test/src/Form/KeypadTextElementForm.php b/modules/keypad/tests/modules/keypad_test/src/Form/KeypadTextElementForm.php
new file mode 100644
index 0000000..794a6c4
--- /dev/null
+++ b/modules/keypad/tests/modules/keypad_test/src/Form/KeypadTextElementForm.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Drupal\commerce_pos_keypad_test\Form;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Form for testing keypad textfield elements.
+ */
+class KeypadTextElementForm extends FormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'commerce_pos_keypad_test_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['#attached']['library'][] = 'commerce_pos_keypad/keypad';
+
+    $form['cashier_id'] = [
+      '#type' => 'textfield',
+      '#title' => t('Cashier ID'),
+      '#description' => t('ID of the cashier logging in'),
+      '#commerce_pos_keypad' => [
+        'type' => 'keypad',
+        'events' => [
+          '.commerce-pos-cashier-login-form-log-in' => [
+            'click' => [],
+          ],
+        ],
+      ],
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+
+  }
+
+}
diff --git a/modules/keypad/tests/src/FunctionalJavascript/KeypadTest.php b/modules/keypad/tests/src/FunctionalJavascript/KeypadTest.php
new file mode 100644
index 0000000..33382b6
--- /dev/null
+++ b/modules/keypad/tests/src/FunctionalJavascript/KeypadTest.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace Drupal\Tests\commerce_pos_keypad\FunctionalJavascript;
+
+use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
+
+/**
+ * Tests the Commerce POS Keypad form.
+ *
+ * @group commerce_pos_keypad
+ */
+class KeypadTest extends JavascriptTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'commerce_pos_keypad_test',
+  ];
+
+  /**
+   * Tests a keypad added to a form the same way as PosForm.
+   */
+  public function testCommercePosForm() {
+    $web_assert = $this->assertSession();
+    $this->drupalGet('commerce_pos_keypad_pos_test');
+    $web_assert->fieldValueEquals('keypad[amount]', '100');
+    $this->getSession()->getPage()->find('xpath', '//*[@id="commerce-pos-sale-keypad-wrapper"]/div/div[2]/div[1]/div[1]');
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="7"]')[0]->click();
+    $web_assert->fieldValueEquals('keypad[amount]', '1007');
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind=""]')[0]->click();
+    $web_assert->fieldValueEquals('keypad[amount]', '100');
+    $this->xpath('//div[@class="commerce-pos-keypad-key clear-key" and @data-keybind="Clear"]')[0]->click();
+    $web_assert->fieldValueEquals('keypad[amount]', '');
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="1"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="000"]')[0]->click();
+    $web_assert->fieldValueEquals('keypad[amount]', '1000');
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="."]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="5"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="2"]')[0]->click();
+    $web_assert->fieldValueEquals('keypad[amount]', '1000.52');
+  }
+
+  /**
+   * Tests a keypad added to text element.
+   */
+  public function testCommerceTextForm() {
+    $web_assert = $this->assertSession();
+    $this->drupalGet('commerce_pos_keypad_text_test');
+    $this->click('.commerce-pos-keypad-keypad-icon');
+    // Press all of the buttons.
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="1"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="2"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="3"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="4"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="5"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="6"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="7"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="8"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="9"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="0"]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="."]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="1"]')[0]->click();
+    // This is the delete button.
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind=""]')[0]->click();
+    $this->xpath('//div[@class="commerce-pos-keypad-key commerce-pos-keypad-action" and @data-key-action="submit"]')[0]->click();
+    $web_assert->fieldValueEquals('cashier_id', '1234567890.');
+    $this->click('.commerce-pos-keypad-keypad-icon');
+    $this->xpath('//div[@class="commerce-pos-keypad-key" and @data-keybind="1"]')[0]->click();
+    $web_assert->fieldValueEquals('commerce-pos-keypad-keypad-value', '1234567890.1');
+    $this->click('.commerce-pos-keypad-close');
+    // After clicking close the value is not updated.
+    $web_assert->fieldValueEquals('cashier_id', '1234567890.');
+  }
+
+}
