From 07e1a2406b6f6124f227738c214d2feb8a3a316b Mon Sep 17 00:00:00 2001 From: Naz Gargol Date: Mon, 27 Jan 2020 18:41:12 +0700 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Added=20{{price}}=20helper=20for=20?= =?UTF-8?q?formatting=20stripe=20amounts=20(ie.=20"1935"=20to=20"19.35")?= =?UTF-8?q?=20(#11473)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no issue - This helper allows to format currencies that use decimal normalization. For example 19.35 USD is served as 1935 from the API which always needs to be divided by 100 to get a dollar ammount. --- core/frontend/helpers/index.js | 2 ++ core/frontend/helpers/price.js | 32 +++++++++++++++++++ core/server/translations/en.json | 4 +++ core/test/unit/helpers/index_spec.js | 2 +- core/test/unit/helpers/price_spec.js | 46 ++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 core/frontend/helpers/price.js create mode 100644 core/test/unit/helpers/price_spec.js diff --git a/core/frontend/helpers/index.js b/core/frontend/helpers/index.js index 342ec1302d..a5f19ec669 100644 --- a/core/frontend/helpers/index.js +++ b/core/frontend/helpers/index.js @@ -36,6 +36,7 @@ coreHelpers.pagination = require('./pagination'); coreHelpers.plural = require('./plural'); coreHelpers.post_class = require('./post_class'); coreHelpers.prev_post = require('./prev_next'); +coreHelpers.price = require('./price'); coreHelpers.next_post = require('./prev_next'); coreHelpers.reading_time = require('./reading_time'); coreHelpers.t = require('./t'); @@ -84,6 +85,7 @@ registerAllCoreHelpers = function registerAllCoreHelpers() { registerThemeHelper('pagination', coreHelpers.pagination); registerThemeHelper('plural', coreHelpers.plural); registerThemeHelper('post_class', coreHelpers.post_class); + registerThemeHelper('price', coreHelpers.price); registerThemeHelper('reading_time', coreHelpers.reading_time); registerThemeHelper('t', coreHelpers.t); registerThemeHelper('tags', coreHelpers.tags); diff --git a/core/frontend/helpers/price.js b/core/frontend/helpers/price.js new file mode 100644 index 0000000000..2cb80e0f29 --- /dev/null +++ b/core/frontend/helpers/price.js @@ -0,0 +1,32 @@ +// # {{price}} helper +// +// Usage: `{{price 2100}}` +// +// Returns amount equal to the dominant denomintation of the currency. +// For example, if 2100 is passed, it will return 21. +const _ = require('lodash'); +const {errors, i18n} = require('./proxy'); + +module.exports = function price(amount) { + // CASE: if no amount is passed, e.g. `{{price}}` we throw an error + if (arguments.length < 2) { + throw new errors.IncorrectUsageError({ + message: i18n.t('warnings.helpers.price.attrIsRequired') + }); + } + + // CASE: if amount is passed, but it is undefined we throw an error + if (amount === undefined) { + throw new errors.IncorrectUsageError({ + message: i18n.t('warnings.helpers.price.attrIsRequired') + }); + } + + if (!_.isNumber(amount)) { + throw new errors.IncorrectUsageError({ + message: i18n.t('warnings.helpers.price.attrMustBeNumeric') + }); + } + + return amount / 100; +}; diff --git a/core/server/translations/en.json b/core/server/translations/en.json index 76c8f1f3cb..41d7a2b3af 100644 --- a/core/server/translations/en.json +++ b/core/server/translations/en.json @@ -607,6 +607,10 @@ "plural": { "valuesMustBeDefined": "All values must be defined for empty, singular and plural" }, + "price": { + "attrIsRequired": "Attribute is required e.g. \\{\\{price plan.amount\\}\\}", + "attrMustBeNumeric": "Attribute value should be a number" + }, "img_url": { "attrIsRequired": "Attribute is required e.g. \\{\\{img_url feature_image\\}\\}", "attrIsUnknown": "Attribute passed to \\{\\{img_url\\}\\} is unknown" diff --git a/core/test/unit/helpers/index_spec.js b/core/test/unit/helpers/index_spec.js index 587c210639..9cf7be34cb 100644 --- a/core/test/unit/helpers/index_spec.js +++ b/core/test/unit/helpers/index_spec.js @@ -10,7 +10,7 @@ describe('Helpers', function () { ghostHelpers = [ 'asset', 'author', 'authors', 'body_class', 'cancel_link', 'concat', 'content', 'date', 'encode', 'excerpt', 'facebook_url', 'foreach', 'get', 'ghost_foot', 'ghost_head', 'has', 'img_url', 'is', 'lang', 'link', 'link_class', 'meta_description', 'meta_title', 'navigation', - 'next_post', 'page_url', 'pagination', 'plural', 'post_class', 'prev_post', 'reading_time', 't', 'tags', 'title', 'twitter_url', + 'next_post', 'page_url', 'pagination', 'plural', 'post_class', 'prev_post', 'price', 'reading_time', 't', 'tags', 'title', 'twitter_url', 'url' ], expectedHelpers = _.concat(hbsHelpers, ghostHelpers); diff --git a/core/test/unit/helpers/price_spec.js b/core/test/unit/helpers/price_spec.js new file mode 100644 index 0000000000..f76b43d664 --- /dev/null +++ b/core/test/unit/helpers/price_spec.js @@ -0,0 +1,46 @@ +const should = require('should'); +const helpers = require.main.require('core/frontend/helpers'); +const handlebars = require.main.require('core/frontend/services/themes/engine').handlebars; + +function compile(templateString) { + const template = handlebars.compile(templateString); + template.with = (locals = {}, globals) => { + return template(locals, globals); + }; + + return template; +} + +describe('{{price}} helper', function () { + before(function () { + handlebars.registerHelper('price', helpers.price); + }); + + it('throws an error for no provided parameters', function () { + (function compileWith() { + compile('{{price}}') + .with({}); + }).should.throw(); + }); + + it('throws an error for undefined parameter', function () { + (function compileWith() { + compile('{{price @dont.exist}}') + .with({}); + }).should.throw(); + }); + + it('throws if argument is not a number', function () { + (function compileWith() { + compile('{{price "not_a_number"}}') + .with({}); + }).should.throw(); + }); + + it('will format decimal adjusted amount', function () { + compile('{{price 2000}}') + .with({}) + .should.equal('20'); + }); +}); +