diff --git a/services/web/app/src/Features/Subscription/SubscriptionFormatters.js b/services/web/app/src/Features/Subscription/SubscriptionFormatters.js index 8bdfc2a060..1953f337fa 100644 --- a/services/web/app/src/Features/Subscription/SubscriptionFormatters.js +++ b/services/web/app/src/Features/Subscription/SubscriptionFormatters.js @@ -1,21 +1,4 @@ const dateformat = require('dateformat') -const { formatCurrency } = require('../../util/currency') - -/** - * @param {number} priceInCents - price in the smallest currency unit (e.g. dollar cents, CLP units, ...) - * @param {CurrencyCode?} currency - currency code (default to USD) - * @param {string} [locale] - locale string - * @returns {string} - formatted price - */ -function formatPriceLocalized(priceInCents, currency = 'USD', locale) { - const isNoCentsCurrency = ['CLP', 'JPY', 'KRW', 'VND'].includes(currency) - - const priceInCurrencyUnit = isNoCentsCurrency - ? priceInCents - : priceInCents / 100 - - return formatCurrency(priceInCurrencyUnit, currency, locale) -} function formatDateTime(date) { if (!date) { @@ -32,7 +15,6 @@ function formatDate(date) { } module.exports = { - formatPriceLocalized, formatDateTime, formatDate, } diff --git a/services/web/app/src/Features/Subscription/SubscriptionViewModelBuilder.js b/services/web/app/src/Features/Subscription/SubscriptionViewModelBuilder.js index 309678cb77..752eb5df98 100644 --- a/services/web/app/src/Features/Subscription/SubscriptionViewModelBuilder.js +++ b/services/web/app/src/Features/Subscription/SubscriptionViewModelBuilder.js @@ -284,7 +284,6 @@ async function buildUsersSubscriptionViewModel(user, locale = 'en') { }) const totalLicenses = (plan.membersLimit || 0) + additionalLicenses personalSubscription.recurly = { - tax, taxRate, billingDetailsLink: buildHostedLink('billing-details'), accountManagementLink: buildHostedLink('account-management'), @@ -346,11 +345,6 @@ async function buildUsersSubscriptionViewModel(user, locale = 'en') { recurlySubscription.currency, locale ) - personalSubscription.recurly.currentPlanDisplayPrice = formatCurrency( - recurlySubscription.planPrice + addOnPrice + tax, - recurlySubscription.currency, - locale - ) personalSubscription.recurly.planOnlyDisplayPrice = getPlanOnlyDisplayPrice( totalPrice, diff --git a/services/web/test/frontend/features/subscription/fixtures/subscriptions.ts b/services/web/test/frontend/features/subscription/fixtures/subscriptions.ts index 4c9fe5f51d..62597e395e 100644 --- a/services/web/test/frontend/features/subscription/fixtures/subscriptions.ts +++ b/services/web/test/frontend/features/subscription/fixtures/subscriptions.ts @@ -34,7 +34,6 @@ export const annualActiveSubscription: RecurlySubscription = { featureDescription: [], }, recurly: { - tax: 0, taxRate: 0, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', @@ -75,7 +74,6 @@ export const annualActiveSubscriptionEuro: RecurlySubscription = { featureDescription: [], }, recurly: { - tax: 4296, taxRate: 0.24, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', @@ -115,7 +113,6 @@ export const annualActiveSubscriptionPro: RecurlySubscription = { featureDescription: [], }, recurly: { - tax: 0, taxRate: 0, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', @@ -156,7 +153,6 @@ export const pastDueExpiredSubscription: RecurlySubscription = { featureDescription: [], }, recurly: { - tax: 0, taxRate: 0, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', @@ -197,7 +193,6 @@ export const canceledSubscription: RecurlySubscription = { featureDescription: [], }, recurly: { - tax: 0, taxRate: 0, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', @@ -238,7 +233,6 @@ export const pendingSubscriptionChange: RecurlySubscription = { featureDescription: [], }, recurly: { - tax: 0, taxRate: 0, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', @@ -290,7 +284,6 @@ export const groupActiveSubscription: GroupSubscription = { membersLimitAddOn: 'additional-license', }, recurly: { - tax: 0, taxRate: 0, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', @@ -336,7 +329,6 @@ export const groupActiveSubscriptionWithPendingLicenseChange: GroupSubscription membersLimitAddOn: 'additional-license', }, recurly: { - tax: 0, taxRate: 0, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', @@ -352,7 +344,6 @@ export const groupActiveSubscriptionWithPendingLicenseChange: GroupSubscription accountEmail: 'fake@example.com', hasPastDueInvoice: false, displayPrice: '$2967.00', - currentPlanDisplayPrice: '$2709.00', pendingAdditionalLicenses: 13, pendingTotalLicenses: 23, planOnlyDisplayPrice: '', @@ -390,7 +381,6 @@ export const trialSubscription: RecurlySubscription = { hideFromUsers: true, }, recurly: { - tax: 0, taxRate: 0, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', @@ -452,7 +442,6 @@ export const trialCollaboratorSubscription: RecurlySubscription = { hideFromUsers: true, }, recurly: { - tax: 0, taxRate: 0, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', @@ -492,7 +481,6 @@ export const monthlyActiveCollaborator: RecurlySubscription = { featureDescription: [], }, recurly: { - tax: 0, taxRate: 0, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: '/user/subscription/recurly/account-management', diff --git a/services/web/test/frontend/shared/utils/currency.test.js b/services/web/test/frontend/shared/utils/currency.test.js new file mode 100644 index 0000000000..757b56ad2a --- /dev/null +++ b/services/web/test/frontend/shared/utils/currency.test.js @@ -0,0 +1,316 @@ +import { expect } from 'chai' +import { formatCurrency } from '../../../../frontend/js/shared/utils/currency' + +/* + Users can select any language we support, regardless of the country where they are located. + Which mean that any combination of "supported language"-"supported currency" can be displayed + on the user's screen. + + Users located in the USA visiting https://fr.overleaf.com/user/subscription/plans + should see amounts in USD (because of their IP address), + but with French text, number formatting and currency formats (because of language choice). + (e.g. 1 000,00 $) + + Users located in the France visiting https://www.overleaf.com/user/subscription/plans + should see amounts in EUR (because of their IP address), + but with English text, number formatting and currency formats (because of language choice). + (e.g. €1,000.00) + */ + +describe('formatCurrency', function () { + describe('en', function () { + const format = currency => priceInCents => + formatCurrency(priceInCents, currency) + + describe('USD', function () { + const formatUSD = format('USD') + + it('should format basic amounts', function () { + expect(formatUSD(0)).to.equal('$0.00') + expect(formatUSD(12.34)).to.equal('$12.34') + expect(formatUSD(123)).to.equal('$123.00') + }) + + it('should format thousand separators', function () { + expect(formatUSD(1_000)).to.equal('$1,000.00') + expect(formatUSD(98_765_432.1)).to.equal('$98,765,432.10') + }) + + it('should format negative amounts', function () { + expect(formatUSD(-0.01)).to.equal('-$0.01') + expect(formatUSD(-12.34)).to.equal('-$12.34') + expect(formatUSD(-123)).to.equal('-$123.00') + }) + }) + + describe('EUR', function () { + const formatEUR = format('EUR') + + it('should format basic amounts', function () { + expect(formatEUR(0)).to.equal('€0.00') + expect(formatEUR(12.34)).to.equal('€12.34') + expect(formatEUR(123)).to.equal('€123.00') + }) + + it('should format thousand separators', function () { + expect(formatEUR(1_000)).to.equal('€1,000.00') + expect(formatEUR(98_765_432.1)).to.equal('€98,765,432.10') + }) + + it('should format negative amounts', function () { + expect(formatEUR(-0.01)).to.equal('-€0.01') + expect(formatEUR(-12.34)).to.equal('-€12.34') + expect(formatEUR(-123)).to.equal('-€123.00') + }) + }) + + describe('HUF', function () { + const formatHUF = format('HUF') + + it('should format basic amounts', function () { + expect(formatHUF(0)).to.equal('Ft 0.00') + expect(formatHUF(12.34)).to.equal('Ft 12.34') + expect(formatHUF(123)).to.equal('Ft 123.00') + }) + + it('should format thousand separators', function () { + expect(formatHUF(1_000)).to.equal('Ft 1,000.00') + expect(formatHUF(98_765_432.1)).to.equal('Ft 98,765,432.10') + }) + + it('should format negative amounts', function () { + expect(formatHUF(-0.01)).to.equal('-Ft 0.01') + expect(formatHUF(-12.34)).to.equal('-Ft 12.34') + expect(formatHUF(-123)).to.equal('-Ft 123.00') + }) + }) + + describe('CLP', function () { + const formatCLP = format('CLP') + + it('should format basic amounts', function () { + expect(formatCLP(0)).to.equal('$0') + expect(formatCLP(12.34)).to.equal('$12') + expect(formatCLP(123)).to.equal('$123') + expect(formatCLP(1234)).to.equal('$1,234') + }) + + it('should format thousand separators', function () { + expect(formatCLP(1_000)).to.equal('$1,000') + expect(formatCLP(98_765_432.1)).to.equal('$98,765,432') + }) + + it('should format negative amounts', function () { + expect(formatCLP(-1)).to.equal('-$1') + expect(formatCLP(-12.34)).to.equal('-$12') + expect(formatCLP(-1234)).to.equal('-$1,234') + }) + }) + + describe('all currencies', function () { + it('should format 1 "minimal atomic units"', function () { + const amount = 1 + + // "no cents currencies" + expect(format('CLP')(amount)).to.equal('$1') + expect(format('JPY')(amount)).to.equal('¥1') + expect(format('KRW')(amount)).to.equal('₩1') + expect(format('VND')(amount)).to.equal('₫1') + + // other currencies + expect(format('AUD')(amount)).to.equal('$1.00') + expect(format('BRL')(amount)).to.equal('R$1.00') + expect(format('CAD')(amount)).to.equal('$1.00') + expect(format('CHF')(amount)).to.equal('CHF 1.00') + expect(format('CNY')(amount)).to.equal('¥1.00') + expect(format('COP')(amount)).to.equal('$1.00') + expect(format('DKK')(amount)).to.equal('kr 1.00') + expect(format('EUR')(amount)).to.equal('€1.00') + expect(format('GBP')(amount)).to.equal('£1.00') + expect(format('HUF')(amount)).to.equal('Ft 1.00') + expect(format('IDR')(amount)).to.equal('Rp 1.00') + expect(format('INR')(amount)).to.equal('₹1.00') + expect(format('MXN')(amount)).to.equal('$1.00') + expect(format('MYR')(amount)).to.equal('RM 1.00') + expect(format('NOK')(amount)).to.equal('kr 1.00') + expect(format('NZD')(amount)).to.equal('$1.00') + expect(format('PEN')(amount)).to.equal('PEN 1.00') + expect(format('PHP')(amount)).to.equal('₱1.00') + expect(format('SEK')(amount)).to.equal('kr 1.00') + expect(format('SGD')(amount)).to.equal('$1.00') + expect(format('THB')(amount)).to.equal('฿1.00') + expect(format('USD')(amount)).to.equal('$1.00') + }) + + it('should format 1_234_567.897_654 "minimal atomic units"', function () { + const amount = 1_234_567.897_654 + + // "no cents currencies" + expect(format('CLP')(amount)).to.equal('$1,234,568') + expect(format('JPY')(amount)).to.equal('¥1,234,568') + expect(format('KRW')(amount)).to.equal('₩1,234,568') + expect(format('VND')(amount)).to.equal('₫1,234,568') + + // other currencies + expect(format('AUD')(amount)).to.equal('$1,234,567.90') + expect(format('BRL')(amount)).to.equal('R$1,234,567.90') + expect(format('CAD')(amount)).to.equal('$1,234,567.90') + expect(format('CHF')(amount)).to.equal('CHF 1,234,567.90') + expect(format('CNY')(amount)).to.equal('¥1,234,567.90') + expect(format('COP')(amount)).to.equal('$1,234,567.90') + expect(format('DKK')(amount)).to.equal('kr 1,234,567.90') + expect(format('EUR')(amount)).to.equal('€1,234,567.90') + expect(format('GBP')(amount)).to.equal('£1,234,567.90') + expect(format('HUF')(amount)).to.equal('Ft 1,234,567.90') + expect(format('IDR')(amount)).to.equal('Rp 1,234,567.90') + expect(format('INR')(amount)).to.equal('₹1,234,567.90') + expect(format('MXN')(amount)).to.equal('$1,234,567.90') + expect(format('MYR')(amount)).to.equal('RM 1,234,567.90') + expect(format('NOK')(amount)).to.equal('kr 1,234,567.90') + expect(format('NZD')(amount)).to.equal('$1,234,567.90') + expect(format('PEN')(amount)).to.equal('PEN 1,234,567.90') + expect(format('PHP')(amount)).to.equal('₱1,234,567.90') + expect(format('SEK')(amount)).to.equal('kr 1,234,567.90') + expect(format('SGD')(amount)).to.equal('$1,234,567.90') + expect(format('THB')(amount)).to.equal('฿1,234,567.90') + expect(format('USD')(amount)).to.equal('$1,234,567.90') + }) + }) + }) + + describe('fr', function () { + const format = currency => priceInCents => + formatCurrency(priceInCents, currency, 'fr') + + describe('USD', function () { + const formatUSD = format('USD') + + it('should format basic amounts', function () { + expect(formatUSD(0)).to.equal('0,00 $') + expect(formatUSD(12.34)).to.equal('12,34 $') + expect(formatUSD(123)).to.equal('123,00 $') + }) + + it('should format thousand separators', function () { + expect(formatUSD(1_000)).to.equal('1 000,00 $') + expect(formatUSD(98_765_432.1)).to.equal('98 765 432,10 $') + }) + + it('should format negative amounts', function () { + expect(formatUSD(-0.01)).to.equal('-0,01 $') + expect(formatUSD(-12.34)).to.equal('-12,34 $') + expect(formatUSD(-123)).to.equal('-123,00 $') + }) + }) + + describe('EUR', function () { + const formatEUR = format('EUR') + + it('should format basic amounts', function () { + expect(formatEUR(0)).to.equal('0,00 €') + expect(formatEUR(12.34)).to.equal('12,34 €') + expect(formatEUR(123)).to.equal('123,00 €') + }) + + it('should format thousand separators', function () { + expect(formatEUR(1_000)).to.equal('1 000,00 €') + expect(formatEUR(98_765_432.1)).to.equal('98 765 432,10 €') + }) + + it('should format negative amounts', function () { + expect(formatEUR(-0.01)).to.equal('-0,01 €') + expect(formatEUR(-12.34)).to.equal('-12,34 €') + expect(formatEUR(-123)).to.equal('-123,00 €') + }) + }) + + describe('HUF', function () { + const formatHUF = format('HUF') + + it('should format basic amounts', function () { + expect(formatHUF(0)).to.equal('0,00 Ft') + expect(formatHUF(12.34)).to.equal('12,34 Ft') + expect(formatHUF(123)).to.equal('123,00 Ft') + }) + + it('should format thousand separators', function () { + expect(formatHUF(1_000)).to.equal('1 000,00 Ft') + expect(formatHUF(98_765_432.1)).to.equal('98 765 432,10 Ft') + }) + + it('should format negative amounts', function () { + expect(formatHUF(-0.01)).to.equal('-0,01 Ft') + expect(formatHUF(-12.34)).to.equal('-12,34 Ft') + expect(formatHUF(-123)).to.equal('-123,00 Ft') + }) + }) + + describe('CLP', function () { + const formatCLP = format('CLP') + + it('should format basic amounts', function () { + expect(formatCLP(0)).to.equal('0 $') + expect(formatCLP(12.34)).to.equal('12 $') + expect(formatCLP(123)).to.equal('123 $') + expect(formatCLP(1234)).to.equal('1 234 $') + }) + + it('should format thousand separators', function () { + expect(formatCLP(100_000)).to.equal('100 000 $') + expect(formatCLP(9_876_543_210)).to.equal('9 876 543 210 $') + }) + + it('should format negative amounts', function () { + expect(formatCLP(-1)).to.equal('-1 $') + expect(formatCLP(-12.34)).to.equal('-12 $') + expect(formatCLP(-1234)).to.equal('-1 234 $') + }) + }) + + describe('all currencies', function () { + it('should format 1 "minimal atomic units"', function () { + const amount = 1 + + // "no cents currencies" + expect(format('CLP')(amount)).to.equal('1 $') + expect(format('JPY')(amount)).to.equal('1 ¥') + expect(format('KRW')(amount)).to.equal('1 ₩') + expect(format('VND')(amount)).to.equal('1 ₫') + + // other currencies + expect(format('AUD')(amount)).to.equal('1,00 $') + expect(format('BRL')(amount)).to.equal('1,00 R$') + expect(format('CAD')(amount)).to.equal('1,00 $') + expect(format('CHF')(amount)).to.equal('1,00 CHF') + expect(format('CNY')(amount)).to.equal('1,00 ¥') + expect(format('COP')(amount)).to.equal('1,00 $') + + expect(format('EUR')(amount)).to.equal('1,00 €') + expect(format('GBP')(amount)).to.equal('1,00 £') + expect(format('USD')(amount)).to.equal('1,00 $') + }) + + it('should format 1_234_567.897_654 "minimal atomic units"', function () { + const amount = 1_234_567.897_654 + + // "no cents currencies" + expect(format('CLP')(amount)).to.equal('1 234 568 $') + expect(format('JPY')(amount)).to.equal('1 234 568 ¥') + expect(format('KRW')(amount)).to.equal('1 234 568 ₩') + expect(format('VND')(amount)).to.equal('1 234 568 ₫') + + // other currencies + expect(format('AUD')(amount)).to.equal('1 234 567,90 $') + expect(format('BRL')(amount)).to.equal('1 234 567,90 R$') + expect(format('CAD')(amount)).to.equal('1 234 567,90 $') + expect(format('CHF')(amount)).to.equal('1 234 567,90 CHF') + expect(format('CNY')(amount)).to.equal('1 234 567,90 ¥') + expect(format('COP')(amount)).to.equal('1 234 567,90 $') + + expect(format('EUR')(amount)).to.equal('1 234 567,90 €') + expect(format('GBP')(amount)).to.equal('1 234 567,90 £') + expect(format('USD')(amount)).to.equal('1 234 567,90 $') + }) + }) + }) +}) diff --git a/services/web/test/unit/src/Subscription/SubscriptionFormattersTests.js b/services/web/test/unit/src/Subscription/SubscriptionFormattersTests.js index 972f6d8961..0ee781d54f 100644 --- a/services/web/test/unit/src/Subscription/SubscriptionFormattersTests.js +++ b/services/web/test/unit/src/Subscription/SubscriptionFormattersTests.js @@ -3,298 +3,30 @@ const SubscriptionFormatters = require('../../../../app/src/Features/Subscriptio const { expect } = chai -/* - Users can select any language we support, regardless of the country where they are located. - Which mean that any combination of "supported language"-"supported currency" can be displayed - on the user's screen. - - Users located in the USA visiting https://fr.overleaf.com/user/subscription/plans - should see amounts in USD (because of their IP address), - but with French text, number formatting and currency formats (because of language choice). - (e.g. 1 000,00 $) - - Users located in the France visiting https://www.overleaf.com/user/subscription/plans - should see amounts in EUR (because of their IP address), - but with English text, number formatting and currency formats (because of language choice). - (e.g. €1,000.00) - */ - -describe('SubscriptionFormatters.formatPrice', function () { - describe('en', function () { - const format = currency => priceInCents => - SubscriptionFormatters.formatPriceLocalized(priceInCents, currency) - - describe('USD', function () { - const formatUSD = format('USD') - - it('should format basic amounts', function () { - expect(formatUSD(0)).to.equal('$0.00') - expect(formatUSD(1234)).to.equal('$12.34') - }) - - it('should format thousand separators', function () { - expect(formatUSD(100_000)).to.equal('$1,000.00') - expect(formatUSD(9_876_543_210)).to.equal('$98,765,432.10') - }) - - it('should format negative amounts', function () { - expect(formatUSD(-1)).to.equal('-$0.01') - expect(formatUSD(-1234)).to.equal('-$12.34') - }) +describe('SubscriptionFormatters', function () { + describe('formatDateTime', function () { + it('should return null if no date', function () { + const result = SubscriptionFormatters.formatDateTime(null) + expect(result).to.equal(null) }) - describe('EUR', function () { - const formatEUR = format('EUR') - - it('should format basic amounts', function () { - expect(formatEUR(0)).to.equal('€0.00') - expect(formatEUR(1234)).to.equal('€12.34') - }) - - it('should format thousand separators', function () { - expect(formatEUR(100_000)).to.equal('€1,000.00') - expect(formatEUR(9_876_543_210)).to.equal('€98,765,432.10') - }) - - it('should format negative amounts', function () { - expect(formatEUR(-1)).to.equal('-€0.01') - expect(formatEUR(-1234)).to.equal('-€12.34') - }) - }) - - describe('HUF', function () { - const formatHUF = format('HUF') - - it('should format basic amounts', function () { - expect(formatHUF(0)).to.equal('Ft 0.00') - expect(formatHUF(1234)).to.equal('Ft 12.34') - }) - - it('should format thousand separators', function () { - expect(formatHUF(100_000)).to.equal('Ft 1,000.00') - expect(formatHUF(9_876_543_210)).to.equal('Ft 98,765,432.10') - }) - - it('should format negative amounts', function () { - expect(formatHUF(-1)).to.equal('-Ft 0.01') - expect(formatHUF(-1234)).to.equal('-Ft 12.34') - }) - }) - - describe('CLP', function () { - const formatCLP = format('CLP') - - it('should format basic amounts', function () { - expect(formatCLP(0)).to.equal('$0') - expect(formatCLP(1234)).to.equal('$1,234') - }) - - it('should format thousand separators', function () { - expect(formatCLP(100_000)).to.equal('$100,000') - expect(formatCLP(9_876_543_210)).to.equal('$9,876,543,210') - }) - - it('should format negative amounts', function () { - expect(formatCLP(-1)).to.equal('-$1') - expect(formatCLP(-1234)).to.equal('-$1,234') - }) - }) - - describe('all currencies', function () { - it('should format 100 "minimal atomic units"', function () { - const amount = 100 - - // "no cents currencies" - expect(format('CLP')(amount)).to.equal('$100') - expect(format('JPY')(amount)).to.equal('¥100') - expect(format('KRW')(amount)).to.equal('₩100') - expect(format('VND')(amount)).to.equal('₫100') - - // other currencies - expect(format('AUD')(amount)).to.equal('$1.00') - expect(format('BRL')(amount)).to.equal('R$1.00') - expect(format('CAD')(amount)).to.equal('$1.00') - expect(format('CHF')(amount)).to.equal('CHF 1.00') - expect(format('CNY')(amount)).to.equal('¥1.00') - expect(format('COP')(amount)).to.equal('$1.00') - expect(format('DKK')(amount)).to.equal('kr 1.00') - expect(format('EUR')(amount)).to.equal('€1.00') - expect(format('GBP')(amount)).to.equal('£1.00') - expect(format('HUF')(amount)).to.equal('Ft 1.00') - expect(format('IDR')(amount)).to.equal('Rp 1.00') - expect(format('INR')(amount)).to.equal('₹1.00') - expect(format('MXN')(amount)).to.equal('$1.00') - expect(format('MYR')(amount)).to.equal('RM 1.00') - expect(format('NOK')(amount)).to.equal('kr 1.00') - expect(format('NZD')(amount)).to.equal('$1.00') - expect(format('PEN')(amount)).to.equal('PEN 1.00') - expect(format('PHP')(amount)).to.equal('₱1.00') - expect(format('SEK')(amount)).to.equal('kr 1.00') - expect(format('SGD')(amount)).to.equal('$1.00') - expect(format('THB')(amount)).to.equal('฿1.00') - expect(format('USD')(amount)).to.equal('$1.00') - }) - - it('should format 123_456_789.987_654 "minimal atomic units"', function () { - const amount = 123_456_789.987_654 - - // "no cents currencies" - expect(format('CLP')(amount)).to.equal('$123,456,790') - expect(format('JPY')(amount)).to.equal('¥123,456,790') - expect(format('KRW')(amount)).to.equal('₩123,456,790') - expect(format('VND')(amount)).to.equal('₫123,456,790') - - // other currencies - expect(format('AUD')(amount)).to.equal('$1,234,567.90') - expect(format('BRL')(amount)).to.equal('R$1,234,567.90') - expect(format('CAD')(amount)).to.equal('$1,234,567.90') - expect(format('CHF')(amount)).to.equal('CHF 1,234,567.90') - expect(format('CNY')(amount)).to.equal('¥1,234,567.90') - expect(format('COP')(amount)).to.equal('$1,234,567.90') - expect(format('DKK')(amount)).to.equal('kr 1,234,567.90') - expect(format('EUR')(amount)).to.equal('€1,234,567.90') - expect(format('GBP')(amount)).to.equal('£1,234,567.90') - expect(format('HUF')(amount)).to.equal('Ft 1,234,567.90') - expect(format('IDR')(amount)).to.equal('Rp 1,234,567.90') - expect(format('INR')(amount)).to.equal('₹1,234,567.90') - expect(format('MXN')(amount)).to.equal('$1,234,567.90') - expect(format('MYR')(amount)).to.equal('RM 1,234,567.90') - expect(format('NOK')(amount)).to.equal('kr 1,234,567.90') - expect(format('NZD')(amount)).to.equal('$1,234,567.90') - expect(format('PEN')(amount)).to.equal('PEN 1,234,567.90') - expect(format('PHP')(amount)).to.equal('₱1,234,567.90') - expect(format('SEK')(amount)).to.equal('kr 1,234,567.90') - expect(format('SGD')(amount)).to.equal('$1,234,567.90') - expect(format('THB')(amount)).to.equal('฿1,234,567.90') - expect(format('USD')(amount)).to.equal('$1,234,567.90') - }) + it('should format date with time', function () { + const date = new Date(1639904485000) + const result = SubscriptionFormatters.formatDateTime(date) + expect(result).to.equal('December 19th, 2021 9:01 AM UTC') }) }) - describe('fr', function () { - const format = currency => priceInCents => - SubscriptionFormatters.formatPriceLocalized(priceInCents, currency, 'fr') - - describe('USD', function () { - const formatUSD = format('USD') - - it('should format basic amounts', function () { - expect(formatUSD(0)).to.equal('0,00 $') - expect(formatUSD(1234)).to.equal('12,34 $') - }) - - it('should format thousand separators', function () { - expect(formatUSD(100_000)).to.equal('1 000,00 $') - expect(formatUSD(9_876_543_210)).to.equal('98 765 432,10 $') - }) - - it('should format negative amounts', function () { - expect(formatUSD(-1)).to.equal('-0,01 $') - expect(formatUSD(-1234)).to.equal('-12,34 $') - }) + describe('formatDate', function () { + it('should return null if no date', function () { + const result = SubscriptionFormatters.formatDate(null) + expect(result).to.equal(null) }) - describe('EUR', function () { - const formatEUR = format('EUR') - - it('should format basic amounts', function () { - expect(formatEUR(0)).to.equal('0,00 €') - expect(formatEUR(1234)).to.equal('12,34 €') - }) - - it('should format thousand separators', function () { - expect(formatEUR(100_000)).to.equal('1 000,00 €') - expect(formatEUR(9_876_543_210)).to.equal('98 765 432,10 €') - }) - - it('should format negative amounts', function () { - expect(formatEUR(-1)).to.equal('-0,01 €') - expect(formatEUR(-1234)).to.equal('-12,34 €') - }) - }) - - describe('HUF', function () { - const formatHUF = format('HUF') - - it('should format basic amounts', function () { - expect(formatHUF(0)).to.equal('0,00 Ft') - expect(formatHUF(1234)).to.equal('12,34 Ft') - }) - - it('should format thousand separators', function () { - expect(formatHUF(100_000)).to.equal('1 000,00 Ft') - expect(formatHUF(9_876_543_210)).to.equal('98 765 432,10 Ft') - }) - - it('should format negative amounts', function () { - expect(formatHUF(-1)).to.equal('-0,01 Ft') - expect(formatHUF(-1234)).to.equal('-12,34 Ft') - }) - }) - - describe('CLP', function () { - const formatCLP = format('CLP') - - it('should format basic amounts', function () { - expect(formatCLP(0)).to.equal('0 $') - expect(formatCLP(1234)).to.equal('1 234 $') - }) - - it('should format thousand separators', function () { - expect(formatCLP(100_000)).to.equal('100 000 $') - expect(formatCLP(9_876_543_210)).to.equal('9 876 543 210 $') - }) - - it('should format negative amounts', function () { - expect(formatCLP(-1)).to.equal('-1 $') - expect(formatCLP(-1234)).to.equal('-1 234 $') - }) - }) - - describe('all currencies', function () { - it('should format 100 "minimal atomic units"', function () { - const amount = 100 - - // "no cents currencies" - expect(format('CLP')(amount)).to.equal('100 $') - expect(format('JPY')(amount)).to.equal('100 ¥') - expect(format('KRW')(amount)).to.equal('100 ₩') - expect(format('VND')(amount)).to.equal('100 ₫') - - // other currencies - expect(format('AUD')(amount)).to.equal('1,00 $') - expect(format('BRL')(amount)).to.equal('1,00 R$') - expect(format('CAD')(amount)).to.equal('1,00 $') - expect(format('CHF')(amount)).to.equal('1,00 CHF') - expect(format('CNY')(amount)).to.equal('1,00 ¥') - expect(format('COP')(amount)).to.equal('1,00 $') - - expect(format('EUR')(amount)).to.equal('1,00 €') - expect(format('GBP')(amount)).to.equal('1,00 £') - expect(format('USD')(amount)).to.equal('1,00 $') - }) - - it('should format 123_456_789.987_654 "minimal atomic units"', function () { - const amount = 123_456_789.987_654 - - // "no cents currencies" - expect(format('CLP')(amount)).to.equal('123 456 790 $') - expect(format('JPY')(amount)).to.equal('123 456 790 ¥') - expect(format('KRW')(amount)).to.equal('123 456 790 ₩') - expect(format('VND')(amount)).to.equal('123 456 790 ₫') - - // other currencies - expect(format('AUD')(amount)).to.equal('1 234 567,90 $') - expect(format('BRL')(amount)).to.equal('1 234 567,90 R$') - expect(format('CAD')(amount)).to.equal('1 234 567,90 $') - expect(format('CHF')(amount)).to.equal('1 234 567,90 CHF') - expect(format('CNY')(amount)).to.equal('1 234 567,90 ¥') - expect(format('COP')(amount)).to.equal('1 234 567,90 $') - - expect(format('EUR')(amount)).to.equal('1 234 567,90 €') - expect(format('GBP')(amount)).to.equal('1 234 567,90 £') - expect(format('USD')(amount)).to.equal('1 234 567,90 $') - }) + it('should format date', function () { + const date = new Date(1639904485000) + const result = SubscriptionFormatters.formatDate(date) + expect(result).to.equal('December 19th, 2021') }) }) }) diff --git a/services/web/test/unit/src/Subscription/SubscriptionViewModelBuilderTests.js b/services/web/test/unit/src/Subscription/SubscriptionViewModelBuilderTests.js index f72b42c7c9..1e0c6457df 100644 --- a/services/web/test/unit/src/Subscription/SubscriptionViewModelBuilderTests.js +++ b/services/web/test/unit/src/Subscription/SubscriptionViewModelBuilderTests.js @@ -525,7 +525,6 @@ describe('SubscriptionViewModelBuilder', function () { this.user ) assert.deepEqual(result.personalSubscription.recurly, { - tax: 1.5, taxRate: 0.1, billingDetailsLink: '/user/subscription/recurly/billing-details', accountManagementLink: @@ -598,10 +597,6 @@ describe('SubscriptionViewModelBuilder', function () { result.personalSubscription.recurly.displayPrice, '€1,756.92' ) - assert.equal( - result.personalSubscription.recurly.currentPlanDisplayPrice, - '€16.50' - ) assert.equal( result.personalSubscription.recurly.planOnlyDisplayPrice, '€1,754.72' diff --git a/services/web/types/subscription/dashboard/subscription.ts b/services/web/types/subscription/dashboard/subscription.ts index d0cd229601..bf274fe283 100644 --- a/services/web/types/subscription/dashboard/subscription.ts +++ b/services/web/types/subscription/dashboard/subscription.ts @@ -17,7 +17,6 @@ type RecurlyCoupon = { } type Recurly = { - tax: number taxRate: number billingDetailsLink: string accountManagementLink: string @@ -36,7 +35,6 @@ type Recurly = { displayPrice: string planOnlyDisplayPrice: string addOnDisplayPricesWithoutAdditionalLicense: Record - currentPlanDisplayPrice?: string pendingAdditionalLicenses?: number pendingTotalLicenses?: number pausedAt?: Nullable