Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Gerwitz <gerwitm@lovullo.com>2016-06-28 10:28:18 -0400
committerMike Gerwitz <gerwitm@lovullo.com>2016-06-28 10:28:18 -0400
commitd168e6cfb5ff1d2cca33c7bf3d75ab92829168c0 (patch)
treea3921c456c7a783a7c23d4c46287c087018dff07
parent4ecaa378530f85729bb576a263ff07ca2a952a6f (diff)
parentd0768e20ca3dedfb9a81f2fd4bc57625c95e732f (diff)
downloadliza-d168e6cfb5ff1d2cca33c7bf3d75ab92829168c0.tar.gz
liza-d168e6cfb5ff1d2cca33c7bf3d75ab92829168c0.tar.bz2
liza-d168e6cfb5ff1d2cca33c7bf3d75ab92829168c0.zip
Additional validator/formatters
Some are new, some are rewritten to extract from our internal repo. More to come.
-rw-r--r--src/ui/ElementStyler.js141
-rw-r--r--src/validate/ValidatorFormatter.js57
-rw-r--r--src/validate/formatter/AcceptReject.js79
-rw-r--r--src/validate/formatter/EchoFormatter.js60
-rw-r--r--src/validate/formatter/MultiDelimited.js149
-rw-r--r--src/validate/formatter/MultiDimension.js116
-rw-r--r--src/validate/formatter/Number.js88
-rw-r--r--src/validate/formatter/PatternFormatter.js140
-rw-r--r--src/validate/formatter/UnorderedList.js112
-rw-r--r--src/validate/formatter/insurance/Limit.js70
-rw-r--r--src/validate/formatter/insurance/StandardLimitFormatter.js28
-rw-r--r--test/validate/formatter/AcceptRejectTest.js93
-rw-r--r--test/validate/formatter/EchoFormatterTest.js65
-rw-r--r--test/validate/formatter/MultiDelimitedTest.js71
-rw-r--r--test/validate/formatter/MultiDimensionTest.js109
-rw-r--r--test/validate/formatter/NumberTest.js50
-rw-r--r--test/validate/formatter/PatternFormatterTest.js124
-rw-r--r--test/validate/formatter/UnorderedListTest.js152
-rw-r--r--test/validate/formatter/common.js140
-rw-r--r--test/validate/formatter/insurance/LimitTest.js68
20 files changed, 1771 insertions, 141 deletions
diff --git a/src/ui/ElementStyler.js b/src/ui/ElementStyler.js
index 6c183be..8c8db3c 100644
--- a/src/ui/ElementStyler.js
+++ b/src/ui/ElementStyler.js
@@ -84,93 +84,6 @@ module.exports = Class( 'ElementStyler',
_answerStyles: {
- 'limit': function( value, _, default_val )
- {
- value = ( value + '' ).replace( ',', '' );
-
-
- // if no value was given, be sure that we use the proper default
- // value
- if ( ( value === '' ) && default_val )
- {
- return default_val;
- }
-
- // if the value is simply a string, return it
- if ( /^[a-z_ -]+$/i.test( value ) )
- {
- return value;
- }
-
- // split on multiple limits (this will work fine if there's only
- // one)
- var data = ( ''+( value ) ).split( '/' ),
- i = data.length;
-
- // simple comma addition (for thousands); XXX: this mess is an
- // abomination
- while ( i-- )
- {
- data[ i ] = data[ i ]
- .replace( /^.*(?:[0-9]{3}|[1-9]0{2})$/, function( number )
- {
- var len = number.length,
- ret = '';
-
- // insert thousands separators into their proper
- // positions
- for ( var i = 0; i < len; i++ )
- {
- ret += number.substr( i, 1 );
-
- if ( ( ( len - i ) % 3 ) === 1 )
- {
- ret += ',';
- }
- }
-
- // could handle this in the above loop, but this is more
- // clear
- return ret.replace( /,$/, '' );
- } )
- .replace( /^,?([0-9]{2,})$/, '$1,000' )
- .replace( /^,/, '' );
- }
-
- // re-join multiple limits
- return data.join( '/' );
- },
-
- 'multilimit': function( values, _, default_val )
- {
- var limit = this._getAnswerStyler( 'limit' );
-
- // if we're not an array, fall back to the normal limit styler
- if ( typeof values !== 'object' )
- {
- return limit.apply( this, arguments );
- }
-
- var formatted = [],
- same = true;
-
- for ( var i in values )
- {
- formatted.push(
- limit.call( this, values[ i ], _, default_val )
- );
-
- if ( i > 0 )
- {
- same = ( same && formatted[ i ] === formatted[ i - 1 ] );
- }
- }
-
- return ( same )
- ? formatted[ 0 ]
- : formatted.join( '; ' );
- },
-
'multitext': function( values, _, default_val )
{
// for now
@@ -191,31 +104,6 @@ module.exports = Class( 'ElementStyler',
return value + ' Deductible';
},
- /*
- * display as accepted, rejected or default if available
- */
- 'acceptReject': function( value, _, default_val )
- {
- // use the default if no value
- if ( ( value === '' ) && default_val )
- {
- return default_val;
- }
-
- var ret = value;
-
- if ( +value === 0 )
- {
- ret = 'Rejected';
- }
- else if ( +value === 1 )
- {
- ret = 'Accepted';
- }
-
- return ret;
- },
-
'includeExclude': function( value, _, default_val )
{
// use the default if no value
@@ -229,35 +117,6 @@ module.exports = Class( 'ElementStyler',
: 'Included';
},
- /*
- * display as a limit, rejected or default if available
- */
- 'limitReject': function( value, _, default_val )
- {
- // use the default if no value
- if ( ( value === '' ) && default_val )
- {
- return default_val;
- }
-
- var limit = this._getAnswerStyler( 'number' );
-
- if ( +value === 0 )
- {
- ret = 'Rejected';
- }
- else if ( +value === 1 )
- {
- ret = 'Accepted';
- }
- else
- {
- ret = limit.apply( this, arguments );
- }
-
- return ret;
- },
-
'state': function( value )
{
return State.getName( value );
diff --git a/src/validate/ValidatorFormatter.js b/src/validate/ValidatorFormatter.js
new file mode 100644
index 0000000..bdc1318
--- /dev/null
+++ b/src/validate/ValidatorFormatter.js
@@ -0,0 +1,57 @@
+/**
+ * Validator-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 Interface = require( 'easejs' ).Interface;
+
+
+module.exports = Interface( 'ValidatorFormatter',
+{
+ /**
+ * Format the given data or fail if no match is found
+ *
+ * If the given data matches a pattern, it will be formatted with
+ * respect to the first matched pattern. Otherwise, an error will
+ * be thrown indicating a validation failure.
+ *
+ * @param {string} data data to parse
+ *
+ * @return {string} formatted string, if a match is found
+ */
+ 'public parse': [ 'data' ],
+
+
+ /**
+ * Retrieve data that may require formatting for display
+ *
+ * Return formatting is optional. No formatting will be done if no pattern
+ * was given when the instance was constructed.
+ *
+ * To ensure consistency and correctness, *any data returned by this method
+ * must be reversible* --- that is, parse( retrieve( data ) ) should not
+ * throw an exception.
+ *
+ * @param {string} data data to format for display
+ *
+ * @return {string} data formatted for display
+ */
+ 'public retrieve': [ 'data' ]
+} );
diff --git a/src/validate/formatter/AcceptReject.js b/src/validate/formatter/AcceptReject.js
new file mode 100644
index 0000000..64b0dbe
--- /dev/null
+++ b/src/validate/formatter/AcceptReject.js
@@ -0,0 +1,79 @@
+/**
+ * Accept/reject styling
+ *
+ * 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' );
+
+
+/**
+ * Applies supertype for each item in a delimited string
+ */
+module.exports = Trait( 'AcceptReject' )
+ .implement( ValidatorFormatter )
+ .extend(
+{
+ /**
+ * Format accept/reject string as an integer boolean
+ *
+ * @param {string} data data to parse
+ *
+ * @return {string} data formatted for storage
+ */
+ 'virtual abstract override public parse': function( data )
+ {
+ switch ( data )
+ {
+ case '0':
+ case 'Rejected':
+ return '0';
+
+ case '1':
+ case 'Accepted':
+ return '1';
+
+ default:
+ return this.__super( data );
+ }
+ },
+
+
+ /**
+ * Format boolean integer as accept/reject string
+ *
+ * @param {string} data data to format for display
+ *
+ * @return {string} data formatted for display
+ */
+ 'virtual abstract override public retrieve': function( data )
+ {
+ switch ( data )
+ {
+ case '0':
+ return 'Rejected';
+
+ case '1':
+ return 'Accepted';
+
+ default:
+ return this.__super( data );
+ }
+ }
+} );
diff --git a/src/validate/formatter/EchoFormatter.js b/src/validate/formatter/EchoFormatter.js
new file mode 100644
index 0000000..4e6a44f
--- /dev/null
+++ b/src/validate/formatter/EchoFormatter.js
@@ -0,0 +1,60 @@
+/**
+ * Echo 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 Class = require( 'easejs' ).Class,
+ ValidatorFormatter = require( '../ValidatorFormatter' );
+
+
+/**
+ * Echos its input
+ *
+ * This formatter does nothing; it is intended to be used as a base
+ * for mixing in other formatters, or for a formatting noop.
+ */
+module.exports = Class( 'EchoFormatter' )
+ .implement( ValidatorFormatter )
+ .extend(
+{
+ /**
+ * Echo given data
+ *
+ * @param {string} data data to echo
+ *
+ * @return {string} DATA
+ */
+ 'virtual public parse': function( data )
+ {
+ return data;
+ },
+
+
+ /**
+ * Echo given data
+ *
+ * @param {string} data data to echo
+ *
+ * @return {string} DATA
+ */
+ 'virtual public retrieve': function( data )
+ {
+ return data;
+ }
+} );
diff --git a/src/validate/formatter/MultiDelimited.js b/src/validate/formatter/MultiDelimited.js
new file mode 100644
index 0000000..31c2c49
--- /dev/null
+++ b/src/validate/formatter/MultiDelimited.js
@@ -0,0 +1,149 @@
+/**
+ * Apply styles to each delimited item individaully
+ *
+ * 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' );
+
+
+/**
+ * Applies supertype for each item in a delimited string
+ */
+module.exports = Trait( 'MultiDelimited' )
+ .implement( ValidatorFormatter )
+ .extend(
+{
+ /**
+ * Delimited to used in parse input
+ * @type {string}
+ */
+ 'private _parse_delim': '',
+
+ /**
+ * Delimited to used in retrieve result
+ * @type {string}
+ */
+ 'private _retrieve_delim': '',
+
+
+ /**
+ * Initialize with parse and retrieve delimiters
+ *
+ * Parsing is intended for storage of data, retrieval is intended
+ * for display. When parsing, RETRIEVE_DELIM will be added
+ * between parts, and when parsing, PARSE_DELIM will be used
+ * instead.
+ *
+ * If RETRIEVE_DELIM is undefined, it will default to PARSE_DELIM.
+ *
+ * @param {string} parse_delim delimiter on input data for parsing
+ * @param {?string} retrieve_delim delimiter on input data for retrieval
+ */
+ __mixin: function( parse_delim, retrieve_delim )
+ {
+ this._parse_delim = ''+parse_delim;
+
+ this._retrieve_delim = ( retrieve_delim === undefined )
+ ? this._parse_delim
+ : ''+retrieve_delim;
+ },
+
+
+ /**
+ * Parse each item in a delimited string
+ *
+ * @param {string} data data to parse
+ *
+ * @return {string} data formatted for storage
+ */
+ 'virtual abstract override public parse': function( data )
+ {
+ var _self = this,
+ _super = this.__super;
+
+ return this.forEachPart( this._parse_delim, data, function( part )
+ {
+ return _super.call( _self, part );
+ } ).join( this._retrieve_delim );
+ },
+
+
+ /**
+ * Format each item in a delimited string
+ *
+ * @param {string} data data to format for display
+ *
+ * @return {string} data formatted for display
+ */
+ 'virtual abstract override public retrieve': function( data )
+ {
+ var _self = this,
+ _super = this.__super;
+
+ return this.forEachPart( this._retrieve_delim, data, function( part )
+ {
+ return _super.call( _self, part );
+ } ).join( this._parse_delim );
+ },
+
+
+ /**
+ * Determine DATA parts from the given delimiter DELIM
+ *
+ * Subtypes may override this method to change behavior or provide
+ * more sophisticated handling.
+ *
+ * @param {string} delim part delimiter
+ * @param {string} data delimited data
+ *
+ * @return {Array.<string>} items split by DELIM
+ */
+ 'virtual protected getParts': function( delim, data )
+ {
+ return ( ''+data ).split( delim );
+ },
+
+
+ /**
+ * Invoke CALLBACK for each part in DATA delimited by DELIM
+ *
+ * TODO: This can go away once ES3 compatibility can be dropped.
+ *
+ * @param {string} delim part delimiter
+ * @param {string} data delimited data
+ *
+ * @param {function(string)} callback formatter
+ *
+ * @return {Array.<string>} formatetd DATA parts as split by DELIM
+ */
+ 'virtual protected forEachPart': function( delim, data, callback )
+ {
+ var result = [],
+ parts = this.getParts( delim, data );
+
+ // maintain ES3 compatibility
+ for ( var i = 0; i < parts.length; i++ )
+ {
+ result.push( callback( parts[ i ] ) );
+ }
+
+ return result;
+ }
+} ); \ No newline at end of file
diff --git a/src/validate/formatter/MultiDimension.js b/src/validate/formatter/MultiDimension.js
new file mode 100644
index 0000000..e3d2f5c
--- /dev/null
+++ b/src/validate/formatter/MultiDimension.js
@@ -0,0 +1,116 @@
+/**
+ * Multi-dimensional array formatting
+ *
+ * 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' );
+
+
+/**
+ * Applies supertype for each item in a vector
+ */
+module.exports = Trait( 'MultiDimension' )
+ .implement( ValidatorFormatter )
+ .extend(
+{
+ /**
+ * Delimiter to combine values
+ * @type {string}
+ */
+ 'private _delim': '',
+
+
+ /**
+ * Initialize delimiter for parsing and retrieval
+ *
+ * DELIM will be used to split during parsing, and will be used to
+ * join formatted strings during retrieval.
+ *
+ * @param {string} delim delimiter
+ */
+ __mixin: function( delim )
+ {
+ this._delim = ''+delim;
+ },
+
+
+ /**
+ * Parse each item into a vector
+ *
+ * @param {string} data data to parse
+ *
+ * @return {Array} vector of data formatted for storage
+ */
+ 'virtual abstract override public parse': function( data )
+ {
+ var split = data.split( this._delim );
+
+ // maintain ES3 compatibility (no map)
+ for ( var i = 0; i < split.length; i++ )
+ {
+ split[ i ] = this.__super( split[ i ] );
+ }
+
+ return split;
+ },
+
+
+ /**
+ * Join formatted vector elements into a delimited string
+ *
+ * If DATA is not a vector, it will be treated as though it were a
+ * vector with a single element `[DATA]'.
+ *
+ * If all elements of DATA are the same value, then only that
+ * value will be returned; there will be no delimiters. This
+ * might be problematic if #parse is subsequently used, since that
+ * would change the number of elements in the vector.
+ *
+ * @param {Array|string} data vector to parse
+ *
+ * @return {string} delimited string
+ */
+ 'virtual abstract override public retrieve': function( data )
+ {
+ // pretend non-arrays are single-element vectors
+ if ( Object.prototype.toString.call( data ) !== '[object Array]' )
+ {
+ return this.__super( data );
+ }
+
+ var parsed = [],
+ same = true;
+
+ // must maintain ES3 support; no forEach
+ for ( var i = 0; i < data.length; i++ )
+ {
+ parsed[ i ] = this.__super( data[ i ] );
+
+ same = same && (
+ ( i === 0 )
+ || ( parsed[ i - 1 ] === parsed[ i ] )
+ );
+ }
+
+ return ( same )
+ ? parsed[ 0 ]
+ : parsed.join( this._delim );
+ }
+} );
diff --git a/src/validate/formatter/Number.js b/src/validate/formatter/Number.js
new file mode 100644
index 0000000..4adf3c8
--- /dev/null
+++ b/src/validate/formatter/Number.js
@@ -0,0 +1,88 @@
+/**
+ * Number 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 insurance limit(s)
+ */
+module.exports = Trait( 'Number' )
+ .implement( ValidatorFormatter )
+ .extend(
+{
+ /**
+ * Parse item as a number
+ *
+ * @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 number with thousands separators
+ *
+ * @param {string} data data to format for display
+ *
+ * @return {string} data formatted for display
+ */
+ 'virtual abstract override public retrieve': function( data )
+ {
+ return this.styleNumber( this.__super( data ) );
+ },
+
+
+ /**
+ * Style number with thousands separators
+ *
+ * @param {string} number number to style (digits only)
+ *
+ * @return {string} formatted number
+ */
+ 'virtual protected styleNumber': function( number )
+ {
+ var i = number.length,
+ ret = [],
+ chunk = '';
+
+ do
+ {
+ i -= 3;
+
+ // the second argument will adjust the length of the chunk
+ // if I is negative (e.g. 3 + -2 = 1)
+ chunk = number.substr(
+ ( i < 0 ) ? 0 : i,
+ Math.min( 3, 3 + i )
+ );
+
+ ret.unshift( chunk );
+ } while ( i > 0 );
+
+ return ret.join( ',' );
+ }
+} ); \ No newline at end of file
diff --git a/src/validate/formatter/PatternFormatter.js b/src/validate/formatter/PatternFormatter.js
new file mode 100644
index 0000000..43fccea
--- /dev/null
+++ b/src/validate/formatter/PatternFormatter.js
@@ -0,0 +1,140 @@
+/**
+ * Pattern-based validator-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 Class = require( 'easejs' ).Class,
+ ValidatorFormatter = require( '../ValidatorFormatter' );
+
+
+/**
+ * Data validation and formatting based on patterns and their
+ * replacements
+ */
+module.exports = Class( 'VFormat' )
+ .implement( ValidatorFormatter )
+ .extend(
+{
+ /**
+ * Pattern definition
+ * @type {Array.<Array>}
+ */
+ 'private _dfn': [],
+
+ /**
+ * Data retrieval format
+ * @type {Array}
+ */
+ 'private _retdfn': [],
+
+
+ /**
+ * Initialize with a pattern definition and return format definition
+ *
+ * The pattern definition should be an array of arrays with two elements:
+ * the pattern to match against and its replacement. The patterns must be
+ * regular expressions and the replacements may be either strings or
+ * functions.
+ *
+ * The return formatter is an optional single array consisting of a pattern
+ * and a replacement.
+ *
+ * @param {Array.<Array>} dfn pattern definition
+ * @param {Array=} retdfn return format definition
+ */
+ __construct: function( dfn, retdfn )
+ {
+ this._dfn = dfn;
+ this._retdfn = retdfn;
+ },
+
+
+ /**
+ * Format the given data or fail if no match is found
+ *
+ * If the given data matches a pattern, it will be formatted with respect to
+ * the first matched pattern. Otherwise, an error will be thrown indicating
+ * a validation failure.
+ *
+ * @param {string} data data to parse
+ *
+ * @return {string} formatted string, if a match is found
+ */
+ 'public parse': function( data )
+ {
+ var dfn = this._dfn;
+
+ // cast all data to a string
+ data = ''+( data );
+
+ var match;
+ for ( var i = 0, len = this._dfn.length; i < len; i += 2 )
+ {
+ if ( match = dfn[ i ].test( data ) )
+ {
+ var replace = dfn[ i + 1 ];
+
+ // minor optimization that may help on very large sets in
+ // poorly performing browsers; do not perform replacement if it
+ // it would result in an identical string
+ try
+ {
+ return ( ( replace === '$&' )
+ ? data
+ : data.replace( dfn[ i ], dfn[ i + 1 ] )
+ );
+ }
+ // throwing an exception within the replacement function is
+ // equivalent to saying "no match" and allows for more
+ // complicated logic that would otherwise overcomplicate a
+ // regex; fall through to continue to the next matcher
+ catch ( e ) {}
+ }
+ }
+
+ throw Error( 'No match for data: ' + data );
+ },
+
+
+ /**
+ * Retrieve data that may require formatting for display
+ *
+ * Return formatting is optional. No formatting will be done if no pattern
+ * was given when the instance was constructed.
+ *
+ * To ensure consistency and correctness, *any data returned by this method
+ * must be reversible* --- that is, parse( retrieve( data ) ) should not
+ * throw an exception.
+ *
+ * @param {string} data data to format for display
+ *
+ * @return {string} data formatted for display
+ */
+ 'public retrieve': function( data )
+ {
+ if ( !( this._retdfn ) )
+ {
+ return data;
+ }
+
+ return ( ''+data ).replace( this._retdfn[ 0 ], this._retdfn[ 1 ] );
+ }
+} );
+
diff --git a/src/validate/formatter/UnorderedList.js b/src/validate/formatter/UnorderedList.js
new file mode 100644
index 0000000..06625e4
--- /dev/null
+++ b/src/validate/formatter/UnorderedList.js
@@ -0,0 +1,112 @@
+/**
+ * Formatter for unordered lists
+ *
+ * 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 delimited items as an HTML unordered list, storing as a
+ * delimited string.
+ */
+module.exports = Trait( 'UnorderedList' )
+ .implement( ValidatorFormatter )
+ .extend(
+{
+ /**
+ * Format the given data as a delimited string
+ *
+ * HTML list elements will be stripped and items normalized
+ * (whitespace and empty items removed).
+ *
+ * @param {string} data data to parse
+ *
+ * @return {string} formatted string
+ */
+ 'virtual abstract override public parse': function( data )
+ {
+ // strip HTMl elements before processing (closing li tag
+ // is translated into a semicolon)
+ return this.getParts(
+ this.__super( data )
+ .replace( /<\/li>/g, ';' )
+ .replace( /\s*<.*?>\s*/g, '' )
+ ).join( '; ' );
+ },
+
+
+ /**
+ * Retrieve data that may require formatting for display
+ *
+ * Return formatting is optional. No formatting will be done if no pattern
+ * was given when the instance was constructed.
+ *
+ * To ensure consistency and correctness, *any data returned by this method
+ * must be reversible* --- that is, parse( retrieve( data ) ) should not
+ * throw an exception.
+ *
+ * @param {string} data data to format for display
+ *
+ * @return {string} data formatted for display
+ */
+ 'virtual abstract override public retrieve': function( data )
+ {
+ var parts = this.getParts( this.__super( data ) ),
+ items = '';
+
+ for ( var i = 0; i < parts.length; i++ )
+ {
+ var part = parts[ i ];
+
+ items += ( part === '' )
+ ? ''
+ : '<li>' + part + '</li>';
+ }
+
+ return ( items === '' )
+ ? ''
+ : "<ul>" + items + "</ul>";
+ },
+
+
+ /**
+ * Get trimmed, non-empty parts of semicolon-delimited string
+ *
+ * @param {string} input semicolon-delimited string
+ *
+ * @return {Array} non-empty trimmed parts
+ */
+ 'virtual protected getParts': function( data )
+ {
+ var parts = data.split( /(?:\s*;+\s*)+/ ),
+ ret = [];
+
+ for ( var i = 0; i < parts.length; i++ )
+ {
+ if ( parts[ i ] !== '' )
+ {
+ ret.push( parts[ i ] );
+ }
+ }
+
+ return ret;
+ }
+} );
diff --git a/src/validate/formatter/insurance/Limit.js b/src/validate/formatter/insurance/Limit.js
new file mode 100644
index 0000000..2664b47
--- /dev/null
+++ b/src/validate/formatter/insurance/Limit.js
@@ -0,0 +1,70 @@
+/**
+ * Insurance limit 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 insurance limit(s)
+ */
+module.exports = Trait( 'Limit' )
+ .implement( ValidatorFormatter )
+ .extend(
+{ /**
+ * Parse item as a number
+ *
+ * @param {string} data data to parse
+ *
+ * @return {string} data formatted for storage
+ */
+ 'virtual abstract override public parse': function( data )
+ {
+ return ( isNaN( parseInt( data ) ) )
+ ? data
+ : this.__super( data );
+ },
+
+
+ /**
+ * Format number with thousands separators
+ *
+ * @param {string} data data to format for display
+ *
+ * @return {string} data formatted for display
+ */
+ 'virtual abstract override public retrieve': function( data )
+ {
+ var number = parseFloat( data ),
+ is_numeric = !isNaN( number );
+
+ if ( !is_numeric )
+ {
+ return data;
+ }
+
+ return this.__super(
+ ( number < 1000 )
+ ? ''+( number * 1000 )
+ : data
+ );
+ }
+} );
diff --git a/src/validate/formatter/insurance/StandardLimitFormatter.js b/src/validate/formatter/insurance/StandardLimitFormatter.js
new file mode 100644
index 0000000..4305701
--- /dev/null
+++ b/src/validate/formatter/insurance/StandardLimitFormatter.js
@@ -0,0 +1,28 @@
+/**
+ * Formatter for standard limit format
+ *
+ * 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/>.
+ */
+
+/**
+ * Pre-configured insurance limit of the form N(/N)+
+ */
+module.exports = require( '../EchoFormatter' )
+ .use( require( '../Number' ) )
+ .use( require( './Limit' ) )
+ .use( require( '../MultiDelimited' )( '/' ) );
diff --git a/test/validate/formatter/AcceptRejectTest.js b/test/validate/formatter/AcceptRejectTest.js
new file mode 100644
index 0000000..3c9a6cc
--- /dev/null
+++ b/test/validate/formatter/AcceptRejectTest.js
@@ -0,0 +1,93 @@
+/**
+ * Accept/reject 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( '../../../' ),
+ Class = require( 'easejs' ).Class,
+ Sut = liza.validate.formatter.AcceptReject,
+ EchoFormatter = liza.validate.formatter.EchoFormatter,
+ ValidatorFormatter = liza.validate.ValidatorFormatter,
+ common = require( './common' ),
+ expect = require( 'chai' ).expect;
+
+var DummyFormatter = Class.implement( ValidatorFormatter )
+ .extend(
+{
+ 'virtual parse': function( data )
+ {
+ return '+' + data;
+ },
+
+ 'virtual retrieve': function( data )
+ {
+ return '-' + data;
+ },
+} );
+
+
+describe( 'validate.formatter.Number', function()
+{
+ common.testValidate( EchoFormatter.use( Sut )(), {
+ "": [ '' ],
+ "0": [ "0", "Rejected" ],
+ "1": [ "1", "Accepted" ],
+ "Rejected": [ "0", "Rejected" ],
+ "Accepted": [ "1", "Accepted" ],
+
+ // arbitrary text left alone
+ "foo": [ "foo" ],
+ } );
+
+
+ describe( '#parse', function()
+ {
+ it( 'considers accept/reject before supertype formatting', function()
+ {
+ // will equal +Accepted if supertype is called first
+ expect( DummyFormatter.use( Sut )().parse( 'Accepted' ) )
+ .to.equal( '1' );
+
+ // will equal +1 if supertype is called first
+ expect( DummyFormatter.use( Sut )().parse( '1' ) )
+ .to.equal( '1' );
+ } );
+ } );
+
+
+ describe( '#retrieve', function()
+ {
+ it( 'considers accept/reject before supertype formatting', function()
+ {
+ // will equal -1 if supertype is called first
+ expect( DummyFormatter.use( Sut )().retrieve( '1' ) )
+ .to.equal( 'Accepted' );
+ } );
+ } );
+
+
+ common.testMixin(
+ EchoFormatter,
+ Sut,
+ 'asdf',
+ 'given',
+ 'asdfgiven',
+ 'asdfgiven'
+ );
+} );
diff --git a/test/validate/formatter/EchoFormatterTest.js b/test/validate/formatter/EchoFormatterTest.js
new file mode 100644
index 0000000..01133de
--- /dev/null
+++ b/test/validate/formatter/EchoFormatterTest.js
@@ -0,0 +1,65 @@
+/**
+ * Tests echo list 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 liza = require( '../../../' ),
+ Sut = liza.validate.formatter.EchoFormatter,
+ testValidate = require( './common' ).testValidate,
+ expect = require( 'chai' ).expect;
+
+
+describe( 'EchoListFormatter', function()
+{
+ testValidate( Sut(), {
+ "": [ "" ],
+ "foo": [ "foo" ],
+ " 123 ": [ " 123 " ],
+ } );
+
+
+ describe( 'as a supertype', function()
+ {
+ it( 'permits overriding #parse', function()
+ {
+ var expected = 'parsed';
+
+ expect(
+ Sut.extend(
+ {
+ 'override parse': function( _ ) { return expected; }
+ } )().parse( 'foo' )
+ ).to.equal( expected );
+ } );
+
+
+ it( 'permits overriding #retrieve', function()
+ {
+ var expected = 'retrieved';
+
+ expect(
+ Sut.extend(
+ {
+ 'override retrieve': function( _ ) { return expected; }
+ } )().retrieve( 'foo' )
+ ).to.equal( expected );
+ } );
+ } );
+} ); \ No newline at end of file
diff --git a/test/validate/formatter/MultiDelimitedTest.js b/test/validate/formatter/MultiDelimitedTest.js
new file mode 100644
index 0000000..cc411db
--- /dev/null
+++ b/test/validate/formatter/MultiDelimitedTest.js
@@ -0,0 +1,71 @@
+/**
+ * Tests delimited formatting
+ *
+ * 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 Class = require( 'easejs' ).Class,
+ liza = require( '../../../' ),
+ formatter = liza.validate.formatter,
+ Sut = formatter.MultiDelimited,
+ EchoFormatter = formatter.EchoFormatter,
+ ValidatorFormatter = liza.validate.ValidatorFormatter,
+ common = require( './common' ),
+ expect = require( 'chai' ).expect;
+
+var DummyFormatter = Class.implement( ValidatorFormatter )
+ .extend(
+{
+ 'virtual parse': function( data )
+ {
+ return '+' + data;
+ },
+
+ 'virtual retrieve': function( data )
+ {
+ return '-' + data;
+ },
+} );
+
+
+describe( 'validate.formatter.MultiDelimited', function()
+{
+ var sut = DummyFormatter.use( Sut( ',', '|' ) )();
+
+ common.testValidate( sut, {
+ "": [ "+", "-+" ],
+ "abc": [ "+abc", "-+abc" ],
+ "abc,123": [ "+abc|+123", "-+abc,-+123" ],
+ " 1122 ": [ "+ 1122 ", "-+ 1122 " ],
+ " 1122 ,34": [ "+ 1122 |+34", "-+ 1122 ,-+34" ],
+ } );
+
+
+ // sane default behavior
+ it( 'defaults retrieve delimeter to parse delimiter', function()
+ {
+ var sut = DummyFormatter.use( Sut( '!' ) )();
+
+ expect( sut.parse( "abc!123" ) )
+ .to.equal( "+abc!+123" );
+
+ expect( sut.retrieve( "abc!123" ) )
+ .to.equal( "-abc!-123" );
+ } );
+} );
diff --git a/test/validate/formatter/MultiDimensionTest.js b/test/validate/formatter/MultiDimensionTest.js
new file mode 100644
index 0000000..0f700ac
--- /dev/null
+++ b/test/validate/formatter/MultiDimensionTest.js
@@ -0,0 +1,109 @@
+/**
+ * Multi-dimensional array formatting 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 Class = require( 'easejs' ).Class,
+ liza = require( '../../../' ),
+ formatter = liza.validate.formatter,
+ Sut = formatter.MultiDimension,
+ EchoFormatter = formatter.EchoFormatter,
+ ValidatorFormatter = liza.validate.ValidatorFormatter,
+ common = require( './common' ),
+ expect = require( 'chai' ).expect;
+
+var DummyFormatter = Class.implement( ValidatorFormatter )
+ .extend(
+{
+ 'virtual parse': function( data )
+ {
+ return '+' + data;
+ },
+
+ 'virtual retrieve': function( data )
+ {
+ return '-' + data;
+ },
+} );
+
+
+describe( 'validate.formatter.MultiDimension', function()
+{
+ describe( '#parse', function()
+ {
+ it( 'splits on delimiter into vector', function()
+ {
+ expect(
+ DummyFormatter.use( Sut( '||' ) )()
+ .parse( 'foo||bar||baz' )
+ ).to.deep.equal( [ '+foo', '+bar', '+baz' ] );
+ } );
+
+
+ it( 'produces vector for non-delimited strings', function()
+ {
+ expect(
+ DummyFormatter.use( Sut( '||' ) )()
+ .parse( 'foo' )
+ ).to.deep.equal( [ '+foo' ] );
+ } );
+ } );
+
+
+ describe( '#retrieve', function()
+ {
+ it( 'applies formatting to each element in vector', function()
+ {
+ expect(
+ DummyFormatter.use( Sut( '||' ) )()
+ .retrieve( [ 'one', 'two', 'three' ] )
+ ).to.equal( '-one||-two||-three' );
+ } );
+
+
+ it( 'treats scalars as single-element vectors', function()
+ {
+ expect(
+ DummyFormatter.use( Sut( '||' ) )()
+ .retrieve( 'one' )
+ ).to.equal( '-one' );
+ } );
+
+
+ describe( 'given identical elements', function()
+ {
+ it( 'combines if all elements are identical', function()
+ {
+ expect(
+ DummyFormatter.use( Sut( '||' ) )()
+ .retrieve( [ 'foo', 'foo', 'foo' ] )
+ ).to.equal( '-foo' );
+ } );
+
+
+ it( 'does not combine if not all are identical', function()
+ {
+ expect(
+ DummyFormatter.use( Sut( '||' ) )()
+ .retrieve( [ 'foo', 'foo', 'bar' ] )
+ ).to.equal( '-foo||-foo||-bar' );
+ } );
+ } );
+ } );
+} );
diff --git a/test/validate/formatter/NumberTest.js b/test/validate/formatter/NumberTest.js
new file mode 100644
index 0000000..74d2595
--- /dev/null
+++ b/test/validate/formatter/NumberTest.js
@@ -0,0 +1,50 @@
+/**
+ * Number 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.Number,
+ EchoFormatter = liza.validate.formatter.EchoFormatter,
+ common = require( './common' );
+
+
+describe( 'validate.formatter.Number', function()
+{
+ common.testValidate( EchoFormatter.use( Sut )(), {
+ "1": [ "1", "1" ],
+ "123": [ "123", "123" ],
+ "12345": [ "12345", "12,345" ],
+ "12,345": [ "12345", "12,345" ],
+ ",12,345": [ "12345", "12,345" ],
+ "12,345,": [ "12345", "12,345" ],
+ " 12,345 ,": [ "12345", "12,345" ],
+ " 1, ,": [ "1", "1" ],
+ } );
+
+
+ common.testMixin(
+ EchoFormatter,
+ Sut,
+ '123',
+ '4567',
+ '1234567',
+ '1,234,567'
+ );
+} );
diff --git a/test/validate/formatter/PatternFormatterTest.js b/test/validate/formatter/PatternFormatterTest.js
new file mode 100644
index 0000000..749d428
--- /dev/null
+++ b/test/validate/formatter/PatternFormatterTest.js
@@ -0,0 +1,124 @@
+/**
+ * Test pattern-based validator-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 liza = require( '../../../' ),
+ Sut = liza.validate.formatter.PatternFormatter,
+ VFmt = liza.validate.ValidatorFormatter,
+ Class = require( 'easejs' ).Class,
+ expect = require( 'chai' ).expect,
+ assert = require( 'assert' ),
+ dfn = [
+ /^kitten/, '$&s',
+ /^[a-z]+/, 'Foo',
+ /^[0-9]([0-9]+)/, '$1',
+ ];
+
+
+describe( 'PatternFormatter', function()
+{
+ it( 'is a ValidatorFormatter', function()
+ {
+ expect( Class.isA( VFmt, createSut( [] ) ) )
+ .to.be.true;
+ } );
+
+
+ describe( '#parse', function()
+ {
+ it( 'formats string according to given definition', function()
+ {
+ var sut = createSut( dfn );
+
+ // this first test also ensures that the very first match
+ // in dfn takes precedence
+ [
+ [ 'kitten', 'kittens' ],
+ [ 'abcd', 'Foo' ],
+ [ '0123', '123' ],
+ ].forEach( function( test )
+ {
+ assert.equal( sut.parse( test[ 0 ] ), test[ 1 ] );
+ } );
+ } );
+
+
+ // validation error
+ it( 'throws an exception if no match is found', function()
+ {
+ assert.throws( function()
+ {
+ // cannot possibly match anything
+ createSut( [] ).parse( 'foo' );
+ }, Error );
+ } );
+
+
+ /**
+ * To support complex logic that may be difficult to express
+ * (or not worth expressing due to verbosity required with JS's
+ * regex impl.), we permit throwing an exception in a
+ * replacement function to result in the equivalent of "no
+ * match".
+ */
+ it( 'yields no match given exception during replacement', function()
+ {
+ var val = 'bar',
+ sut = createSut( [
+ /^fo/, function() { throw Error( 'ignore me' ); },
+ /^foo/, val,
+ ] );
+
+ assert.equal( val, sut.parse( 'foo' ),
+ "Should ignore matches that throw exceptions"
+ );
+ } );
+ } );
+
+
+ describe( '#retrieve', function()
+ {
+ it( 'retrieval does not format data by default', function()
+ {
+ var str = 'foo';
+ assert.equal( createSut( [] ).retrieve( str ), str );
+ } );
+
+
+ it( 'formats return data according to given definition', function()
+ {
+ // the dfn is technically not required, but for the sake
+ // of a "proper" demonstration, it will be included
+ var dfn = [ [ /-/, '' ] ],
+ retdfn = [ /[a-z]/g, '$&-' ];
+
+ assert.equal(
+ createSut( dfn, retdfn ).retrieve( 'foo' ),
+ 'f-o-o-'
+ );
+ } );
+ } );
+} );
+
+
+function createSut( dfn, retdfn )
+{
+ return Sut( dfn, retdfn );
+}
diff --git a/test/validate/formatter/UnorderedListTest.js b/test/validate/formatter/UnorderedListTest.js
new file mode 100644
index 0000000..6802239
--- /dev/null
+++ b/test/validate/formatter/UnorderedListTest.js
@@ -0,0 +1,152 @@
+/**
+ * Tests unordered list 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 liza = require( '../../../' ),
+ Sut = liza.validate.formatter.UnorderedList,
+ EchoFormatter = liza.validate.formatter.EchoFormatter,
+ common = require( './common' );
+
+
+describe( 'UnorderedList', function()
+{
+ common.testValidate( EchoFormatter.use( Sut )(), {
+ "": [ "", "" ],
+ "no semi": [ "no semi", "<ul><li>no semi</li></ul>" ],
+
+ "semi; colon": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ "semi;colon": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ "semi; colon": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ "semi ; colon": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ "semi ;colon": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ "semi;;;colon": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ "semi ; ;; colon": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ ";semi;colon": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ ";semi": [
+ "semi",
+ "<ul><li>semi</li></ul>"
+ ],
+ " ; semi": [
+ "semi",
+ "<ul><li>semi</li></ul>"
+ ],
+ "semi;colon;": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ ";semi;": [
+ "semi",
+ "<ul><li>semi</li></ul>"
+ ],
+ "semi;": [
+ "semi",
+ "<ul><li>semi</li></ul>"
+ ],
+ "semi ; ": [
+ "semi",
+ "<ul><li>semi</li></ul>"
+ ],
+ ";": [
+ "",
+ ""
+ ],
+ " ; ": [
+ "",
+ ""
+ ],
+
+ // single
+ "<ul><li>no semi</li></ul>": [
+ "no semi",
+ "<ul><li>no semi</li></ul>"
+ ],
+ // multi
+ "<ul><li>semi</li><li>colon</li></ul>": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ // ensure that all li elements are replaced globally
+ "<ul><li>foo</li><li>bar</li><li>baz</li></ul>": [
+ "foo; bar; baz",
+ "<ul><li>foo</li><li>bar</li><li>baz</li></ul>"
+ ],
+ // extra whitespace
+ " <ul><li>semi </li> <li>colon </li></ul> ": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ // malformed
+ " <li>semi </li> <li>colon </li></ul> ": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ // malformed
+ " <li>no semi </li> <li>": [
+ "no semi",
+ "<ul><li>no semi</li></ul>"
+ ],
+ // empty node
+ "<ul><li>no semi</li><li></li></ul>": [
+ "no semi",
+ "<ul><li>no semi</li></ul>"
+ ],
+
+ // implementation consequence; no way to escape a semicolon
+ "<ul><li>semi;colon</li></ul>": [
+ "semi; colon",
+ "<ul><li>semi</li><li>colon</li></ul>"
+ ],
+ } );
+
+
+ common.testMixin(
+ EchoFormatter,
+ Sut,
+ 'foo;',
+ 'bar',
+ 'foo; bar',
+ '<ul><li>foo</li><li>bar</li></ul>'
+ );
+} );
diff --git a/test/validate/formatter/common.js b/test/validate/formatter/common.js
new file mode 100644
index 0000000..2d0a292
--- /dev/null
+++ b/test/validate/formatter/common.js
@@ -0,0 +1,140 @@
+/**
+ * Common validator-formatter test functions
+ *
+ * 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( '../../../' ),
+ VFmt = liza.validate.ValidatorFormatter,
+ Class = require( 'easejs' ).Class,
+ expect = require( 'chai' ).expect;
+
+
+module.exports = {
+ testValidate: function( sut, tests )
+ {
+ it( 'is a ValidatorFormatter', function()
+ {
+ expect( Class.isA( VFmt, sut ) )
+ .to.equal( true, 'Is not a ValidatorFormatter' );
+ } );
+
+
+ Object.keys( tests ).forEach( function( data )
+ {
+ var failure = false,
+ err = function() { failure = true; },
+ result = '',
+ fmt = '',
+ expected = tests[ data ];
+
+ try
+ {
+ result = sut.parse( data );
+ }
+ catch ( e )
+ {
+ failure = true;
+ }
+
+ if ( expected === false )
+ {
+ it( 'fails on ' + data, function()
+ {
+ expect( failure ).to.equal(
+ true,
+ ( data + " should yield error" )
+ );
+ } );
+
+ return;
+ }
+
+ fmt = sut.retrieve( result );
+
+ var expval = ( ( expected[ 0 ] === true ) ? data : expected[ 0 ] ),
+ retval = ( ( expected[ 1 ] === true )
+ ? data
+ : ( expected[ 1 ] === undefined ) ? data : expected[ 1 ]
+ );
+
+ // convert to store in bucket
+ it ( 'parses "' + data + '" as "' + expval + '"', function()
+ {
+ expect( result ).to.equal(
+ expval,
+ ( data + " !-> " + expval + ' (=>' + result + ')' )
+ );
+ } );
+
+ // retrieve value, formatted
+ it ( 'retrieves "' + result + '" as "' + retval + '"', function()
+ {
+ expect( fmt ).to.equal(
+ retval,
+ ( result + " !~> " + retval + ' (=>' + fmt + ')' )
+ );
+ } );
+ } );
+ },
+
+
+ /**
+ * Test that mixin respects supertype data
+ *
+ * @param {Function} Super supertype constructor to extend
+ * @param {Trait} Sut SUT trait
+ * @param {string} base string to serve as base to data
+ * @param {string} given given data to pass to extended Super
+ * @param {string} parse expected #parse result
+ * @param {string} retrieve expected #retrieve result
+ *
+ * @return {undefined}
+ */
+ testMixin: function( Super, Sut, base, given, parse, retrieve )
+ {
+ describe( 'as a mixin', function()
+ {
+ var sut = Super.extend(
+ {
+ 'virtual override parse': function( data )
+ {
+ return base + data;
+ },
+ 'virtual override retrieve': function( data )
+ {
+ return base + data;
+ }
+ } ).use( Sut )();
+
+
+ it( 'respects supertype #parse', function()
+ {
+ expect( sut.parse( given ) )
+ .to.equal( parse );
+ } );
+
+
+ it( 'respects supertype #retrieve', function()
+ {
+ expect( sut.retrieve( given ) )
+ .to.equal( retrieve );
+ } );
+ } );
+ },
+};
diff --git a/test/validate/formatter/insurance/LimitTest.js b/test/validate/formatter/insurance/LimitTest.js
new file mode 100644
index 0000000..33b7e5e
--- /dev/null
+++ b/test/validate/formatter/insurance/LimitTest.js
@@ -0,0 +1,68 @@
+/**
+ * Tests insurance limit 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 Class = require( 'easejs' ).Class,
+ liza = require( '../../../../' ),
+ Sut = liza.validate.formatter.insurance.Limit,
+ EchoFormatter = liza.validate.formatter.EchoFormatter,
+ ValidatorFormatter = liza.validate.ValidatorFormatter,
+ common = require( '../common' ),
+ expect = require( 'chai' ).expect;
+
+var DummyFormatter = Class.implement( ValidatorFormatter )
+ .extend(
+{
+ 'virtual parse': function( data )
+ {
+ return '+' + data;
+ },
+
+ 'virtual retrieve': function( data )
+ {
+ return '-' + data;
+ },
+} );
+
+
+describe( 'validate.formatter.insurance.Limit', function()
+{
+ common.testValidate( DummyFormatter.use( Sut )(), {
+ // plain strings are ignored (and do not invoke supertype)
+ "": [ "" ],
+ "abc": [ "abc" ],
+ "abc_": [ "abc_" ],
+ "_ -": [ "_ -" ],
+
+ // numbers >3 digits echoed
+ "1234": [ "+1234", "-+1234" ],
+ "123456": [ "+123456", "-+123456" ],
+ } );
+
+
+ // 3-digit abbreviations are converted *on retrieval* (we'll often
+ // be styling existing data, so we don't want to rely on prior
+ // conversion)
+ common.testValidate( EchoFormatter.use( Sut )(), {
+ "100": [ "100", "100000" ],
+ "500": [ "500", "500000" ],
+ } );
+} );