From 34784025a84a622a2262a6cce842347024e579f2 Mon Sep 17 00:00:00 2001 From: Philip Dudley <435890+pdud@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:47:41 -0500 Subject: [PATCH] feat: octanify --- .github/workflows/ci.yml | 6 +- .jshintrc | 32 ---- README.md | 81 +++++---- addon/components/credit-card-form.hbs | 56 ++++++ addon/components/credit-card-form.js | 100 +++++------ addon/components/input-credit-card-cvc.hbs | 8 + addon/components/input-credit-card-cvc.js | 49 +++--- .../input-credit-card-expiration.hbs | 10 ++ .../input-credit-card-expiration.js | 69 ++++---- addon/components/input-credit-card-number.hbs | 10 ++ addon/components/input-credit-card-number.js | 40 ++--- .../components/input-credit-card-zipcode.hbs | 9 + addon/components/input-credit-card-zipcode.js | 45 +++-- addon/utils/formatters.js | 15 +- addon/utils/is-whitelist-keypress.js | 10 +- config/ember-try.js | 12 ++ tests/.jshintrc | 52 ------ tests/dummy/app/controllers/application.js | 25 +++ tests/dummy/app/index.html | 1 + tests/dummy/app/templates/application.hbs | 12 +- .../components/credit-card-form-test.js | 37 +++- .../components/input-credit-card-cvc-test.js | 6 +- .../input-credit-card-expiration-test.js | 162 +++++++++++++----- .../input-credit-card-number-test.js | 9 +- .../input-credit-card-zipcode-test.js | 6 +- tests/unit/utils/cards-test.js | 2 +- tests/unit/utils/formatters-test.js | 7 +- tests/unit/utils/validations-test.js | 2 +- 28 files changed, 515 insertions(+), 358 deletions(-) delete mode 100644 .jshintrc create mode 100644 addon/components/credit-card-form.hbs create mode 100644 addon/components/input-credit-card-cvc.hbs create mode 100644 addon/components/input-credit-card-expiration.hbs create mode 100644 addon/components/input-credit-card-number.hbs create mode 100644 addon/components/input-credit-card-zipcode.hbs delete mode 100644 tests/.jshintrc create mode 100644 tests/dummy/app/controllers/application.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6e07e5..37ce16f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,9 +90,9 @@ jobs: try-scenario: - ember-lts-3.24 - ember-lts-3.28 - # - ember-release - # - ember-beta - # - ember-canary + - ember-release + - ember-beta + - ember-canary - ember-classic - ember-default-with-jquery - embroider-safe diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index d421faa..0000000 --- a/.jshintrc +++ /dev/null @@ -1,32 +0,0 @@ -{ - "predef": [ - "document", - "window", - "-Promise" - ], - "browser": true, - "boss": true, - "curly": true, - "debug": false, - "devel": true, - "eqeqeq": true, - "evil": true, - "forin": false, - "immed": false, - "laxbreak": false, - "newcap": true, - "noarg": true, - "noempty": false, - "nonew": false, - "nomen": false, - "onevar": false, - "plusplus": false, - "regexp": false, - "undef": true, - "sub": true, - "strict": false, - "white": false, - "eqnull": true, - "esversion": 6, - "unused": true -} diff --git a/README.md b/README.md index 19ad5f2..0a7c0a4 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,10 @@ ember install ember-credit-cards Usage (Components) ------------------------------------------------------------------------------ -### credit-card-form +### CreditCardForm Full credit card form with validations and formatting. -Attributes: +Arguments: * number * name * month @@ -41,47 +41,47 @@ Attributes: * zipcodeRequired Events: + * onUpdate * onValidate Example: -``` html -//templates/credit-cards/new.hbs - -
- {{ credit-card-form - number=attrs.number - name=attrs.name - month=attrs.month - year=attrs.year - cvc=attrs.cvc - onValidate=(mut disabled) - }} -
- - - +``` hbs + +
+ +
+ + ``` -### input-credit-card-number +### `` Formats credit card number on entry. Discards non-numeric and extra characters. Parses sets number attribute. Attributes: * number -### input-credit-card-cvc +### `` Formats cvc number on entry. Discards non-numeric and extra characters. Parses sets cvc attribute. Attributes: * cvc -### input-credit-card-expiration +### `` Validates and formats expiration date. Discards non-numeric and extra characters. Parses and sets month, year attributes. @@ -90,7 +90,7 @@ Attributes: * year -### input-credit-card-zipcode +### `` Validates and formats zip code. Discards non-numeric and extra characters. Sets zipcode attribute. @@ -175,26 +175,23 @@ validations.validateZipcode('94611-24'); //=> false ## Custom Labels - You can provide custom labels for localization. -``` html -
- {{ - credit-card-form - number=ccNumber - name=ccName - month=ccMonth - year=ccYear - cvc=ccCvc - numberLabel=(t 'credit-card-form.number') - securityCodeLabel=(t 'credit-card-form.security-code') - nameOnCardLabel=(t 'credit-card-form.name-on-card') - expirationLabel=(t 'credit-card-form.expiration') - zipCodeLabel=(t 'credit-card-form.zip-code') - on-validate='ccValidate' - }} -
+``` hbs + ``` Contributing diff --git a/addon/components/credit-card-form.hbs b/addon/components/credit-card-form.hbs new file mode 100644 index 0000000..22ca59f --- /dev/null +++ b/addon/components/credit-card-form.hbs @@ -0,0 +1,56 @@ +
+
+
+ + +
+ +
+ + +
+
+ +
+
+ + {{!-- template-lint-disable require-input-label --}} + +
+ +
+ + +
+
+ + {{#if @zipcodeRequired}} +
+ + +
+ {{/if}} + + +
+ {{this.type}} +
+
diff --git a/addon/components/credit-card-form.js b/addon/components/credit-card-form.js index 690ed96..bbe1d72 100644 --- a/addon/components/credit-card-form.js +++ b/addon/components/credit-card-form.js @@ -1,81 +1,59 @@ -/* eslint-disable ember/require-tagless-components */ -/* eslint-disable ember/no-classic-components */ -/* eslint-disable ember/no-classic-classes */ -/* eslint-disable ember/no-observers */ - -import { and } from '@ember/object/computed'; -import Component from '@ember/component'; -import { computed, observer } from '@ember/object'; +import Component from '@glimmer/component'; +import { action } from '@ember/object'; import Validations from 'ember-credit-cards/utils/validations'; import Cards from 'ember-credit-cards/utils/cards'; -export default Component.extend({ - tagName: 'form', - classNames: ['credit-card-form'], - classNameBindings: ['isValid'], - name: null, - number: null, - month: null, - year: null, - cvc: null, - zipcode: null, - zipcodeRequired: false, - onValidate() {}, - - isValid: and( - 'nameValid', - 'numberValid', - 'expirationValid', - 'cvcValid', - 'zipcodeValid' - ), - - becameValid: observer('isValid', function () { - this.onValidate(this.isValid); - }), - - nameValid: computed('name', function () { - var name = this.name; +export default class CreditCardFormComponent extends Component { + get isValid() { + return ( + this.nameValid && + this.numberValid && + this.expirationValid && + this.cvcValid && + this.zipcodeValid + ); + } + + get nameValid() { + var name = this.args.name; if (name) { return true; } return false; - }), - - numberValid: computed('number', function () { - var number = this.number; + } - return Validations.validateNumber(number); - }), + get numberValid() { + return Validations.validateNumber(this.args.number); + } - expirationValid: computed('month', 'year', function () { - var month = this.month; - var year = this.year; + get expirationValid() { + var month = this.args.month; + var year = this.args.year; return Validations.validateExpiration(month, year); - }), + } - cvcValid: computed('cvc', 'type', function () { - var cvc = this.cvc; + get cvcValid() { + var cvc = this.args.cvc; var type = this.type; return Validations.validateCVC(cvc, type); - }), + } - zipcodeValid: computed('zipcodeRequired', 'zipcode', function () { - if (this.zipcodeRequired) { - var zip = this.zipcode; + get zipcodeValid() { + if (this.args.zipcodeRequired) { + var zip = this.args.zipcode; return Validations.validateZipcode(zip); } return true; - }), + } - type: computed('number', function () { - var number = this.number; + get type() { + var number = this.args.number; var card = Cards.fromNumber(number); if (card) { @@ -83,5 +61,15 @@ export default Component.extend({ } else { return ''; } - }), -}); + } + + @action + setValue(key, value) { + this.args.onUpdate(key, value); + this._onValidate(); + } + + _onValidate() { + (this.args.onValidate || (() => {}))(this.isValid); + } +} diff --git a/addon/components/input-credit-card-cvc.hbs b/addon/components/input-credit-card-cvc.hbs new file mode 100644 index 0000000..2404d5f --- /dev/null +++ b/addon/components/input-credit-card-cvc.hbs @@ -0,0 +1,8 @@ + diff --git a/addon/components/input-credit-card-cvc.js b/addon/components/input-credit-card-cvc.js index bd8027e..1fd9c16 100644 --- a/addon/components/input-credit-card-cvc.js +++ b/addon/components/input-credit-card-cvc.js @@ -1,42 +1,37 @@ -/* eslint-disable ember/no-classic-classes */ -import TextField from '@ember/component/text-field'; -import { computed } from '@ember/object'; +import Component from '@glimmer/component'; +import { action } from '@ember/object'; import hasTextSelected from 'ember-credit-cards/utils/has-text-selected'; +import formatters from 'ember-credit-cards/utils/formatters'; import isDigitKeypress from 'ember-credit-cards/utils/is-digit-keypress'; import isWhitelistKeypress from 'ember-credit-cards/utils/is-whitelist-keypress'; -export default TextField.extend({ - classNames: ['input-credit-card-cvc'], - autocomplete: 'cc-csc', - placeholder: '•••', - label: 'Expiration', - type: 'tel', +function inputValid(value) { + return value.length <= 4; +} - keyPress: function (e) { +export default class InputCreditCardCvcComponent extends Component { + get cvc() { + return formatters.formatCvc(this.args.cvc); + } + + set cvc(value) { + this.args.onUpdate(value); + } + + @action + keyPress(e) { var digit = String.fromCharCode(e.which); if (!isDigitKeypress(e)) { return false; } - if (hasTextSelected(this.element)) { + if (hasTextSelected(e.target)) { return true; } - var value = this.element.value + digit; - - return isWhitelistKeypress(e) || value.length <= 4; - }, - - value: computed('cvc', { - get() { - return this.cvc; - }, - set(propertyName, newValue) { - var number = newValue.replace(/\D/g, '').slice(0, 4); - this.set('cvc', newValue); + var value = (this.args.cvc || '') + digit; - return number; - }, - }), -}); + return isWhitelistKeypress(e) || inputValid(value); + } +} diff --git a/addon/components/input-credit-card-expiration.hbs b/addon/components/input-credit-card-expiration.hbs new file mode 100644 index 0000000..5a02507 --- /dev/null +++ b/addon/components/input-credit-card-expiration.hbs @@ -0,0 +1,10 @@ + diff --git a/addon/components/input-credit-card-expiration.js b/addon/components/input-credit-card-expiration.js index 69a1cb9..7674d42 100644 --- a/addon/components/input-credit-card-expiration.js +++ b/addon/components/input-credit-card-expiration.js @@ -1,6 +1,6 @@ -/* eslint-disable ember/no-classic-classes */ -import TextField from '@ember/component/text-field'; -import { computed } from '@ember/object'; +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; import formatters from 'ember-credit-cards/utils/formatters'; import hasTextSelected from 'ember-credit-cards/utils/has-text-selected'; import isDigitKeypress from 'ember-credit-cards/utils/is-digit-keypress'; @@ -36,46 +36,45 @@ function parseInput(value) { return [mon, year]; } -export default TextField.extend({ - classNames: ['input-credit-card-expiration'], - month: null, - year: null, - placeholder: '•• / ••', - autocomplete: 'cc-exp', - type: 'tel', - required: true, +export default class InputCreditCardExpirationComponent extends Component { + @tracked + _value; - keyPress: function (e) { + constructor() { + super(...arguments); + this._value = formatters.formatExpiration(this.args.month, this.args.year); + } + + get value() { + return this._value; + } + + set value(value) { + var isBackspace = this._value.length - 1 === value.length; + var parsed = parseInput(value); + + var month = parsed[0]; + var year = parsed[1]; + + this._value = formatters.formatExpiration(month, year, isBackspace); + + this.args.onUpdateMonth(month); + this.args.onUpdateYear(year); + } + + @action + keyPress(e) { var digit = String.fromCharCode(e.which); if (!isDigitKeypress(e)) { return false; } - if (hasTextSelected(this.element)) { + if (hasTextSelected(e.target)) { return true; } - var value = this.element.value + digit; + var value = this._value + digit; return inputValid(value); - }, - - value: computed('month', 'year', { - get() { - return formatters.formatExpiration(this.month, this.year); - }, - set(key, value) { - var parsed = parseInput(value); - - var month = parsed[0]; - var year = parsed[1]; - - this.setProperties({ - month: month, - year: year, - }); - - return formatters.formatExpiration(month, year); - }, - }), -}); + } +} diff --git a/addon/components/input-credit-card-number.hbs b/addon/components/input-credit-card-number.hbs new file mode 100644 index 0000000..6ac1adb --- /dev/null +++ b/addon/components/input-credit-card-number.hbs @@ -0,0 +1,10 @@ + diff --git a/addon/components/input-credit-card-number.js b/addon/components/input-credit-card-number.js index ac40e33..c7710cb 100644 --- a/addon/components/input-credit-card-number.js +++ b/addon/components/input-credit-card-number.js @@ -1,6 +1,5 @@ -/* eslint-disable ember/no-classic-classes */ -import TextField from '@ember/component/text-field'; -import { computed } from '@ember/object'; +import Component from '@glimmer/component'; +import { action } from '@ember/object'; import hasTextSelected from 'ember-credit-cards/utils/has-text-selected'; import formatters from 'ember-credit-cards/utils/formatters'; import cards from 'ember-credit-cards/utils/cards'; @@ -20,34 +19,27 @@ function inputValid(value) { } } -export default TextField.extend({ - classNames: ['input-credit-card-number'], - placeholder: '•••• •••• •••• ••••', - autocomplete: 'cc-number', - type: 'tel', - required: true, +export default class InputCreditCardNumberComponent extends Component { + get number() { + return formatters.formatNumber(this.args.number); + } + + set number(value) { + this.args.onUpdate(value); + } - keyPress: function (e) { + @action + keyPress(e) { if (!isDigitKeypress(e)) { return false; } - if (hasTextSelected(this.element)) { + if (hasTextSelected(e.target)) { return true; } var digit = String.fromCharCode(e.which); - var value = this.element.value + digit; + var value = this.args.number + digit; return inputValid(value); - }, - - value: computed('number', { - get() { - return formatters.formatNumber(this.number); - }, - set(key, value) { - this.set('number', value); - return formatters.formatNumber(value); - }, - }), -}); + } +} diff --git a/addon/components/input-credit-card-zipcode.hbs b/addon/components/input-credit-card-zipcode.hbs new file mode 100644 index 0000000..98ad798 --- /dev/null +++ b/addon/components/input-credit-card-zipcode.hbs @@ -0,0 +1,9 @@ + diff --git a/addon/components/input-credit-card-zipcode.js b/addon/components/input-credit-card-zipcode.js index 9eff831..df4878a 100644 --- a/addon/components/input-credit-card-zipcode.js +++ b/addon/components/input-credit-card-zipcode.js @@ -1,38 +1,35 @@ -/* eslint-disable ember/no-classic-classes */ -import TextField from '@ember/component/text-field'; -import { computed } from '@ember/object'; +import Component from '@glimmer/component'; +import { action } from '@ember/object'; import hasTextSelected from 'ember-credit-cards/utils/has-text-selected'; import formatters from 'ember-credit-cards/utils/formatters'; import isDigitKeypress from 'ember-credit-cards/utils/is-digit-keypress'; -export default TextField.extend({ - type: 'tel', - classNames: ['input-credit-card-zipcode'], - autocomplete: 'none', - autocorrect: 'off', +function inputValid(value) { + return value.length <= 10; +} - keyPress: function (e) { +export default class InputCreditCardZipcodeComponent extends Component { + get zipcode() { + return formatters.formatZipcode(this.args.zipcode); + } + + set zipcode(value) { + this.args.onUpdate(value); + } + + @action + keyPress(e) { var digit = String.fromCharCode(e.which); if (!isDigitKeypress(e)) { return false; } - if (hasTextSelected(this.element)) { + if (hasTextSelected(e.target)) { return true; } - var value = this.element.value + digit; - return value.length <= 10; - }, - - value: computed('zipcode', { - get() { - return formatters.formatZipcode(this.zipcode); - }, - set(key, value) { - this.set('zipcode', value); - return formatters.formatZipcode(value); - }, - }), -}); + var value = this._zipcode + digit; + return inputValid(value); + } +} diff --git a/addon/utils/formatters.js b/addon/utils/formatters.js index 5e9ea16..ebb734a 100644 --- a/addon/utils/formatters.js +++ b/addon/utils/formatters.js @@ -37,7 +37,7 @@ function formatNumber(num) { } } -function formatExpiration(mon, year) { +function formatExpiration(mon, year, isBackspace) { var sep = ''; mon = mon || ''; @@ -47,13 +47,21 @@ function formatExpiration(mon, year) { mon = '0' + mon; } - if (mon.length === 2) { - sep = ' / '; + if (year !== '' || !isBackspace) { + if (mon.length === 2) { + sep = ' / '; + } } return mon + sep + year; } +function formatCvc(value) { + if (value) { + return value.toString().replace(/\D/g, '').slice(0, 4); + } +} + function formatZipcode(zip) { zip = zip || ''; @@ -71,5 +79,6 @@ function formatZipcode(zip) { export default { formatNumber: formatNumber, formatExpiration: formatExpiration, + formatCvc: formatCvc, formatZipcode: formatZipcode, }; diff --git a/addon/utils/is-whitelist-keypress.js b/addon/utils/is-whitelist-keypress.js index 6004be3..b83fa25 100644 --- a/addon/utils/is-whitelist-keypress.js +++ b/addon/utils/is-whitelist-keypress.js @@ -1,6 +1,10 @@ -import { A } from '@ember/array'; - -const validKeyCodes = A([9, 8, 46, 27, 13]); +const validKeyCodes = [ + 9, // Tab + 8, // Backspace + 46, // Delete + 27, // Escape + 13, // Enter +]; export default function isDigitKeypress(e) { var keyCode = e.keyCode || e.which; diff --git a/config/ember-try.js b/config/ember-try.js index 2612023..fd1aa7f 100644 --- a/config/ember-try.js +++ b/config/ember-try.js @@ -28,6 +28,10 @@ module.exports = async function () { devDependencies: { 'ember-source': await getChannelURL('release'), }, + dependencies: { + 'ember-auto-import': '^2.2.4', + webpack: '^5.64.4', + }, }, }, { @@ -36,6 +40,10 @@ module.exports = async function () { devDependencies: { 'ember-source': await getChannelURL('beta'), }, + dependencies: { + 'ember-auto-import': '^2.2.4', + webpack: '^5.64.4', + }, }, }, { @@ -44,6 +52,10 @@ module.exports = async function () { devDependencies: { 'ember-source': await getChannelURL('canary'), }, + dependencies: { + 'ember-auto-import': '^2.2.4', + webpack: '^5.64.4', + }, }, }, { diff --git a/tests/.jshintrc b/tests/.jshintrc deleted file mode 100644 index d2bd113..0000000 --- a/tests/.jshintrc +++ /dev/null @@ -1,52 +0,0 @@ -{ - "predef": [ - "document", - "window", - "location", - "setTimeout", - "$", - "-Promise", - "define", - "console", - "visit", - "exists", - "fillIn", - "click", - "keyEvent", - "triggerEvent", - "find", - "findWithAssert", - "wait", - "DS", - "andThen", - "currentURL", - "currentPath", - "currentRouteName" - ], - "node": false, - "browser": false, - "boss": true, - "curly": true, - "debug": false, - "devel": false, - "eqeqeq": true, - "evil": true, - "forin": false, - "immed": false, - "laxbreak": false, - "newcap": true, - "noarg": true, - "noempty": false, - "nonew": false, - "nomen": false, - "onevar": false, - "plusplus": false, - "regexp": false, - "undef": true, - "sub": true, - "strict": false, - "white": false, - "eqnull": true, - "esversion": 6, - "unused": true -} diff --git a/tests/dummy/app/controllers/application.js b/tests/dummy/app/controllers/application.js new file mode 100644 index 0000000..e20e8fc --- /dev/null +++ b/tests/dummy/app/controllers/application.js @@ -0,0 +1,25 @@ +import Controller from '@ember/controller'; +import { tracked } from '@glimmer/tracking'; +import { action } from '@ember/object'; + +export default class ApplicationController extends Controller { + @tracked + name; + + @tracked + number; + + @tracked + cvc; + + @tracked + month; + + @tracked + year; + + @action + setValue(key, value) { + this[key] = value; + } +} diff --git a/tests/dummy/app/index.html b/tests/dummy/app/index.html index 53ed12f..141e718 100644 --- a/tests/dummy/app/index.html +++ b/tests/dummy/app/index.html @@ -11,6 +11,7 @@ + {{content-for "head-footer"}} diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index fb1e016..6cfcae2 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -21,13 +21,21 @@
- + + {{this.name}}
-
diff --git a/tests/integration/components/credit-card-form-test.js b/tests/integration/components/credit-card-form-test.js index 16323df..fa02764 100644 --- a/tests/integration/components/credit-card-form-test.js +++ b/tests/integration/components/credit-card-form-test.js @@ -3,13 +3,27 @@ import { setupRenderingTest } from 'ember-qunit'; import hbs from 'htmlbars-inline-precompile'; import { render } from '@ember/test-helpers'; -module('credit-card-form', function (hooks) { +module('Integration | Component | credit-card-form', function (hooks) { setupRenderingTest(hooks); test('it should format Card labels correctly with default values', async function (assert) { assert.expect(5); - await render(hbs`{{credit-card-form zipcodeRequired=true}}`); + this.set('setValue', () => {}); + + await render( + hbs` + + ` + ); assert.equal( this.element.querySelector('.cc-number .control-label').innerHTML, @@ -41,11 +55,24 @@ module('credit-card-form', function (hooks) { ); }); - // tests for custom label - test('it should format Card Number label correctly with custom numberLabel provided', async function (assert) { await render( - hbs`{{credit-card-form zipcodeRequired=true numberLabel="Kaartnummer" securityCodeLabel="Veiligheidscode" nameOnCardLabel="Naam op Kaart" expirationLabel="Vervalt op" zipCodeLabel="postcode"}}` + hbs` + + ` ); assert.equal( diff --git a/tests/integration/components/input-credit-card-cvc-test.js b/tests/integration/components/input-credit-card-cvc-test.js index f07be3e..f872ffb 100644 --- a/tests/integration/components/input-credit-card-cvc-test.js +++ b/tests/integration/components/input-credit-card-cvc-test.js @@ -3,7 +3,7 @@ import { setupRenderingTest } from 'ember-qunit'; import hbs from 'htmlbars-inline-precompile'; import { render } from '@ember/test-helpers'; -module('input-credit-card-cvc', function (hooks) { +module('Integration | Component | input-credit-card-cvc', function (hooks) { setupRenderingTest(hooks); test('it renders', async function (assert) { @@ -11,7 +11,9 @@ module('input-credit-card-cvc', function (hooks) { this.set('cvc', 300); - await render(hbs`{{input-credit-card-cvc cvc=cvc class="form-control"}}`); + await render( + hbs`` + ); assert.equal(this.element.querySelector('.form-control').value, '300'); }); diff --git a/tests/integration/components/input-credit-card-expiration-test.js b/tests/integration/components/input-credit-card-expiration-test.js index e0b7590..d03cc37 100644 --- a/tests/integration/components/input-credit-card-expiration-test.js +++ b/tests/integration/components/input-credit-card-expiration-test.js @@ -3,58 +3,138 @@ import { setupRenderingTest } from 'ember-qunit'; import hbs from 'htmlbars-inline-precompile'; import { render, typeIn } from '@ember/test-helpers'; -module('input-credit-card-expiration', function (hooks) { - setupRenderingTest(hooks); +module( + 'Integration | Component | input-credit-card-expiration', + function (hooks) { + setupRenderingTest(hooks); - test('it renders', async function (assert) { - assert.expect(1); + test('it renders', async function (assert) { + assert.expect(1); - this.set('month', 10); - this.set('year', 2019); + this.set('month', 10); + this.set('year', 2019); + this.set('setMonth', (month) => { + this.set('month', month); + }); + this.set('setYear', (year) => { + this.set('year', year); + }); - await render(hbs`{{input-credit-card-expiration month=month year=year }}`); + await render( + hbs` + + ` + ); - assert.equal(this.element.querySelector('input').value, '102019'); - }); + assert.equal(this.element.querySelector('input').value, '102019'); + }); - test('should format month shorthand correctly', async function (assert) { - assert.expect(1); + test('should format month shorthand correctly', async function (assert) { + assert.expect(1); - await render(hbs`{{input-credit-card-expiration}}`); + this.set('setMonth', (month) => { + this.set('month', month); + }); + this.set('setYear', (year) => { + this.set('year', year); + }); - await typeIn('input', '4'); + await render( + hbs` + + ` + ); - assert.equal(this.element.querySelector('input').value, '04 / '); - }); + await typeIn('input', '4'); - test('should format forward slash shorthand correctly', async function (assert) { - assert.expect(1); - this.set('month', 8); - await render(hbs`{{input-credit-card-expiration month=month}}`); - await typeIn('input', '/'); + assert.equal(this.element.querySelector('input').value, '04 / '); + }); - assert.equal(this.element.querySelector('input').value, '08 / '); - }); + test('should format forward slash shorthand correctly', async function (assert) { + assert.expect(1); + this.set('month', 8); + this.set('setMonth', (month) => { + this.set('month', month); + }); + this.set('setYear', (year) => { + this.set('year', year); + }); - test('should only allow numbers', async function (assert) { - assert.expect(3); - this.set('month', ''); - this.set('year', ''); - await render(hbs`{{input-credit-card-expiration month=month year=year}}`); - await typeIn('input', '4'); - assert.equal(this.element.querySelector('input').value, '04 / '); - await typeIn('input', 'd'); + await render( + hbs` + + ` + ); + await typeIn('input', '/'); - assert.equal(this.month, '04'); - assert.equal(this.year, ''); - }); + assert.equal(this.element.querySelector('input').value, '08 / '); + }); - test('should only allow six numbers', async function (assert) { - assert.expect(1); - this.set('month', '4'); - this.set('year', '2019'); - await render(hbs`{{input-credit-card-expiration month=month year=year}}`); + test('should only allow numbers', async function (assert) { + assert.expect(3); + this.set('month', ''); + this.set('year', ''); + this.set('setMonth', (month) => { + this.set('month', month); + }); + this.set('setYear', (year) => { + this.set('year', year); + }); + await render( + hbs` + + ` + ); + await typeIn('input', '4'); + assert.equal(this.element.querySelector('input').value, '04 / '); + await typeIn('input', 'd'); - assert.equal(this.element.querySelector('input').value, '04 / 2019'); - }); -}); + assert.equal(this.month, '04'); + assert.equal(this.year, ''); + }); + + test('should only allow six numbers', async function (assert) { + assert.expect(1); + this.set('month', '4'); + this.set('year', '2019'); + this.set('setMonth', (month) => { + this.set('month', month); + }); + this.set('setYear', (year) => { + this.set('year', year); + }); + await render( + hbs` + + ` + ); + + assert.equal(this.element.querySelector('input').value, '04 / 2019'); + }); + } +); diff --git a/tests/integration/components/input-credit-card-number-test.js b/tests/integration/components/input-credit-card-number-test.js index 6a5cc8d..45720c0 100644 --- a/tests/integration/components/input-credit-card-number-test.js +++ b/tests/integration/components/input-credit-card-number-test.js @@ -3,13 +3,18 @@ import { setupRenderingTest } from 'ember-qunit'; import hbs from 'htmlbars-inline-precompile'; import { render, typeIn } from '@ember/test-helpers'; -module('input-credit-card-number', function (hooks) { +module('Integration | Component | input-credit-card-number', function (hooks) { setupRenderingTest(hooks); test('it should format cc number correctly', async function (assert) { assert.expect(2); this.set('number', '42424'); - await render(hbs`{{input-credit-card-number number=number}}`); + this.set('onUpdate', (value) => { + this.set('number', value); + }); + await render( + hbs`` + ); assert.equal(this.element.querySelector('input').value, '4242 4'); await typeIn('input', '5'); assert.equal(this.element.querySelector('input').value, '4242 45'); diff --git a/tests/integration/components/input-credit-card-zipcode-test.js b/tests/integration/components/input-credit-card-zipcode-test.js index 6bfbf1d..976ed29 100644 --- a/tests/integration/components/input-credit-card-zipcode-test.js +++ b/tests/integration/components/input-credit-card-zipcode-test.js @@ -3,13 +3,15 @@ import { setupRenderingTest } from 'ember-qunit'; import hbs from 'htmlbars-inline-precompile'; import { render } from '@ember/test-helpers'; -module('input-credit-card-zipcode', function (hooks) { +module('Integration | Component | input-credit-card-zipcode', function (hooks) { setupRenderingTest(hooks); test('should accept 9 digits ', async function (assert) { assert.expect(1); this.set('zipcode', '946062370'); - await render(hbs`{{input-credit-card-zipcode zipcode=zipcode}}`); + await render(hbs` + + `); assert.equal(this.element.querySelector('input').value, '94606-2370'); }); }); diff --git a/tests/unit/utils/cards-test.js b/tests/unit/utils/cards-test.js index 1179197..709b2a0 100644 --- a/tests/unit/utils/cards-test.js +++ b/tests/unit/utils/cards-test.js @@ -1,7 +1,7 @@ import cards from 'ember-credit-cards/utils/cards'; import { module, test } from 'qunit'; -module('cards', function () { +module('Unit | Utility | cards', function () { test('should return Visa that begins with 40', function (assert) { assert.equal(cards.cardType('4012121212121212'), 'visa'); }); diff --git a/tests/unit/utils/formatters-test.js b/tests/unit/utils/formatters-test.js index 42bec29..2913b7a 100644 --- a/tests/unit/utils/formatters-test.js +++ b/tests/unit/utils/formatters-test.js @@ -1,7 +1,7 @@ import formatters from 'ember-credit-cards/utils/formatters'; import { module, test } from 'qunit'; -module('formatters', function () { +module('Unit | Utility | formatters', function () { module('formatExpiration', function () { test('it should format incomplete date', function (assert) { var result = formatters.formatExpiration('2'); @@ -12,6 +12,11 @@ module('formatters', function () { var result = formatters.formatExpiration('12', '2010'); assert.equal(result, '12 / 2010'); }); + + test('it should handle backspace', function (assert) { + var result = formatters.formatExpiration('12', '', true); + assert.equal(result, '12'); + }); }); module('formatNumber', function () { diff --git a/tests/unit/utils/validations-test.js b/tests/unit/utils/validations-test.js index 3e15989..618da7c 100644 --- a/tests/unit/utils/validations-test.js +++ b/tests/unit/utils/validations-test.js @@ -1,7 +1,7 @@ import validations from 'ember-credit-cards/utils/validations'; import { module, test } from 'qunit'; -module('validations', function () { +module('Unit | Utility | validations', function () { test('Validating a card number', function (assert) { var validate = validations.validateNumber;