Skip to content
Browse files

Add doc to the tap method on value resolution and clean up the place…

…s that unnecessarily used isdefined checks
  • Loading branch information...
1 parent cdbe69b commit 42a381bd186c89022a0cc319a2d970c6312cc01b @vybs vybs committed
Showing with 239 additions and 33 deletions.
  1. +48 −32 lib/dust-helpers.js
  2. +191 −1 test/jasmine-test/spec/helpersTests.js
View
80 lib/dust-helpers.js
@@ -36,7 +36,7 @@ function filter(chunk, context, bodies, params, filterOp) {
actualKey,
expectedValue,
filterOpType = params.filterOpType || '';
- // when @eq, @lt etc are used as standalone helpers, key is defined
+ // when @eq, @lt etc are used as standalone helpers, key is required and hence check for defined
if ( typeof params.key !== "undefined") {
actualKey = dust.helpers.tap(params.key, chunk, context);
}
@@ -92,13 +92,27 @@ function coerce (value, type, context) {
var helpers = {
// Utility helping to resolve dust references in the given chunk
- // returns "undefined" when unable to resolve a value, since it relies on Chunk.reference method
+ // uses the Chunk.render method to resolve value
+ /*
+ Reference resolution rules:
+ if value exists in JSON:
+ "" or '' will evaluate to false, boolean false, null, or undefined will evaluate to false,
+ numeric 0 evaluates to true, so does, string "0", string "null", string "undefined" and string "false".
+ Also note that empty array -> [] is evaluated to false and empty object -> {} and non-empty object are evaluated to true
+
+ if value does not exist in JSON and the input is a single reference: {x}
+ dust render emits empty string, and we then return false
+
+ if values does not exist in JSON and the input is a chain of references : {x} < {y}
+ dust render emits < and we return the partial output
+
+ */
"tap": function( input, chunk, context ){
// return given input if there is no dust reference to resolve
var output = input;
- // dust compiles a string to function, if there are references
+ // dust compiles a string/reference such as {foo} to function,
if( typeof input === "function"){
- // just a plain function/ lamda in the context, not a dust `body` function created by the dust compiler
+ // just a plain function (a.k.a anonymous functions) in the context, not a dust `body` function created by the dust compiler
if( input.isFunction === true ){
output = input();
} else {
@@ -216,26 +230,22 @@ var helpers = {
* @param operand is the second value needed for operations like mod, add, subtract, etc.
*/
"math": function ( chunk, context, bodies, params ) {
- //make sure we have key and method params before continuing
+ //key and method are required for further processing
if( params && typeof params.key !== "undefined" && params.method ){
var key = params.key,
method = params.method,
- operand = params.operand || null,
+ // operand can be null for "abs", ceil and floor
+ operand = params.operand,
mathOut = null,
operError = function(){_console.log("operand is required for this math method"); return null;};
key = dust.helpers.tap(key, chunk, context);
operand = dust.helpers.tap(operand, chunk, context);
- // cannot resolve/find the operand in the context from the tap method
- if( typeof operand === 'undefined' )
- {
- operError();
- } else {
// TODO: handle and tests for negatives and floats in all math operations
switch(method) {
case "mod":
- if(operand === 0) {
- _console.log("operand for mod operation is 0: expect NaN!");
- }
+ if(operand === 0 || operand === -0) {
+ _console.log("operand for divide operation is 0/-0: expect Nan!");
+ }
mathOut = parseFloat(key) % parseFloat(operand);
break;
case "add":
@@ -248,8 +258,8 @@ var helpers = {
mathOut = parseFloat(key) * parseFloat(operand);
break;
case "divide":
- if(operand === 0) {
- _console.log("operand for divide operation is 0: expect Nan!");
+ if(operand === 0 || operand === -0) {
+ _console.log("operand for divide operation is 0/-0: expect Nan/Infinity!");
}
mathOut = parseFloat(key) / parseFloat(operand);
break;
@@ -264,7 +274,6 @@ var helpers = {
break;
default:
_console.log( "method passed is not supported" );
- }
}
if (mathOut !== null){
@@ -296,6 +305,7 @@ var helpers = {
**/
"select": function(chunk, context, bodies, params) {
var body = bodies.block;
+ // key is required for processing, hence check for defined
if( params && typeof params.key !== "undefined"){
// returns given input as output, if the input is not a dust reference, else does a context lookup
var key = dust.helpers.tap(params.key, chunk, context);
@@ -347,8 +357,9 @@ var helpers = {
"ne": function(chunk, context, bodies, params) {
if(params) {
params.filterOpType = "ne";
+ return filter(chunk, context, bodies, params, function(expected, actual) { return actual !== expected; });
}
- return filter(chunk, context, bodies, params, function(expected, actual) { return actual !== expected; });
+ return chunk;
},
/**
@@ -364,9 +375,9 @@ var helpers = {
**/
"lt": function(chunk, context, bodies, params) {
if(params) {
- params.filterOpType = "lt";
- }
- return filter(chunk, context, bodies, params, function(expected, actual) { return actual < expected; });
+ params.filterOpType = "lt";
+ return filter(chunk, context, bodies, params, function(expected, actual) { return actual < expected; });
+ }
},
/**
@@ -382,9 +393,10 @@ var helpers = {
**/
"lte": function(chunk, context, bodies, params) {
if(params) {
- params.filterOpType = "lte";
- }
- return filter(chunk, context, bodies, params, function(expected, actual) { return actual <= expected; });
+ params.filterOpType = "lte";
+ return filter(chunk, context, bodies, params, function(expected, actual) { return actual <= expected; });
+ }
+ return chunk;
},
@@ -400,10 +412,12 @@ var helpers = {
Note : use type="number" when comparing numeric
**/
"gt": function(chunk, context, bodies, params) {
- if(params) {
- params.filterOpType = "gt";
- }
- return filter(chunk, context, bodies, params, function(expected, actual) { return actual > expected; });
+ // if no params do no go further
+ if(params) {
+ params.filterOpType = "gt";
+ return filter(chunk, context, bodies, params, function(expected, actual) { return actual > expected; });
+ }
+ return chunk;
},
/**
@@ -419,18 +433,20 @@ var helpers = {
**/
"gte": function(chunk, context, bodies, params) {
if(params) {
- params.filterOpType = "gte";
- }
- return filter(chunk, context, bodies, params, function(expected, actual) { return actual >= expected; });
+ params.filterOpType = "gte";
+ return filter(chunk, context, bodies, params, function(expected, actual) { return actual >= expected; });
+ }
+ return chunk;
},
// to be used in conjunction with the select helper
// TODO: fix the helper to do nothing when used standalone
"default": function(chunk, context, bodies, params) {
+ // does not require any params
if(params) {
params.filterOpType = "default";
}
- return filter(chunk, context, bodies, params, function(expected, actual) { return true; });
+ return filter(chunk, context, bodies, params, function(expected, actual) { return true; });
},
/**
View
192 test/jasmine-test/spec/helpersTests.js
@@ -56,6 +56,27 @@ var helpersTests = [
message: "testing math/mod helper with zero as key value"
},
{
+ name: "math/mod helper with zero as key value",
+ source: '<div>{@math key="0" method="mod" operand="-16"/}</div>',
+ context: {},
+ expected: "<div>0</div>",
+ message: "testing math/mod helper with zero as key value"
+ },
+ {
+ name: "math/mod helper with zero as key value and operand as variable as variable without quotes",
+ source: '<div>{@math key="0" method="mod" operand=y/}</div>',
+ context: { y: 4},
+ expected: "<div>0</div>",
+ message: "testing math/mod helper with zero as key value and operand as variable without quotes"
+ },
+ {
+ name: "math/mod helper with zero as key value and operand as variable with quotes",
+ source: '<div>{@math key="0" method="mod" operand="{y}"/}</div>',
+ context: { y: 4},
+ expected: "<div>0</div>",
+ message: "testing math/mod helper with zero as key value and operand as variable with quotes"
+ },
+ {
name: "math/mod helper with zero as operand value",
source: '<div>{@math key="0" method="mod" operand="0"/}</div>',
context: {},
@@ -63,6 +84,13 @@ var helpersTests = [
message: "testing math/mod helper with zero as operand value"
},
{
+ name: "math/mod helper with negative zero as operand value",
+ source: '<div>{@math key="0" method="mod" operand="-0"/}</div>',
+ context: {},
+ expected: "<div>NaN</div>",
+ message: "testing math/mod helper with negative zero as operand value"
+ },
+ {
name: "math/divide helper with zero as key value",
source: '<div>{@math key="0" method="divide" operand="16"/}</div>',
context: {},
@@ -91,6 +119,13 @@ var helpersTests = [
message: "should test the math/mod helper using $idx"
},
{
+ name: "math helper mod using $idx without quotes with lizt size = 2",
+ source: '{#list}<div>{@math key="{$idx}" method="mod" operand="2"/}</div>{/list}',
+ context: { list: [ { y: 'foo' }, { y: "bar"} ]},
+ expected: "<div>0</div><div>1</div>",
+ message: "should test the math/mod helper using $idx without quotes with lizt size = 2"
+ },
+ {
name: "math helper mod using $idx without quotes",
source: '{#list}<div>{@math key=$idx method="mod" operand="5"/}</div>{/list}',
context: { list: [ { y: 'foo' } ]},
@@ -98,6 +133,27 @@ var helpersTests = [
message: "should test the math/mod helper using $idx without quotes"
},
{
+ name: "math helper mod using $idx without quotes with lizt size = 2",
+ source: '{#list}<div>{@math key=$idx method="mod" operand="2"/}</div>{/list}',
+ context: { list: [ { y: 'foo' }, { y: "bar"} ]},
+ expected: "<div>0</div><div>1</div>",
+ message: "should test the math/mod helper using $idx without quotes with lizt size = 2"
+ },
+ {
+ name: "math helper mod using $len",
+ source: '{#list}<div>{@math key="{$len}" method="mod" operand="5"/}</div>{/list}',
+ context: { list: [ { y: 'foo' } ]},
+ expected: "<div>1</div>",
+ message: "should test the math/mod helper using $len"
+ },
+ {
+ name: "math helper mod using $len without quotes",
+ source: '{#list}<div>{@math key=$len method="mod" operand="5"/}</div>{/list}',
+ context: { list: [ { y: 'foo' } ]},
+ expected: "<div>1</div>",
+ message: "should test the math/mod helper using $len without quotes"
+ },
+ {
name: "math helper subtract numbers",
source: '<div>{@math key="16" method="subtract" operand="4"/}</div>',
context: {},
@@ -105,6 +161,13 @@ var helpersTests = [
message: "testing math/subtract helper with two numbers"
},
{
+ name: "math helper add with key as negative number",
+ source: '<div>{@math key="-16" method="add" operand="4"/}</div>',
+ context: {},
+ expected: "<div>-12</div>",
+ message: "testing math/add helper with key as negative number"
+ },
+ {
name: "math helper subtract with key as negative number",
source: '<div>{@math key="-16" method="subtract" operand="4"/}</div>',
context: {},
@@ -112,6 +175,27 @@ var helpersTests = [
message: "testing math/subtract helper with key as negative number"
},
{
+ name: "math helper multiply with key as negative number",
+ source: '<div>{@math key="-2" method="multiply" operand="4"/}</div>',
+ context: {},
+ expected: "<div>-8</div>",
+ message: "testing math/multiply helper with key as negative number"
+ },
+ {
+ name: "math helper multiply with key as negative number and variable operand without quotes",
+ source: '<div>{@math key="-2" method="multiply" operand=y/}</div>',
+ context: { y:4},
+ expected: "<div>-8</div>",
+ message: "testing math/multiply helper with key as negative number and variable operand without quotes"
+ },
+ {
+ name: "math helper multiply with key as negative number and variable operand with quotes",
+ source: '<div>{@math key="-2" method="multiply" operand="{y}"/}</div>',
+ context: { y:4},
+ expected: "<div>-8</div>",
+ message: "testing math/multiply helper with key as negative number and variable operand with quotes"
+ },
+ {
name: "math helper add negative numbers",
source: '<div>{@math key="-16" method="add" operand="-4"/}</div>',
context: {},
@@ -119,7 +203,28 @@ var helpersTests = [
message: "testing math/add helper with negative numbers"
},
{
- name: "math helper zero key",
+ name: "math helper subtract negative numbers",
+ source: '<div>{@math key="-16" method="subtract" operand="-4"/}</div>',
+ context: {},
+ expected: "<div>-12</div>",
+ message: "testing math/subtract helper with negative numbers"
+ },
+ {
+ name: "math helper multiply negative numbers",
+ source: '<div>{@math key="-0" method="multiply" operand="-4"/}</div>',
+ context: {},
+ expected: "<div>0</div>",
+ message: "testing math/multiply helper with negative numbers"
+ },
+ {
+ name: "math helper blah operation",
+ source: '{@math key="-0" method="blah" operand="-4"/}',
+ context: {},
+ expected: "",
+ message: "math helper blah operation"
+ },
+ {
+ name: "math helper key as zero",
source: '<div>{@math key="0" method="subtract" operand="0"/}</div>',
context: {},
expected: "<div>0</div>",
@@ -133,6 +238,13 @@ var helpersTests = [
message: "testing math helper with zero key"
},
{
+ name: "math helper zero key and operand for divide",
+ source: '<div>{@math key="0" method="divide" operand="0"/}</div>',
+ context: {},
+ expected: "<div>NaN</div>",
+ message: "testing math helper with zero key and operand for divide"
+ },
+ {
name: "math helper zero operand",
source: '<div>{@math key="16" method="subtract" operand="0"/}</div>',
context: {},
@@ -168,6 +280,69 @@ var helpersTests = [
message: "testing math/divide helper with variable as operand"
},
{
+ name: "math helper divide with null as key and operand value",
+ source: '<div>{@math key="{y}" method="divide" operand="{y}"/}</div>',
+ context: { y : null},
+ expected: "<div>NaN</div>",
+ message: "testing math/divide helper with null as key and operand value"
+ },
+ {
+ name: "math helper divide with null as operand value",
+ source: '<div>{@math key="16" method="divide" operand="{y}"/}</div>',
+ context: { y : null},
+ expected: "<div>NaN</div>",
+ message: "testing math/divide helper with null as operand value"
+ },
+ {
+ name: "math helper divide with null as undefined value",
+ source: '<div>{@math key="16" method="divide" operand="{y}"/}</div>',
+ context: { y : undefined},
+ expected: "<div>NaN</div>",
+ message: "testing math/divide helper with null as undefined value"
+ },
+ {
+ name: "math helper mod with negative 0 as operand",
+ source: '<div>{@math key="16" method="mod" operand="{y}"/}</div>',
+ context: { y : -0 },
+ expected: "<div>NaN</div>",
+ message: "testing math/mod helper with negative 0 as operand"
+ },
+ {
+ name: "math helper mod with null as key and operand",
+ source: '<div>{@math key="{y}" method="mod" operand="{y}"/}</div>',
+ context: { y : null },
+ expected: "<div>NaN</div>",
+ message: "testing math helper mod with null as key and operand"
+ },
+ {
+ name: "math helper divide using negative value for variable",
+ source: '<div>{@math key="16" method="divide" operand="{y}"/}</div>',
+ context: { y : -4 },
+ expected: "<div>-4</div>",
+ message: "testing math/divide helper using negative value for variable as operand"
+ },
+ {
+ name: "math helper divide using key as non numeric",
+ source: '<div>{@math key="doh" method="divide" operand="{y}"/}</div>',
+ context: { y : 0 },
+ expected: "<div>NaN</div>",
+ message: "testing math/divide helper using key as non numeric"
+ },
+ {
+ name: "math helper divide using 0 for variable",
+ source: '<div>{@math key="16" method="divide" operand="{y}"/}</div>',
+ context: { y : 0 },
+ expected: "<div>Infinity</div>",
+ message: "testing math/divide helper using 0 for variable as operand"
+ },
+ {
+ name: "math helper divide using negative 0 for variable",
+ source: '<div>{@math key="16" method="divide" operand="{y}"/}</div>',
+ context: { y : -0 },
+ expected: "<div>Infinity</div>",
+ message: "testing math/divide helper using negative 0 for variable as operand"
+ },
+ {
name: "math helper floor numbers",
source: '<div>{@math key="16.5" method="floor"/}</div>',
context: {},
@@ -181,6 +356,14 @@ var helpersTests = [
expected: "<div>17</div>",
message: "testing math/ceil helper with two numbers"
},
+
+ {
+ name: "math helper abs numbers with missing key",
+ source: '<div>{@math key="{key}" method="abs"/}</div>',
+ context: {},
+ expected: "<div>NaN</div>",
+ message: "testing math/abs helper with missing key"
+ },
{
name: "math helper abs numbers",
source: '<div>{@math key="-16" method="abs"/}</div>',
@@ -189,6 +372,13 @@ var helpersTests = [
message: "testing math/abs helper with two numbers"
},
{
+ name: "math helper abs numbers with null key",
+ source: '<div>{@math key="{key}" method="abs"/}</div>',
+ context: {key : null},
+ expected: "<div>NaN</div>",
+ message: "testing math/abs helper with null key"
+ },
+ {
name: "math helper eq filter",
source: '<div>{@math key="-13" method="abs"}{@eq value=13}Test is true{/eq}{/math}</div>',
context: {},

0 comments on commit 42a381b

Please sign in to comment.
Something went wrong with that request. Please try again.