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.master
parent
ab3f5f4cb6
commit
5607bf1927
|
@ -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;
|
||||
},
|
||||
} );
|
|
@ -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;
|
||||
},
|
||||
} );
|
|
@ -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'
|
||||
);
|
||||
} );
|
|
@ -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'
|
||||
);
|
||||
} );
|
Loading…
Reference in New Issue