From 2e69bcd615912c9416c8e3a4d49e33bf4f098ca5 Mon Sep 17 00:00:00 2001 From: Christopher Rogers Date: Tue, 6 Feb 2018 11:58:28 -0700 Subject: [PATCH] Adds additional i18n for ApplePay line item labels Signed-off-by: Christopher Rogers --- karma.conf.js | 1 + lib/recurly/apple-pay.js | 27 +++++++++------ test/apple-pay.test.js | 73 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 88 insertions(+), 13 deletions(-) diff --git a/karma.conf.js b/karma.conf.js index 793f43b64..07aae5e91 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -20,6 +20,7 @@ var staticConfig = { autoWatch: true, browsers: [ 'PhantomJS' + // 'ChromeDebug' // 'IE11 - Win7' ], singleRun: true, diff --git a/lib/recurly/apple-pay.js b/lib/recurly/apple-pay.js index 3740470a7..06a785701 100644 --- a/lib/recurly/apple-pay.js +++ b/lib/recurly/apple-pay.js @@ -2,6 +2,7 @@ import Emitter from 'component-emitter'; import errors from '../errors'; import {Pricing} from './pricing'; import {normalize} from '../util/normalize'; +import decimalize from '../util/decimalize'; import {FIELDS} from './token'; const debug = require('debug')('recurly:apple-pay'); @@ -19,7 +20,11 @@ const APPLE_PAY_ADDRESS_MAP = { }; const I18N = { - authorizationLineItemLabel: 'Card Authorization (Temporary)' + authorizationLineItemLabel: 'Card Authorization (Temporary)', + subtotalLineItemLabel: 'Subtotal', + discountLineItemLabel: 'Discount', + taxLineItemLabel: 'Tax', + giftCardLineItemLabel: 'Gift card' }; /** @@ -160,6 +165,11 @@ class ApplePay extends Emitter { // Initialize with no line items this.config.lineItems = []; + if ('recurly' in options) this.recurly = options.recurly; + else return this.initError = this.error('apple-pay-factory-only'); + + if ('i18n' in options) Object.assign(this.config.i18n, options.i18n); + // Listen for pricing changes to update totals and currency const { pricing } = options; if (pricing instanceof Pricing) { @@ -172,11 +182,6 @@ class ApplePay extends Emitter { return this.initError = this.error('apple-pay-config-missing', { opt: 'total' }); } - if ('recurly' in options) this.recurly = options.recurly; - else return this.initError = this.error('apple-pay-factory-only'); - - if ('i18n' in options) Object.assign(this.config.i18n, options.i18n); - // Retrieve remote configuration this.recurly.request('get', '/apple_pay/info', (err, info) => { if (err) return this.initError = this.error(err); @@ -232,18 +237,18 @@ class ApplePay extends Emitter { if (!pricing.hasPrice) return; let taxAmount = pricing.price.now.taxes || pricing.price.now.tax; - lineItems.push(lineItem('Subtotal', pricing.subtotalPreDiscountNow)); + lineItems.push(lineItem(this.config.i18n.subtotalLineItemLabel, pricing.subtotalPreDiscountNow)); if (+pricing.price.now.discount) { - lineItems.push(lineItem('Discount', -pricing.price.now.discount)); + lineItems.push(lineItem(this.config.i18n.discountLineItemLabel, -pricing.price.now.discount)); } if (+taxAmount) { - lineItems.push(lineItem('Tax', taxAmount)); + lineItems.push(lineItem(this.config.i18n.taxLineItemLabel, taxAmount)); } if (+pricing.price.now.giftCard) { - lineItems.push(lineItem('Gift card', -pricing.price.now.giftCard)); + lineItems.push(lineItem(this.config.i18n.giftCardLineItemLabel, -pricing.price.now.giftCard)); } this.config.lineItems = lineItems; @@ -395,5 +400,5 @@ class ApplePay extends Emitter { * @return {object} */ function lineItem (label = '', amount = 0) { - return { label, amount }; + return { label, amount: decimalize(amount) }; } diff --git a/test/apple-pay.test.js b/test/apple-pay.test.js index 9252d0bb3..fd6373864 100644 --- a/test/apple-pay.test.js +++ b/test/apple-pay.test.js @@ -114,8 +114,8 @@ apiTest(function (requestMethod) { describe('when given options.pricing', function () { beforeEach(function () { - let pricing = this.pricing = this.recurly.Pricing(); - this.applePay = this.recurly.ApplePay(merge({}, validOpts, { pricing })) + let pricing = this.pricing = this.recurly.Pricing.Checkout(); + this.applePay = this.recurly.ApplePay(merge({}, validOpts, { pricing })); }); it('binds a pricing instance', function (done) { @@ -131,6 +131,75 @@ apiTest(function (requestMethod) { done(); }); }); + + describe('when the pricing instance includes several items', () => { + beforeEach(function (done) { + this.subscription = this.recurly.Pricing.Subscription() + .plan('basic') + .address({ country: 'US', postalCode: '94117' }) + .done(() => { + this.pricing + .subscription(this.subscription) + .adjustment({ amount: 100 }) + .coupon('coop') + .giftCard('super-gift-card') + .done(() => done()); + }); + }); + + it('includes relevant line items', function () { + const subtotal = this.applePay.lineItems[0]; + const discount = this.applePay.lineItems[1]; + const giftCard = this.applePay.lineItems[2]; + const total = this.applePay.totalLineItem; + assert.equal(this.applePay.lineItems.length, 3); + assert.strictEqual(subtotal.label, this.applePay.config.i18n.subtotalLineItemLabel); + assert.strictEqual(discount.label, this.applePay.config.i18n.discountLineItemLabel); + assert.strictEqual(giftCard.label, this.applePay.config.i18n.giftCardLineItemLabel); + assert.strictEqual(subtotal.amount, '121.99'); + assert.strictEqual(discount.amount, '-20.00'); + assert.strictEqual(giftCard.amount, '-20.00'); + assert.strictEqual(total.amount, '81.99'); + }); + + describe('when the line item labels are customized', () => { + beforeEach(function () { + const pricing = this.pricing; + const i18n = this.exampleI18n = { + authorizationLineItemLabel: 'Custom card authorization label', + subtotalLineItemLabel: 'Custom subtotal label', + discountLineItemLabel: 'Custom discount label', + taxLineItemLabel: 'Custom tax label', + giftCardLineItemLabel: 'Custom Gift card label' + }; + this.applePay = this.recurly.ApplePay(merge({}, validOpts, { pricing, i18n })); + }); + + it('displays those labels', function () { + const subtotal = this.applePay.lineItems[0]; + const discount = this.applePay.lineItems[1]; + const giftCard = this.applePay.lineItems[2]; + assert.equal(subtotal.label, this.exampleI18n.subtotalLineItemLabel); + assert.equal(discount.label, this.exampleI18n.discountLineItemLabel); + assert.equal(giftCard.label, this.exampleI18n.giftCardLineItemLabel); + }); + }); + + describe('when the total price is zero', () => { + beforeEach(function (done) { + this.pricing.coupon('coop-fixed-all-500').done(() => done()); + }); + + it('adds an authorization line item', function () { + assert.strictEqual(this.applePay.totalLineItem.amount, '0.00'); + this.applePay.begin(); + const authorization = this.applePay.lineItems[2]; + assert.strictEqual(authorization.label, this.applePay.config.i18n.authorizationLineItemLabel); + assert.strictEqual(authorization.amount, '1.00'); + assert.strictEqual(this.applePay.totalLineItem.amount, '1.00'); + }); + }); + }); }); it('requires a valid country', function (done) {