Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Gerwitz <gerwitzm@lovullo.com>2016-12-01 08:44:20 -0500
committerMike Gerwitz <gerwitzm@lovullo.com>2016-12-01 08:47:23 -0500
commit5607bf19279494f8be1ce81d5ec089fe6dcf1023 (patch)
treedda7edc516e76c32ed3854792b36b7eae30e2d63
parentab3f5f4cb608c58fd0f31ce84ad69d2cde6a6f31 (diff)
downloadliza-5607bf19279494f8be1ce81d5ec089fe6dcf1023.tar.gz
liza-5607bf19279494f8be1ce81d5ec089fe6dcf1023.tar.bz2
liza-5607bf19279494f8be1ce81d5ec089fe6dcf1023.zip
Replace Currency formatter with StringFormat
This is a much more general solution. * src/validate/formatter/Currency.js: Remove trait. * test/validate/formatter/CurrencyTest.js: Remove test case. * src/validate/formatter/StringFormat.js: Add trait. * test/validate/formatter/StringFormatTest.js: Add test case.
-rw-r--r--src/validate/formatter/Currency.js75
-rw-r--r--src/validate/formatter/StringFormat.js178
-rw-r--r--test/validate/formatter/CurrencyTest.js60
-rw-r--r--test/validate/formatter/StringFormatTest.js115
4 files changed, 293 insertions, 135 deletions
diff --git a/src/validate/formatter/Currency.js b/src/validate/formatter/Currency.js
deleted file mode 100644
index 5ecf339..0000000
--- a/src/validate/formatter/Currency.js
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Currency formatter
- *
- * Copyright (C) 2016 LoVullo Associates, Inc.
- *
- * This file is part of liza.
- *
- * liza is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-var Trait = require( 'easejs' ).Trait,
- ValidatorFormatter = require( '../ValidatorFormatter' );
-
-
-/**
- * Formats amount as currency
- *
- * This does not guarantee that the value is a number; this should be
- * mixed in atop of a formatter that does guarantee such.
- */
-module.exports = Trait( 'Currency' )
- .implement( ValidatorFormatter )
- .extend(
-{
- /**
- * Parse item as currency
- *
- * @param {string} data data to parse
- *
- * @return {string} data formatted for storage
- */
- 'virtual abstract override public parse': function( data )
- {
- return this.__super( data ).replace( /^\$*/g, '' );
- },
-
-
- /**
- * Format amount as a currency
- *
- * @param {string} data data to format for display
- *
- * @return {string} data formatted for display
- */
- 'virtual abstract override public retrieve': function( data )
- {
- return this.styleCurrency( this.__super( data ) );
- },
-
-
- /**
- * Style amount with currency symbol
- *
- * @param {string} amount amount to style
- *
- * @return {string} formatted number
- */
- 'virtual protected styleCurrency': function( amount )
- {
- return ( ''+amount === '' )
- ? amount
- : '$' + amount;
- },
-} );
diff --git a/src/validate/formatter/StringFormat.js b/src/validate/formatter/StringFormat.js
new file mode 100644
index 0000000..c82510a
--- /dev/null
+++ b/src/validate/formatter/StringFormat.js
@@ -0,0 +1,178 @@
+/**
+ * @license
+ * StringFormat formatter
+ *
+ * Copyright (C) 2016 LoVullo Associates, Inc.
+ *
+ * This file is part of liza.
+ *
+ * liza is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @module validate/formatter
+ */
+
+var Trait = require( 'easejs' ).Trait,
+ ValidatorFormatter = require( '../ValidatorFormatter' );
+
+
+/**
+ * Basic data formatting
+ *
+ * `StringFormat` effectively allows for the definition of prefixes
+ * and suffixes by using a format string of the form `'pre %s post'`.
+ *
+ * For example, the format string `'$%sUSD'` applied to the
+ * input `'$25.00USD'` would yield `'25.00'` after parsing and
+ * re-yield the original string when retrieved.
+ *
+ * If `StringFormat` is mixed in with other formatters that
+ * modify the input, then the former will be applied after earlier
+ * formatters process the data. For example:
+ *
+ * @example
+ * let fmt = EchoFormatter
+ * .use( Number( 2 ) )
+ * .use( StringFormatter( '$%sUSD' ) )();
+ *
+ * fmt.parse( '$25USD' ); // => 25.00
+ * fmt.retrieve( '25' ); // => $25.00USD
+ *
+ * The simple, restricted format string in place of a regular expression
+ * allows for a declarative stacking of formatters without concern as
+ * to whether the format was written correctly. Regular expressions,
+ * however, might well need associated tests for confidence in the
+ * implementation, which complicates the design. Simply: it's easy to
+ * reason about.
+ */
+module.exports = Trait( 'StringFormat' )
+ .implement( ValidatorFormatter )
+ .extend(
+{
+ /**
+ * Prefix string
+ *
+ * @type {string}
+ */
+ 'private _pre': '',
+
+ /**
+ * Postfix string
+ *
+ * @type {string}
+ */
+ 'private _post': '',
+
+
+ /**
+ * Define format string
+ *
+ * The format string must have a single `'%s'` denoting the
+ * placement of the data.
+ *
+ * @param {string} format format string with single `'%s'`
+ */
+ __mixin: function( format )
+ {
+ var parts = this.parseFormat( ''+format );
+
+ this._pre = parts.pre;
+ this._post = parts.post;
+ },
+
+
+ /**
+ * Extract prefix and suffix from format string FORMAT
+ *
+ * Everything before the `'%s'` is the prefix, and everything
+ * after is the suffix.
+ *
+ * @param {string} format format string with single `'%s'`
+ *
+ * @return {Object.<pre,post>} prefix and suffix of FORMAT
+ *
+ * @throws {Error} if FORMAT does not have exactly one `'%s'`
+ */
+ 'virtual protected parseFormat': function( format )
+ {
+ var parts = format.split( '%s' );
+
+ if ( parts.length !== 2 )
+ {
+ throw Error(
+ "Format string must have a single '%s': " + format
+ );
+ }
+
+ return {
+ pre: parts[ 0 ],
+ post: parts[ 1 ]
+ };
+ },
+
+
+ /**
+ * Remove prefix and suffix from data
+ *
+ * @param {string} data data to parse
+ *
+ * @return {string} data formatted for storage
+ */
+ 'virtual abstract override public parse': function( data )
+ {
+ return this.__super( this._stripPrePost( data ) );
+ },
+
+
+ /**
+ * Recursively strip prefixes and suffixes from STR
+ *
+ * This simply allows us to avoid having to use regexes and,
+ * consequently, worry about escaping format strings.
+ *
+ * @param {string} str string to strip
+ *
+ * @return {string} stripped string
+ */
+ 'private _stripPrePost': function( str )
+ {
+ if ( this._pre && ( str.substr( 0, this._pre.length ) === this._pre ) )
+ {
+ return this._stripPrePost(
+ str.substr( this._pre.length )
+ );
+ }
+
+ if ( this._post && ( str.substr( -this._post.length ) === this._post ) )
+ {
+ return this._stripPrePost(
+ str.substr( 0, str.length - this._post.length )
+ );
+ }
+
+ return str;
+ },
+
+
+ /**
+ * Format data by adding prefix and suffix
+ *
+ * @param {string} data data to format for display
+ *
+ * @return {string} data formatted for display
+ */
+ 'virtual abstract override public retrieve': function( data )
+ {
+ return this._pre + this.__super( data ) + this._post;
+ },
+} );
diff --git a/test/validate/formatter/CurrencyTest.js b/test/validate/formatter/CurrencyTest.js
deleted file mode 100644
index 968e2e3..0000000
--- a/test/validate/formatter/CurrencyTest.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Currency formatter test
- *
- * Copyright (C) 2016 LoVullo Associates, Inc.
- *
- * This file is part of liza.
- *
- * liza is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-var liza = require( '../../../' ),
- Sut = liza.validate.formatter.Currency,
- EchoFormatter = liza.validate.formatter.EchoFormatter,
- common = require( './common' );
-
-
-describe( 'validate.formatter.Currency', function()
-{
- common.testValidate( EchoFormatter.use( Sut )(), {
- // should format anything given to it, with or without prefix
- "1": [ "1", "$1" ],
- "foo": [ "foo", "$foo" ],
- "+": [ "+", "$+" ],
- "$foo": [ "foo", "$foo" ],
-
- // empty shouldn't format as anything
- "": [ "", "" ],
- "$": [ "", "" ],
- "$$": [ "", "" ],
-
- // make sure these aren't considered to be empty
- "0": [ "0", "$0" ],
- "$0": [ "0", "$0" ],
-
- // be lax on input
- "$$foo": [ "foo", "$foo" ],
- "$$$$$$$12.34": [ "12.34", "$12.34" ],
- } );
-
-
- common.testMixin(
- EchoFormatter,
- Sut,
- 'foo',
- '123',
- 'foo123',
- '$foo123'
- );
-} );
diff --git a/test/validate/formatter/StringFormatTest.js b/test/validate/formatter/StringFormatTest.js
new file mode 100644
index 0000000..3580d92
--- /dev/null
+++ b/test/validate/formatter/StringFormatTest.js
@@ -0,0 +1,115 @@
+/**
+ * @license
+ * StringFormat formatter test
+ *
+ * Copyright (C) 2016 LoVullo Associates, Inc.
+ *
+ * This file is part of liza.
+ *
+ * liza is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+var liza = require( '../../../' ),
+ expect = require( 'chai' ).expect,
+ Sut = liza.validate.formatter.StringFormat,
+ EchoFormatter = liza.validate.formatter.EchoFormatter,
+ common = require( './common' );
+
+
+describe( 'validate.formatter.StringFormat', function()
+{
+ common.testValidate( EchoFormatter.use( Sut( 'PRE%sPOST' ) )(), {
+ // basic prefix/suffix
+ "": [ "", "PREPOST" ],
+ "foo": [ "foo", "PREfooPOST" ],
+ "PREfoo": [ "foo", "PREfooPOST" ],
+ "barPOST": [ "bar", "PREbarPOST" ],
+ "PREbazPOST": [ "baz", "PREbazPOST" ],
+
+ // only prefix/suffix
+ "PRE": [ "", "PREPOST" ],
+ "POST": [ "", "PREPOST" ],
+ "PREPOST": [ "", "PREPOST" ],
+
+ // repeated prefix/suffix normalization
+ "PREPREfoo": [ "foo", "PREfooPOST" ],
+ "barPOSTPOST": [ "bar", "PREbarPOST" ],
+ "PREPREbazPOSTPOSTPOST": [ "baz", "PREbazPOST" ],
+ "PREPREPOSTPOST": [ "", "PREPOST" ],
+
+ // convoluted interpretations
+ "PREfooPOSTPRE": [ "fooPOSTPRE", "PREfooPOSTPREPOST" ],
+ "PREmooPREfooPOST": [ "mooPREfoo", "PREmooPREfooPOST" ],
+ "mooPREfoo": [ "mooPREfoo", "PREmooPREfooPOST" ],
+ } );
+
+
+ // only prefix format
+ common.testValidate( EchoFormatter.use( Sut( 'BEG%s' ) )(), {
+ "foo": [ "foo", "BEGfoo" ],
+ "BEGfoo": [ "foo", "BEGfoo" ],
+ } );
+
+
+ // only suffix format
+ common.testValidate( EchoFormatter.use( Sut( '%sEND' ) )(), {
+ "fooEND": [ "foo", "fooEND" ],
+ "fooEND": [ "foo", "fooEND" ],
+ } );
+
+
+ // no prefix or suffix
+ common.testValidate( EchoFormatter.use( Sut( '%s' ) )(), {
+ "foo": [ "foo", "foo" ],
+ } );
+
+
+ describe( 'given multiple %s', function()
+ {
+ it( 'throws an error', function()
+ {
+ expect( function()
+ {
+ EchoFormatter.use( Sut( 'foo%sbar%sbaz' ) )();
+ } ).to.throw( Error );
+ } );
+ } );
+
+
+ describe( 'given no %s', function()
+ {
+ it( 'throws an error', function()
+ {
+ expect( function()
+ {
+ EchoFormatter.use( Sut( '' ) )();
+ } ).to.throw( Error );
+
+ expect( function()
+ {
+ EchoFormatter.use( Sut( 'Foo' ) )();
+ } ).to.throw( Error );
+ } );
+ } );
+
+
+ common.testMixin(
+ EchoFormatter,
+ Sut( 'PRE%sPOST' ),
+ 'base',
+ 'PREfooPOST',
+ 'basefoo',
+ 'PREbasePREfooPOSTPOST'
+ );
+} );