diff options
author | Yonaba <roland.yonaba@gmail.com> | 2018-08-22 21:55:48 +0300 |
---|---|---|
committer | Yonaba <roland.yonaba@gmail.com> | 2018-08-22 21:55:48 +0300 |
commit | 9bf85201bf6a8655829af702aa7a1b1ab5755aba (patch) | |
tree | 196f7ff2e4a63c39064fd465dfaa26e333ae62a6 /spec | |
parent | d5185d50ef87602373e932a2bc96fc5eaf4962e3 (diff) |
Improved support for chaining (#Fixes 45)
Changed style from _ to M (Fixes #47)
Added functions
Broughts improvements
Updated documentation and tutorial
Added support for operators
Prepare for 2.0.0 release
Diffstat (limited to 'spec')
-rw-r--r-- | spec/array_spec.lua | 587 | ||||
-rw-r--r-- | spec/chaining_spec.lua | 2 | ||||
-rw-r--r-- | spec/func_spec.lua | 360 | ||||
-rw-r--r-- | spec/import_spec.lua | 18 | ||||
-rw-r--r-- | spec/object_spec.lua | 488 | ||||
-rw-r--r-- | spec/op_spec.lua | 162 | ||||
-rw-r--r-- | spec/table_spec.lua | 374 |
7 files changed, 1223 insertions, 768 deletions
diff --git a/spec/array_spec.lua b/spec/array_spec.lua index e79a6f7..74c7b13 100644 --- a/spec/array_spec.lua +++ b/spec/array_spec.lua @@ -1,48 +1,81 @@ -require 'luacov' -local _ = require 'moses' +--require 'luacov' +local M = require 'moses' context('Array functions specs', function() context('sample', function() test('samples n values from array', function() - local array = _.range(1,20) - local sample = _.sample(array, 5) + local array = M.range(1,20) + local sample = M.sample(array, 5) assert_equal(#sample, 5) - _.each(sample, function(__,v) - assert_true(_.include(array, v)) + M.each(sample, function(__,v) + assert_true(M.include(array, v)) end) end) test('when not given, n defaults to 1', function() - local array = _.range(1,20) - local sample = _.sample(array) - assert_true(_.include(array, sample)) + local array = M.range(1,20) + local sample = M.sample(array) + assert_equal(#sample, 1) + assert_true(M.include(array, sample[1])) end) + test('if n == 0, returns an empty array', function() + local array = M.range(1,5) + local sample = M.sample(array, 0) + assert_true(#sample == 0) + end) + + test('if n < 0, throws an error', function() + local array = M.range(1,5) + assert_error(M.sample(array, -1)) + end) + end) context('sampleProb', function() test('returns a sample of an array values', function() - local array = _.range(1,20) - local sample = _.sampleProb(array, 0.2) - _.each(sample, function(__,v) - assert_true(_.include(array, v)) + local array = M.range(1,20) + local sample = M.sampleProb(array, 0.2) + M.each(sample, function(__,v) + assert_true(M.include(array, v)) end) end) end) + context('shuffle', function() + + test('shuffles values and objects in a collection', function() + local values = {'a','b','c','d'} + assert_true(M.same(M.shuffle (values),values)) + end) + + test('can accept a seed value to init randomization', function() + local values = {'a','b','c','d'} + local seed = os.time() + assert_true(M.same(M.shuffle(values,seed),values)) + end) + + test('shuffled table has the same elements in a different order', function() + local values = {'a','b','c','d'} + assert_true(M.same(M.shuffle(values),values)) + assert_true(M.same(M.shuffle(values),values)) + end) + + end) + context('toArray', function() test('converts a vararg list to an array', function() - assert_true(_.isArray(_.toArray(1,2,3,4))) - assert_true(_.isEqual(_.toArray(1,2,8,'d','a',0),{1,2,8,'d','a',0})) + assert_true(M.isArray(M.toArray(1,2,3,4))) + assert_true(M.isEqual(M.toArray(1,2,8,'d','a',0),{1,2,8,'d','a',0})) end) test('preserves input order', function() - local args = _.toArray(1,2,3,4,5) + local args = M.toArray(1,2,3,4,5) for i = 1, 5 do assert_equal(args[i], i) end end) @@ -51,19 +84,19 @@ context('Array functions specs', function() context('find', function() test('looks for a value in a given array and returns its position', function() - assert_equal(_.find({4,3,2,1},2), 3) + assert_equal(M.find({4,3,2,1},2), 3) end) - test('uses _.isEqual to compare values', function() - assert_equal(_.find({{4},{3},{2},{1}},{3}), 2) + test('uses M.isEqual to compare values', function() + assert_equal(M.find({{4},{3},{2},{1}},{3}), 2) end) test('returns the index of the first occurence', function() - assert_equal(_.find({4,4,3,3,2,2,1,1},2),5) + assert_equal(M.find({4,4,3,3,2,2,1,1},2),5) end) test('can start the search at a specific position', function() - assert_equal(_.find({4,4,3,3,2,1,2,1,1},2,6),7) + assert_equal(M.find({4,4,3,3,2,1,2,1,1},2,6),7) end) end) @@ -71,7 +104,7 @@ context('Array functions specs', function() context('reverse', function() test('reverse values and objects in a given array', function() - assert_true(_.isEqual(_.reverse({1,2,3,'d'}),{'d',3,2,1})) + assert_true(M.isEqual(M.reverse({1,2,3,'d'}),{'d',3,2,1})) end) end) @@ -79,39 +112,65 @@ context('Array functions specs', function() context('fill', function() test('fills an array with a value', function() - local array = _.range(1,5) - assert_true(_.isEqual(_.fill(array,0),{0,0,0,0,0})) + local array = M.range(1,5) + assert_true(M.isEqual(M.fill(array,0),{0,0,0,0,0})) end) test('fills an array starting from an index', function() - local array = _.range(1,5) - assert_true(_.isEqual(_.fill(array,0,4),{1,2,3,0,0})) + local array = M.range(1,5) + assert_true(M.isEqual(M.fill(array,0,4),{1,2,3,0,0})) end) test('fills an array replacing values inside a range', function() - local array = _.range(1,5) - assert_true(_.isEqual(_.fill(array,0,3,4),{1,2,0,0,5})) + local array = M.range(1,5) + assert_true(M.isEqual(M.fill(array,0,3,4),{1,2,0,0,5})) end) test('enlarges the array when the last index is greater than array size', function() - local array = _.range(1,5) - assert_true(_.isEqual(_.fill(array,0,3,8),{1,2,0,0,0,0,0,0})) + local array = M.range(1,5) + assert_true(M.isEqual(M.fill(array,0,3,8),{1,2,0,0,0,0,0,0})) end) end) + context('zeros', function() + + test('returns an array of n zeros', function() + assert_true(M.isEqual(M.zeros(5), {0,0,0,0,0})) + assert_true(M.isEqual(M.zeros(2), {0,0})) + assert_true(M.isEqual(M.zeros(1), {0})) + end) + + end) + + context('ones', function() + + test('returns an array of n zeros', function() + assert_true(M.isEqual(M.ones(5), {1,1,1,1,1})) + assert_true(M.isEqual(M.ones(3), {1,1,1})) + assert_true(M.isEqual(M.ones(1), {1})) + end) + + end) + + context('vector', function() + + test('returns an array of n times a given value', function() + assert_true(M.isEqual(M.vector(false,4), {false, false, false, false})) + local f = function() end + assert_true(M.isEqual(M.vector(f,2), {f, f})) + end) + + end) + context('selectWhile', function() test('collect values from an array while they pass a thruth test', function() - assert_true(_.isEqual(_.selectWhile({2,4,6,8}, function(i,v) - return v%2==0 - end),{2,4,6,8})) + assert_true(M.isEqual(M.selectWhile({2,4,6,8}, function(v)return v%2==0 end),{2,4,6,8})) end) test('breaks as soon as one value do not pass the test', function() - assert_true(_.isEqual(_.selectWhile({2,4,6,8,9,10,12}, function(i,v) - return v%2==0 - end),{2,4,6,8})) + assert_true(M.isEqual(M.selectWhile({2,4,6,8,9,10,12}, function(v) return v%2==0 end),{2,4,6,8})) end) end) @@ -119,15 +178,11 @@ context('Array functions specs', function() context('dropWhile', function() test('rejects values from an array while they pass a thruth test', function() - assert_true(_.isEqual(_.dropWhile({2,4,6,8}, function(i,v) - return v%2==0 - end),{})) + assert_true(M.isEqual(M.dropWhile({2,4,6,8}, function(v) return v%2==0 end),{})) end) test('breaks as soon as one value do not pass the test', function() - assert_true(_.isEqual(_.dropWhile({2,4,6,8,9,10,12}, function(i,v) - return v%2==0 - end),{9,10,12})) + assert_true(M.isEqual(M.dropWhile({2,4,6,8,9,10,12}, function(v) return v%2==0 end),{9,10,12})) end) end) @@ -136,16 +191,16 @@ context('Array functions specs', function() test('returns the index at which a value should be inserted to preserve order', function() local comp = function(a,b) return a<b end - assert_equal(_.sortedIndex({1,2,3},4,comp),4) + assert_equal(M.sortedIndex({1,2,3},4,comp),4) end) test('the given array will be sorted before if boolean arg "sort" is given', function() local comp = function(a,b) return a<b end - assert_equal(_.sortedIndex({0,10,3,-5},4,comp,true),4) + assert_equal(M.sortedIndex({0,10,3,-5},4,comp,true),4) end) test('when no comparison function is given, uses "<" operator', function() - assert_equal(_.sortedIndex({'a','d','e','z'},'b'),2) + assert_equal(M.sortedIndex({'a','d','e','z'},'b'),2) end) end) @@ -153,15 +208,15 @@ context('Array functions specs', function() context('indexOf', function() test('returns the index of a value in an array', function() - assert_equal(_.indexOf({1,2,3},2),2) + assert_equal(M.indexOf({1,2,3},2),2) end) test('returns nil when value was not found', function() - assert_nil(_.indexOf({'a','b','c','d'},'e')) + assert_nil(M.indexOf({'a','b','c','d'},'e')) end) test('will always return the index of the first occurence', function() - assert_equal(_.indexOf({'a','d','d','z'},'d'),2) + assert_equal(M.indexOf({'a','d','d','z'},'d'),2) end) end) @@ -169,12 +224,12 @@ context('Array functions specs', function() context('lastIndexOf', function() test('returns the index of the last occurence of a value in an array', function() - assert_equal(_.lastIndexOf({1,2,3},2),2) - assert_equal(_.lastIndexOf({'a','d','d','z'},'d'),3) + assert_equal(M.lastIndexOf({1,2,3},2),2) + assert_equal(M.lastIndexOf({'a','d','d','z'},'d'),3) end) test('returns nil when value was not found', function() - assert_nil(_.lastIndexOf({'a','b','c','d'},'e')) + assert_nil(M.lastIndexOf({'a','b','c','d'},'e')) end) end) @@ -182,11 +237,11 @@ context('Array functions specs', function() context('findIndex', function() test('returns the first index at which a predicate passes a truth test', function() - assert_equal(_.findIndex({1,2,3,4,5},function(__,v) return v%2==0 end),2) + assert_equal(M.findIndex({1,2,3,4,5},function(__,v) return v%2==0 end),2) end) test('returns nil when nothing was found', function() - assert_nil(_.findIndex({1,2,3,4,5},function(_,v) return v>5 end)) + assert_nil(M.findIndex({1,2,3,4,5},function(_,v) return v>5 end)) end) end) @@ -194,11 +249,11 @@ context('Array functions specs', function() context('findLastIndex', function() test('returns the last index at which a predicate passes a truth test', function() - assert_equal(_.findLastIndex({1,2,3,4,5},function(_,v) return v%2==0 end),4) + assert_equal(M.findLastIndex({1,2,3,4,5},function(_,v) return v%2==0 end),4) end) test('returns nil when nothing was found', function() - assert_nil(_.findLastIndex({1,2,3,4,5},function(_,v) return v>5 end)) + assert_nil(M.findLastIndex({1,2,3,4,5},function(_,v) return v>5 end)) end) end) @@ -206,41 +261,55 @@ context('Array functions specs', function() context('addTop', function() test('adds values at the top of an array', function() - assert_true(_.isEqual(_.addTop({},1,2,3),{3,2,1})) - assert_true(_.isEqual(_.addTop({},'a',true,3),{3,true,'a'})) + assert_true(M.isEqual(M.addTop({},1,2,3),{3,2,1})) + assert_true(M.isEqual(M.addTop({},'a',true,3),{3,true,'a'})) end) test('preserves the existing elements', function() - assert_true(_.isEqual(_.addTop({1,2},1,2,3),{3,2,1,1,2})) - assert_true(_.isEqual(_.addTop({'i','j'},'a',true,3),{3,true,'a','i','j'})) + assert_true(M.isEqual(M.addTop({1,2},1,2,3),{3,2,1,1,2})) + assert_true(M.isEqual(M.addTop({'i','j'},'a',true,3),{3,true,'a','i','j'})) end) end) + context('prepend', function() + + test('adds values at the top of an array, preserving order', function() + assert_true(M.isEqual(M.prepend({},1,2,3),{1,2,3})) + assert_true(M.isEqual(M.prepend({},'a',true,3),{'a',true,3})) + end) + + test('preserves the existing elements', function() + assert_true(M.isEqual(M.prepend({1,2},1,2,3),{1,2,3,1,2})) + assert_true(M.isEqual(M.prepend({'i','j'},'a',true,3),{'a',true,3,'i','j'})) + end) + + end) + context('push', function() test('appends values at the end of an array', function() - assert_true(_.isEqual(_.push({},1,2,3),{1,2,3})) - assert_true(_.isEqual(_.push({},'a',true,3),{'a',true,3})) + assert_true(M.isEqual(M.push({},1,2,3),{1,2,3})) + assert_true(M.isEqual(M.push({},'a',true,3),{'a',true,3})) end) test('preserves the existing elements', function() - assert_true(_.isEqual(_.push({1,2},1,2,3),{1,2,1,2,3})) - assert_true(_.isEqual(_.push({'i','j'},'a',true,3),{'i','j','a',true,3})) + assert_true(M.isEqual(M.push({1,2},1,2,3),{1,2,1,2,3})) + assert_true(M.isEqual(M.push({'i','j'},'a',true,3),{'i','j','a',true,3})) end) end) - context('pop', function() + context('shift', function() test('returns the value at the top of a given array', function() - assert_equal(_.pop {1,7,9} ,1) + assert_equal(M.shift {1,7,9} ,1) end) test('also removes this value from the given array', function() local array = {1,7,9} - assert_equal(_.pop(array),1) - assert_true(_.isEqual(array,{7,9})) + assert_equal(M.shift(array),1) + assert_true(M.isEqual(array,{7,9})) end) end) @@ -248,13 +317,13 @@ context('Array functions specs', function() context('unshift', function() test('returns the value at the end of a given array', function() - assert_equal(_.unshift {1,7,9} ,9) + assert_equal(M.unshift {1,7,9} ,9) end) test('also removes this value from the given array', function() local array = {1,7,9} - assert_equal(_.unshift(array),9) - assert_true(_.isEqual(array,{1,7})) + assert_equal(M.unshift(array),9) + assert_true(M.isEqual(array,{1,7})) end) end) @@ -262,8 +331,8 @@ context('Array functions specs', function() context('pull', function() test('removes all listed values in a given array', function() - assert_true(_.same(_.pull({1,4,3,1,2,3},1),{4,3,2,3})) - assert_true(_.same(_.pull({1,4,3,1,2,3},1,3),{4,2})) + assert_true(M.same(M.pull({1,4,3,1,2,3},1),{4,3,2,3})) + assert_true(M.same(M.pull({1,4,3,1,2,3},1,3),{4,2})) end) end) @@ -271,23 +340,23 @@ context('Array functions specs', function() context('removeRange', function() test('removes all values within "start" and "finish" indexes', function() - assert_true(_.isEqual(_.removeRange({1,2,3,4,5,6},2,4),{1,5,6})) + assert_true(M.isEqual(M.removeRange({1,2,3,4,5,6},2,4),{1,5,6})) end) test('arg "finish" defaults to the end of the array when not given ', function() - assert_true(_.isEqual(_.removeRange({1,2,3,4,5,6},3),{1,2})) + assert_true(M.isEqual(M.removeRange({1,2,3,4,5,6},3),{1,2})) end) test('arg "start" defaults to the initial index when not given ', function() - assert_true(_.isEqual(_.removeRange({1,2,3,4,5,6}),{})) + assert_true(M.isEqual(M.removeRange({1,2,3,4,5,6}),{})) end) test('args "start" and "finish" are be clamped to the array bound ', function() - assert_true(_.isEqual(_.removeRange({1,2,3,4,5,6},0,100),{})) + assert_true(M.isEqual(M.removeRange({1,2,3,4,5,6},0,100),{})) end) - test('leaves the array untouched when "finish" < "start"', function() - assert_true(_.isEqual(_.removeRange({1,2,3,4,5,6},4,2),{1,2,3,4,5,6})) + test('throws an error when "finish" < "start"', function() + assert_error(function()M.removeRange({1,2,3,4,5,6},4,2) end) end) end) @@ -296,29 +365,12 @@ context('Array functions specs', function() test('chunks in blocks consecutive values returning the same value from a given function', function() local t = {1,2,2,3,3,4,4} - local v = _.chunk(t, function(k,v) return v%2==0 end) + local v = M.chunk(t, function(v) return v%2==0 end) assert_equal(#v, 4) - _.each(v[1], function(k) - assert_equal(v[1][k],1) - end) - assert_equal(#v[1],1) - _.each(v[2], function(k) - assert_equal(v[2][k],2) - end) - assert_equal(#v[2],2) - _.each(v[3], function(k) - assert_equal(v[3][k],3) - end) - assert_equal(#v[3],2) - _.each(v[4], function(k) - assert_equal(v[4][k],4) - end) - assert_equal(#v[4],2) - end) - - test('Returns the first argument in case it is not an array', function() - local t = {a = 1, b = 2} - assert_equal(_.chunk(t, function(k,v) return v%2==0 end), t) + assert_true(M.isEqual(v[1], {1})) + assert_true(M.isEqual(v[2], {2,2})) + assert_true(M.isEqual(v[3], {3,3})) + assert_true(M.isEqual(v[4], {4,4})) end) end) @@ -326,15 +378,15 @@ context('Array functions specs', function() context('slice',function() test('slices a portion of an array',function() - assert_true(_.isEqual(_.slice({'a','b','c','d','e'},2,3),{'b','c'})) + assert_true(M.isEqual(M.slice({'a','b','c','d','e'},2,3),{'b','c'})) end) test('arg "right" bound defaults to the array length when not given',function() - assert_true(_.isEqual(_.slice({'a','b','c','d','e'},3),{'c','d','e'})) + assert_true(M.isEqual(M.slice({'a','b','c','d','e'},3),{'c','d','e'})) end) test('arg "left" bound defaults to the initial index when not given',function() - assert_true(_.isEqual(_.slice({'a','b','c','d','e'}),{'a','b','c','d','e'})) + assert_true(M.isEqual(M.slice({'a','b','c','d','e'}),{'a','b','c','d','e'})) end) end) @@ -342,11 +394,11 @@ context('Array functions specs', function() context('first',function() test('returns the n-first elements', function() - assert_true(_.isEqual(_.first({5,8,12,20},2),{5,8})) + assert_true(M.isEqual(M.first({5,8,12,20},2),{5,8})) end) test('arg "n" defaults 1 when not given', function() - assert_true(_.isEqual(_.first({5,8,12,20}),{5})) + assert_true(M.isEqual(M.first({5,8,12,20}),{5})) end) end) @@ -354,67 +406,58 @@ context('Array functions specs', function() context('initial',function() test('exludes the last N elements', function() - assert_true(_.isEqual(_.initial({5,8,12,20},3),{5})) - assert_true(_.isEqual(_.initial({5,8,12,20},4),{})) + assert_true(M.isEqual(M.initial({5,8,12,20},3),{5})) + assert_true(M.isEqual(M.initial({5,8,12,20},4),{})) end) test('returns all values but the last one if arg "n" was not given', function() - assert_true(_.isEqual(_.initial({5,8,12,20}),{5,8,12})) + assert_true(M.isEqual(M.initial({5,8,12,20}),{5,8,12})) end) test('passing "n" greather than the array size returns an empty', function() - assert_true(_.isEqual(_.initial({5,8,12,20},5),{})) + assert_true(M.isEqual(M.initial({5,8,12,20},5),{})) end) test('returns the whole array when "n" equals 0', function() - assert_true(_.isEqual(_.initial({5,8,12,20},0),{5,8,12,20})) - end) - - test('returns "nil" when arg "n" < 0', function() - assert_nil(_.initial({5,8,12,20},-1)) - end) + assert_true(M.isEqual(M.initial({5,8,12,20},0),{5,8,12,20})) + end) end) context('last',function() test('returns the last N elements', function() - assert_true(_.isEqual(_.last({5,8,12,20},3),{8,12,20})) - assert_true(_.isEqual(_.last({5,8,12,20},1),{20})) - assert_true(_.isEqual(_.last({5,8,12,20},2),{12,20})) - assert_true(_.isEqual(_.last({5,8,12,20},4),{5,8,12,20})) + assert_true(M.isEqual(M.last({5,8,12,20},3),{8,12,20})) + assert_true(M.isEqual(M.last({5,8,12,20},1),{20})) + assert_true(M.isEqual(M.last({5,8,12,20},2),{12,20})) + assert_true(M.isEqual(M.last({5,8,12,20},4),{5,8,12,20})) end) test('returns all values but the first one if arg "n" was not given', function() - assert_true(_.isEqual(_.last({5,8,12,20}),{8,12,20})) + assert_true(M.isEqual(M.last({5,8,12,20}),{8,12,20})) end) test('if arg "n" is lower than the array size, returns all values', function() - assert_true(_.isEqual(_.last({5,8,12,20},5),{5,8,12,20})) - end) - - test('returns "nil" when arg "n" <= 0', function() - assert_nil(_.last({5,8,12,20},0)) - assert_nil(_.last({5,8,12,20},-1)) - end) + assert_true(M.isEqual(M.last({5,8,12,20},5),{5,8,12,20})) + end) end) context('rest',function() test('excludes all values before a given index', function() - assert_true(_.isEqual(_.rest({5,8,12,20},2),{8,12,20})) - assert_true(_.isEqual(_.rest({5,8,12,20},1),{5,8,12,20})) - assert_true(_.isEqual(_.rest({5,8,12,20},4),{20})) + assert_true(M.isEqual(M.rest({5,8,12,20},2),{8,12,20})) + assert_true(M.isEqual(M.rest({5,8,12,20},1),{5,8,12,20})) + assert_true(M.isEqual(M.rest({5,8,12,20},4),{20})) end) test('returns an empty array when arg "index" > #array', function() - assert_true(_.isEqual(_.rest({5,8,12,20},5),{})) + assert_true(M.isEqual(M.rest({5,8,12,20},5),{})) end) test('returns all values if arg "index" <= 0', function() - assert_true(_.isEqual(_.rest({5,8,12,20},0),{5,8,12,20})) - assert_true(_.isEqual(_.rest({5,8,12,20},-1),{5,8,12,20})) + assert_true(M.isEqual(M.rest({5,8,12,20},0),{5,8,12,20})) + assert_true(M.isEqual(M.rest({5,8,12,20},-1),{5,8,12,20})) end) end) @@ -422,7 +465,7 @@ context('Array functions specs', function() context('nth', function() test('returns the value at "index"', function() - assert_equal(3, _.nth({1,2,3,4,5,6}, 3)) + assert_equal(3, M.nth({1,2,3,4,5,6}, 3)) end) end) @@ -430,7 +473,7 @@ context('Array functions specs', function() context('compact',function() test('trims out all falsy values from an array', function() - assert_true(_.isEqual(_.compact({a,'a',false,'b',true}),{'a','b',true})) + assert_true(M.isEqual(M.compact({a,'a',false,'b',true}),{'a','b',true})) end) end) @@ -438,11 +481,11 @@ context('Array functions specs', function() context('flatten',function() test('flattens nested arrays', function() - assert_true(_.isEqual(_.flatten({1,{2,3},{4,5,{6,7}}}),{1,2,3,4,5,6,7})) + assert_true(M.isEqual(M.flatten({1,{2,3},{4,5,{6,7}}}),{1,2,3,4,5,6,7})) end) test('when given arg "shallow", flatten only first level', function() - assert_true(_.isEqual(_.flatten({1,{2,3},{4,5,{6,7}}},true),{1,2,3,4,5,{6,7}})) + assert_true(M.isEqual(M.flatten({1,{2,3},{4,5,{6,7}}},true),{1,2,3,4,5,{6,7}})) end) end) @@ -451,17 +494,17 @@ context('Array functions specs', function() test('returns values in the first array not present in the second array', function() local array = {1,2,'a',4,5} - assert_true(_.isEqual(_.difference(array,{1,'a'}),{2,4,5})) - assert_true(_.isEqual(_.difference(array,{5}),{1,2,'a',4})) + assert_true(M.isEqual(M.difference(array,{1,'a'}),{2,4,5})) + assert_true(M.isEqual(M.difference(array,{5}),{1,2,'a',4})) end) test('ignores values in the second array not found in the first array', function() local array = {1,2,'a',4,5} - assert_true(_.isEqual(_.difference(array,{1,'a','b','c'}),{2,4,5})) + assert_true(M.isEqual(M.difference(array,{1,'a','b','c'}),{2,4,5})) end) test('leaves array untouched when given no extra-args', function() - assert_true(_.isEqual(_.difference({1,2,'a',4,5}),{1,2,'a',4,5})) + assert_true(M.isEqual(M.difference({1,2,'a',4,5}),{1,2,'a',4,5})) end) end) @@ -470,12 +513,12 @@ context('Array functions specs', function() test('returns the duplicate-free union of all passed-in arrays', function() local a = {"a"}; local b = {1,2,3}; local c = {2,10} - assert_true(_.isEqual(_.union(a,b,c),{'a',1,2,3,10})) + assert_true(M.isEqual(M.union(a,b,c),{'a',1,2,3,10})) end) test('accepts nested arrays as well', function() local a = {"a",{"b","c"}}; local b = {1,{2},3}; local c = {2,10} - assert_true(_.isEqual(_.union(a,b,c),{'a','b','c',1,2,3,10})) + assert_true(M.isEqual(M.union(a,b,c),{'a','b','c',1,2,3,10})) end) end) @@ -484,12 +527,12 @@ context('Array functions specs', function() test('returns the intersection of all passed-in arrays', function() local a = {1,3}; local b = {4,2,3}; local c = {2,3,10} - assert_true(_.isEqual(_.intersection(a,b,c),{3})) + assert_true(M.isEqual(M.intersection(a,b,c),{3})) end) test('fails with nested arrays', function() local a = {1,{3}}; local b = {4,2,3}; local c = {2,3,10} - assert_true(_.isEqual(_.intersection(a,b,c),{})) + assert_true(M.isEqual(M.intersection(a,b,c),{})) end) end) @@ -498,9 +541,9 @@ context('Array functions specs', function() test('returns the symmetric difference from two arrays', function() local a = {1,3}; local b = {4,2,3}; local c = {2,3,10} - assert_true(_.same(_.symmetricDifference(a, b), {1,4,2})) - assert_true(_.same(_.symmetricDifference(a, c), {1,2,10})) - assert_true(_.same(_.symmetricDifference(b, c), {4,10})) + assert_true(M.same(M.symmetricDifference(a, b), {1,4,2})) + assert_true(M.same(M.symmetricDifference(a, c), {1,2,10})) + assert_true(M.same(M.symmetricDifference(b, c), {4,10})) end) end) @@ -508,7 +551,7 @@ context('Array functions specs', function() context('unique',function() test('returns a duplicate-free array',function() - assert_true(_.isEqual(_.unique({1,1,2,2,3,3,4,4,4,5}),{1,2,3,4,5})) + assert_true(M.isEqual(M.unique({1,1,2,2,3,3,4,4,4,5}),{1,2,3,4,5})) end) end) @@ -516,8 +559,8 @@ context('Array functions specs', function() context('isunique',function() test('Checks if a given array is duplicate-free',function() - assert_true(_.isunique({1,2,3,4,5})) - assert_false(_.isunique({1,2,3,4,4})) + assert_true(M.isunique({1,2,3,4,5})) + assert_false(M.isunique({1,2,3,4,4})) end) end) @@ -525,14 +568,25 @@ context('Array functions specs', function() context('zip',function() test('zips together values from different arrays sharing the same index', function() local names = {'Bob','Alice','James'}; local ages = {22, 23} - assert_true(_.isEqual(_.zip(names,ages),{{'Bob',22},{'Alice',23},{'James'}})) + assert_true(M.isEqual(M.zip(names,ages),{{'Bob',22},{'Alice',23},{'James'}})) end) end) + context('zipWith',function() + test('zips together values from different arrays sharing the same index using a function', function() + local names = {'Bob','Alice','James'}; local ages = {22, 23, 25} + local function introduce(name, age) return 'My name is '..name..' and I am '..age..' years old.' end + local t = M.zipWith(introduce,names,ages) + assert_equal(t[1],'My name is Bob and I am 22 years old.') + assert_equal(t[2],'My name is Alice and I am 23 years old.') + assert_equal(t[3],'My name is James and I am 25 years old.') + end) + end) + context('append',function() test('appends two arrays together', function() - assert_true(_.isEqual(_.append({1,2,3},{'a','b'}),{1,2,3,'a','b'})) + assert_true(M.isEqual(M.append({1,2,3},{'a','b'}),{1,2,3,'a','b'})) end) end) @@ -540,8 +594,8 @@ context('Array functions specs', function() context('interleave',function() test('interleaves values from passed-in arrays', function() - assert_true(_.isEqual(_.interleave({1,2,3},{'a','b','c'}),{1,'a',2,'b',3,'c'})) - assert_true(_.isEqual(_.interleave({1},{'a','b','c'}),{1,'a','b','c'})) + assert_true(M.isEqual(M.interleave({1,2,3},{'a','b','c'}),{1,'a',2,'b',3,'c'})) + assert_true(M.isEqual(M.interleave({1},{'a','b','c'}),{1,'a','b','c'})) end) end) @@ -549,35 +603,36 @@ context('Array functions specs', function() context('interpose',function() test('interposes a value in-between values from a passed-in array', function() - assert_true(_.isEqual(_.interpose('a',{1,2,3}),{1,'a',2,'a',3})) - assert_true(_.isEqual(_.interpose(false,{5,5,5,5}),{5,false,5,false,5,false,5})) - end) + assert_true(M.isEqual(M.interpose({1,2,3},'a'),{1,'a',2,'a',3})) + assert_true(M.isEqual(M.interpose({5,5,5,5}, false),{5,false,5,false,5,false,5})) + end) + + test('leaves the array untouched if containing a single element', function() + assert_true(M.isEqual(M.interpose({1},'a'),{1})) + end) end) context('range',function() test('generate an arithmetic progression', function() - assert_true(_.isEqual(_.range(1,5,1),{1,2,3,4,5})) - assert_true(_.isEqual(_.range(-2,5,1),{-2,-1,0,1,2,3,4,5})) - assert_true(_.isEqual(_.range(1,5,2),{1,3,5})) - end) - - test('arg "step" default to 1 when no given', function() - assert_true(_.isEqual(_.range(1,5),{1,2,3,4,5})) + assert_true(M.isEqual(M.range(1,5,1),{1,2,3,4,5})) + assert_true(M.isEqual(M.range(-2,5,1),{-2,-1,0,1,2,3,4,5})) + assert_true(M.isEqual(M.range(1,5,2),{1,3,5})) end) - test('when a limit cannot be reached via "step", returns an empty array', function() - assert_true(_.isEqual(_.range(1,5,0),{})) - assert_true(_.isEqual(_.range(1,5,-1),{})) + test('arg "step" default to 1 or -1 when no given', function() + assert_true(M.isEqual(M.range(1,5),{1,2,3,4,5})) + assert_true(M.isEqual(M.range(5,1),{5,4,3,2,1})) end) test('handles real values as well', function() - assert_true(_.isEqual(_.range(3.2,5,0.5),{3.2,3.7,4.2,4.7})) + assert_true(M.isEqual(M.range(3.2,5,0.5),{3.2,3.7,4.2,4.7})) end) - test('when only one arg is passed, counts from 0', function() - assert_true(_.isEqual(_.range(3),{0,1,2,3})) + test('when only one arg is passed, counts from 1', function() + assert_true(M.isEqual(M.range(3),{1,2,3})) + assert_true(M.isEqual(M.range(-3),{-1,-2,-3})) end) end) @@ -585,8 +640,17 @@ context('Array functions specs', function() context('rep',function() test('generates a list of n repetitions of a value', function() - assert_true(_.isEqual(_.rep('a',4),{'a','a','a','a'})) - assert_true(_.isEqual(_.rep(false,3),{false, false, false})) + assert_true(M.isEqual(M.rep('a',4),{'a','a','a','a'})) + assert_true(M.isEqual(M.rep(false,3),{false, false, false})) + end) + + end) + + context('powerset',function() + + test('generates the powerset of a given array', function() + assert_true(M.isEqual(M.powerset({1,2,3}),{{1},{2},{3},{1,2},{2,3},{1,2,3}})) + assert_true(M.isEqual(M.powerset({1,2,3,4}),{{1},{2},{3},{4},{1,2},{2,3},{3,4},{1,2,3},{2,3,4},{1,2,3,4}})) end) end) @@ -594,83 +658,134 @@ context('Array functions specs', function() context('partition',function() test('iterates on partitions of a given array', function() - local array = _.range(1,10) - local split5 = {_.range(1,5), _.range(6,10)} - local split3 = {_.range(1,3), _.range(4,6), _.range(7,9), {10}} + local array = M.range(1,10) + local split5 = {M.range(1,5), M.range(6,10)} + local split3 = {M.range(1,3), M.range(4,6), M.range(7,9), {10}} local i = 0 - for p in _.partition(array,5) do + for p in M.partition(array,5) do i = i + 1 - assert_true(_.isEqual(p, split5[i])) + assert_true(M.isEqual(p, split5[i])) end i = 0 - for p in _.partition(array,3) do + for p in M.partition(array,3) do i = i + 1 - assert_true(_.isEqual(p, split3[i])) + assert_true(M.isEqual(p, split3[i])) end end) test('if a 3rd argument pad is supplied, will adjust the last partition', function() - local array = _.range(1,10) + local array = M.range(1,10) local split4 = {{1,2,3,4},{5,6,7,8},{9,10,0,0}} local i = 0 - for p in _.partition(array,4,0) do + for p in M.partition(array,4,0) do i = i + 1 - assert_true(_.isEqual(p, split4[i])) + assert_true(M.isEqual(p, split4[i])) end end) end) - context('sliding',function() + context('overlapping',function() test('returns overlapping subsequences', function() - local array = _.range(1,10) + local array = M.range(1,10) local sliding2 = {{1,2},{2,3},{3,4},{4,5},{5,6},{6,7},{7,8},{8,9},{9,10}} local sliding3 = {{1,2,3},{3,4,5},{5,6,7},{7,8,9},{9,10}} local sliding5 = {{1,2,3,4,5},{5,6,7,8,9},{9,10}} local i = 0 - for p in _.sliding(array,2) do + for p in M.overlapping(array,2) do i = i + 1 - assert_true(_.isEqual(p, sliding2[i])) + assert_true(M.isEqual(p, sliding2[i])) end i = 0 - for p in _.sliding(array,3) do + for p in M.overlapping(array,3) do i = i + 1 - assert_true(_.isEqual(p, sliding3[i])) + assert_true(M.isEqual(p, sliding3[i])) end i = 0 - for p in _.sliding(array,5) do + for p in M.overlapping(array,5) do i = i + 1 - assert_true(_.isEqual(p, sliding5[i])) + assert_true(M.isEqual(p, sliding5[i])) end end) test('if a 3rd argument pad is supplied, will adjust the last subsequence', function() - local array = _.range(1,10) + local array = M.range(1,10) local sliding3 = {{1,2,3},{3,4,5},{5,6,7},{7,8,9},{9,10,0}} local sliding5 = {{1,2,3,4,5},{5,6,7,8,9},{9,10,0,0,0}} local i = 0 - for p in _.sliding(array,3,0) do + for p in M.overlapping(array,3,0) do i = i + 1 - assert_true(_.isEqual(p, sliding3[i])) + assert_true(M.isEqual(p, sliding3[i])) end i = 0 - for p in _.sliding(array,5,0) do + for p in M.overlapping(array,5,0) do i = i + 1 - assert_true(_.isEqual(p, sliding5[i])) + assert_true(M.isEqual(p, sliding5[i])) end end) - end) + end) + + context('aperture', function() + + test('returns sliding partitions of a given array', function() + local array = M.range(1,5) + local slides2 = {{1,2},{2,3},{3,4},{4,5}} + local slides3 = {{1,2,3},{2,3,4},{3,4,5}} + local slides4 = {{1,2,3,4},{2,3,4,5}} + local slides5 = {{1,2,3,4,5}} + + local i = 0 + for p in M.aperture(array, 2) do + i = i + 1 + assert_true(M.isEqual(p, slides2[i])) + end + + i = 0 + for p in M.aperture(array, 3) do + i = i + 1 + assert_true(M.isEqual(p, slides3[i])) + end + + i = 0 + for p in M.aperture(array, 4) do + i = i + 1 + assert_true(M.isEqual(p, slides4[i])) + end + + i = 0 + for p in M.aperture(array, 5) do + i = i + 1 + assert_true(M.isEqual(p, slides5[i])) + end + end) + + end) + + context('pairwise', function() + + test('returns sliding partitions of a given array', function() + local array = M.range(1,5) + local pw = {{1,2},{2,3},{3,4},{4,5}} + + local i = 0 + for p in M.pairwise(array) do + i = i + 1 + assert_true(M.isEqual(p, pw[i])) + end + end) + + end) context('permutation',function() test('iterates on permutations of a given array', function() local array = {'a','b', 'c'} local perm = {'abc','acb', 'bac', 'bca', 'cab', 'cba'} - for p in _.permutation(array) do - local strp = _.concat(p) - _.pull(perm, strp) + for p in M.permutation(array) do + local strp = M.concat(p) + M.pull(perm, strp) end assert_true(#perm == 0) end) @@ -680,8 +795,8 @@ context('Array functions specs', function() context('invert',function() test('switches key-values pairs', function() - assert_true(_.isEqual(_.invert({1,2,3}),{1,2,3})) - assert_true(_.isEqual(_.invert({'a','b','c'}),{a = 1,b = 2,c = 3})) + assert_true(M.isEqual(M.invert({1,2,3}),{1,2,3})) + assert_true(M.isEqual(M.invert({'a','b','c'}),{a = 1,b = 2,c = 3})) end) end) @@ -689,25 +804,77 @@ context('Array functions specs', function() context('concat',function() test('concatenates an array contents', function() - assert_equal(_.concat({1,2,3,4}),'1234') - assert_equal(_.concat({'a',1,0,1,'b'}),'a101b') + assert_equal(M.concat({1,2,3,4}),'1234') + assert_equal(M.concat({'a',1,0,1,'b'}),'a101b') end) test('handles boolean values', function() - assert_equal(_.concat({1,true,3,false}),'1true3false') + assert_equal(M.concat({1,true,3,false}),'1true3false') end) test('when arg "sep" is given, uses "sep" as a separator', function() - assert_equal(_.concat({1,3,false,'A'},' '),'1 3 false A') - assert_equal(_.concat({1,3,false,'A'},', '),'1, 3, false, A') + assert_equal(M.concat({1,3,false,'A'},' '),'1 3 false A') + assert_equal(M.concat({1,3,false,'A'},', '),'1, 3, false, A') end) test('when args "i" and/or "j" are given, concats values within "i" and "j" indexes', function() - assert_equal(_.concat({1,3,false,'A'},' ',2,3),'3 false') - assert_equal(_.concat({1,3,false,'A'},', ',2,3),'3, false') - assert_equal(_.concat({1,3,false,'A','K'},' ',2),'3 false A K') + assert_equal(M.concat({1,3,false,'A'},' ',2,3),'3 false') + assert_equal(M.concat({1,3,false,'A'},', ',2,3),'3, false') + assert_equal(M.concat({1,3,false,'A','K'},' ',2),'3 false A K') end) + end) + + context('xprod',function() + + test('returns all possible pairs', function() + local r = M.xprod({1,2,3},{'a','b'}) + assert_true(M.isEqual(r[1],{1,'a'})) + assert_true(M.isEqual(r[2],{1,'b'})) + assert_true(M.isEqual(r[3],{2,'a'})) + assert_true(M.isEqual(r[4],{2,'b'})) + assert_true(M.isEqual(r[5],{3,'a'})) + assert_true(M.isEqual(r[6],{3,'b'})) + end) + + end) + + context('sum',function() + + test('returns the sum of array values', function() + assert_equal(M.sum {1,2,3,4,5}, 15) + assert_equal(M.sum {1,2,3,4}, 10) + assert_equal(M.sum {1,2,3}, 6) + end) + + end) + + context('product',function() + + test('returns the product of array values', function() + assert_equal(M.product {1,2,3,4,5}, 120) + assert_equal(M.product {1,2,3,4}, 24) + assert_equal(M.product {1,2,3}, 6) + end) + + end) + + context('mean',function() + + test('returns the mean of array values', function() + assert_equal(M.mean {1,2,3,4,5}, 3) + assert_equal(M.mean {1,2,3,4}, 2.5) + end) + + end) + + context('meadian',function() + + test('returns the median of array values', function() + assert_equal(M.median {1,2,3,4,5}, 3) + assert_equal(M.median {1,2,3,4}, 2.5) + end) + end) end)
\ No newline at end of file diff --git a/spec/chaining_spec.lua b/spec/chaining_spec.lua index 065491a..5a24aa6 100644 --- a/spec/chaining_spec.lua +++ b/spec/chaining_spec.lua @@ -1,4 +1,4 @@ -require 'luacov' +--require 'luacov' local _ = require 'moses' context('Chaining specs', function() diff --git a/spec/func_spec.lua b/spec/func_spec.lua index 2803922..1e588d0 100644 --- a/spec/func_spec.lua +++ b/spec/func_spec.lua @@ -1,17 +1,17 @@ -require 'luacov' -local _ = require 'moses' +--require 'luacov' +local M = require 'moses' context('Utility functions specs', function() context('noop', function() test('the no-operation function',function() - assert_nil(_.noop()) - assert_nil(_.noop(nil)) - assert_nil(_.noop(false)) - assert_nil(_.noop({})) - assert_nil(_.noop(function() end)) - assert_nil(_.noop(_.noop)) + assert_nil(M.noop()) + assert_nil(M.noop(nil)) + assert_nil(M.noop(false)) + assert_nil(M.noop({})) + assert_nil(M.noop(function() end)) + assert_nil(M.noop(M.noop)) end) end) @@ -19,9 +19,9 @@ context('Utility functions specs', function() context('identity', function() test('returns the received value',function() - assert_equal(_.identity(1),1) + assert_equal(M.identity(1),1) local v = {x = 0} - assert_equal(_.identity(v),v) + assert_equal(M.identity(v),v) assert_not_equal(v,{x = 0}) end) @@ -30,7 +30,7 @@ context('Utility functions specs', function() context('constant', function() test('creates a constant function',function() - local gravity = _.constant(9.81) + local gravity = M.constant(9.81) assert_equal(gravity(),9.81) assert_equal(gravity(10), 9.81) assert_equal(gravity(nil), 9.81) @@ -38,69 +38,80 @@ context('Utility functions specs', function() end) + context('applySpec', function() + + test('returns a spec function which produces objects',function() + local stats = M.applySpec({ + min = function(...) return math.min(...) end, + max = function(...) return math.max(...) end, + }) + + for i = 1, 10 do + local mn, mx = math.random(1,10), math.random(11,20) + local t = M.range(mn, mx) + table.sort(t) + local r = stats(unpack(t)) + assert_equal(r.min, t[1]) + assert_equal(r.max, t[#t]) + end + end) + + end) + context('memoize', function() local fib_time, fib_value, mfib_time, mfib_value local fib, mfib - before(function() - local function fib(n) - return n < 2 and n or fib(n-1)+fib(n-2) - end - local times = 10 - local mfib = _.memoize(fib) - fib_time = os.clock() - for i = 1, times do fib_value = (fib_value or 0)+fib(20) end - fib_time = (os.clock()-fib_time)*1000 - - mfib_time = os.clock() - for i = 1, times do mfib_value = (mfib_value or 0)+mfib(20) end - mfib_time = (os.clock()-mfib_time )*1000 - end) - test('memoizes an expensive function by caching its results',function() - assert_true(mfib_time<=fib_time) + local function fib(n) return n < 2 and n or fib(n-1)+fib(n-2) end + local mfib = M.memoize(fib) + assert_equal(fib(10), mfib(10)) + assert_equal(fib(15), mfib(15)) + assert_equal(fib(8), mfib(8)) + assert_equal(fib(13), mfib(13)) end) test('can take a hash function to compute an unique output for multiple args',function() - local function hash(a,b) return (a^13+b^19) end local function fact(a) return a <= 1 and 1 or a*fact(a-1) end local diffFact = function(a,b) return fact(a)-fact(b) end - local mdiffFact = _.memoize(function(a,b) return fact(a)-fact(b) end,hash) + local mdiffFact = M.memoize(function(a,b) return fact(a)-fact(b) end,hash) local times, rep = 100, 10 - local time = os.clock() for j = 1,times do for ai = 1,rep do - for aj = 1,rep do diffFact(ai,aj) end + for aj = 1,rep do + assert_equal(diffFact(ai,aj), mdiffFact(ai,aj)) + end end end - time = (os.clock()-time)*1000 - - local mtime = os.clock() - for j = 1,times do - for ai = 1,rep do - for aj = 1,rep do mdiffFact(ai,aj) end - end - end - mtime = (os.clock()-mtime)*1000 - - assert_true(mtime<=time) - end) - end) + end) + + context('unfold', function() + + test('builds a list from a seed value using a iterator',function() + local function iter(seed) + if seed < 100 then return seed, seed * 2 end + end + assert_true(M.isEqual(M.unfold(iter,1),{1,2,4,8,16,32,64})) + assert_true(M.isEqual(M.unfold(iter,5),{5, 10,20,40,80})) + assert_true(M.isEqual(M.unfold(iter,10),{10,20,40,80})) + end) + + end) context('once', function() test('returns a version of a function that runs once',function() - local sq = _.once(function(a) return a*a end) + local sq = M.once(function(a) return a*a end) assert_equal(sq(2),4) end) test('successive calls will keep yielding the original answer',function() - local sq = _.once(function(a) return a*a end) + local sq = M.once(function(a) return a*a end) for i = 1,10 do assert_equal(sq(i),1) end @@ -112,7 +123,7 @@ context('Utility functions specs', function() test('returns a version of a function that runs no more than count-th calls',function() local function say(something) return something end - local speak3times = _.before(say, 3) + local speak3times = M.before(say, 3) assert_equal(speak3times('a'), 'a') assert_equal(speak3times('b'), 'b') assert_equal(speak3times('c'), 'c') @@ -128,7 +139,7 @@ context('Utility functions specs', function() test('returns a function that will respond on its count-th call',function() local function a(r) return (r) end - a = _.after(a,5) + a = M.after(a,5) for i = 1,10 do if i < 5 then assert_nil(a(i)) @@ -145,15 +156,15 @@ context('Utility functions specs', function() test('can compose commutative functions',function() local greet = function(name) return "hi: " .. name end local exclaim = function(sentence) return sentence .. "!" end - assert_equal(_.compose(greet,exclaim)('moe'),'hi: moe!') - assert_equal(_.compose(exclaim,greet)('moe'),'hi: moe!') + assert_equal(M.compose(greet,exclaim)('moe'),'hi: moe!') + assert_equal(M.compose(exclaim,greet)('moe'),'hi: moe!') end) test('composes mutiple functions',function() local function f(x) return x^2 end local function g(x) return x+1 end local function h(x) return x/2 end - local compositae = _.compose(f,g,h) + local compositae = M.compose(f,g,h) assert_equal(compositae(10),36) assert_equal(compositae(20),121) end) @@ -162,10 +173,10 @@ context('Utility functions specs', function() local function f(s) return (s or '')..'f' end local function g(s) return (s or '')..'g' end local function h(s) return (s or '')..'h' end - assert_equal(_.compose(f,g,h)(),'hgf') - assert_equal(_.compose(h,g,f)(),'fgh') - assert_equal(_.compose(f,h,g)(),'ghf') - assert_equal(_.compose(g,h,f)(),'fhg') + assert_equal(M.compose(f,g,h)(),'hgf') + assert_equal(M.compose(h,g,f)(),'fgh') + assert_equal(M.compose(f,h,g)(),'ghf') + assert_equal(M.compose(g,h,f)(),'fhg') end) end) @@ -176,8 +187,8 @@ context('Utility functions specs', function() local function f(x) return x^2 end local function g(x) return x+1 end local function h(x) return x/2 end - assert_equal(_.pipe(10,f,g,h),36) - assert_equal(_.pipe(20,f,g,h),121) + assert_equal(M.pipe(10,f,g,h),36) + assert_equal(M.pipe(20,f,g,h),121) end) end) @@ -185,10 +196,10 @@ context('Utility functions specs', function() context('complement', function() test('returns a function which returns the logical complement of a given function',function() - assert_false(_.complement(function() return true end)()) - assert_true(_.complement(function() return false end)()) - assert_true(_.complement(function() return nil end)()) - assert_false(_.complement(function() return 1 end)()) + assert_false(M.complement(function() return true end)()) + assert_true(M.complement(function() return false end)()) + assert_true(M.complement(function() return nil end)()) + assert_false(M.complement(function() return 1 end)()) end) end) @@ -199,7 +210,7 @@ context('Utility functions specs', function() local function f(x) return x^2 end local function g(x) return x+1 end local function h(x) return x/2 end - local rf, rg, rh = _.juxtapose(10, f, g, h) + local rf, rg, rh = M.juxtapose(10, f, g, h) assert_equal(rf, 100) assert_equal(rg, 11) assert_equal(rh, 5) @@ -211,7 +222,7 @@ context('Utility functions specs', function() test('wraps a function and passes args',function() local greet = function(name) return "hi: " .. name end - local backwards = _.wrap(greet, function(f,arg) + local backwards = M.wrap(greet, function(f,arg) return f(arg) ..'\nhi: ' .. arg:reverse() end) assert_equal(backwards('john'),'hi: john\nhi: nhoj') @@ -223,12 +234,12 @@ context('Utility functions specs', function() test('calls a given function n times',function() local f = ('Lua programming'):gmatch('.') - local r = _.times(3,f) - assert_true(_.isEqual(r,{'L','u','a'})) + local r = M.times(f, 3) + assert_true(M.isEqual(r,{'L','u','a'})) local count = 0 local function counter() count = count+1 end - _.times(10,counter) + M.times(counter, 10) assert_equal(count,10) end) @@ -237,7 +248,7 @@ context('Utility functions specs', function() context('bind', function() test('binds a value to the first arg of a function',function() - local sqrt2 = _.bind(math.sqrt,2) + local sqrt2 = M.bind(math.sqrt,2) assert_equal(sqrt2(),math.sqrt(2)) end) @@ -246,9 +257,9 @@ context('Utility functions specs', function() context('bind2', function() test('binds a value to the second arg of a function',function() - local last2 = _.bind2(_.last,2) + local last2 = M.bind2(M.last,2) local r = last2({1,2,3,4,5,6}) - assert_true(_.isEqual(r, {5,6})) + assert_true(M.isEqual(r, {5,6})) end) end) @@ -259,14 +270,14 @@ context('Utility functions specs', function() local function out(...) return table.concat {...} end - out = _.bindn(out,'OutPut',':',' ') + out = M.bindn(out,'OutPut',':',' ') assert_equal(out(1,2,3),'OutPut: 123') assert_equal(out('a','b','c','d'),'OutPut: abcd') end) end) - context('bindAll', function() + context('bindall', function() test('binds methods to object',function() local window = { @@ -274,7 +285,7 @@ context('Utility functions specs', function() setName = function(w,name) w.name = name end, getName = function(w) return w.name end, } - window = _.bindAll(window, 'setPos', 'setName', 'getName') + window = M.bindall(window, 'setPos', 'setName', 'getName') window.setPos(10,15) window.setName('fooApp') @@ -285,25 +296,44 @@ context('Utility functions specs', function() end) end) + + context('cond', function() + + test('return a function which runs a set of predicates',function() + local multipleOf = M.cond({ + {function(v) return v%2==0 end, function(v) return v..' is multiple of 2' end}, + {function(v) return v%3==0 end, function(v) return v..' is multiple of 3' end}, + {function(v) return v%5==0 end, function(v) return v..' is multiple of 5' end}, + {function() return true end, function(v) return 'could not find an answer for '..v end} + }) + for i = 15, 20 do + assert_equal(multipleOf(i), + i%2 == 0 and i..' is multiple of 2' or + i%3 == 0 and i..' is multiple of 3' or + 'could not find an answer for '..i) + end + end) + + end) context('uniqueId', function() test('returns an unique (for the current session) integer Id',function() local ids = {} for i = 1,100 do - local newId = _.uniqueId() - assert_false(_.include(ids,newId)) - _.push(ids,newId) + local newId = M.uniqueId() + assert_false(M.include(ids,newId)) + M.push(ids,newId) end end) test('accepts a string template to format the returned id',function() local ids = {} for i = 1,100 do - local newId = _.uniqueId('ID:%s') + local newId = M.uniqueId('ID:%s') assert_equal(newId,'ID:'..newId:sub(4)) - assert_false(_.include(ids,newId)) - _.push(ids,newId) + assert_false(M.include(ids,newId)) + M.push(ids,newId) end end) @@ -311,10 +341,10 @@ context('Utility functions specs', function() local ids = {} local formatter = function(ID) return '$'..ID..'$' end for i = 1,100 do - local newId = _.uniqueId(formatter) + local newId = M.uniqueId(formatter) assert_not_nil(newId:match('^%$%d+%$$')) - assert_false(_.include(ids,newId)) - _.push(ids,newId) + assert_false(M.include(ids,newId)) + M.push(ids,newId) end end) @@ -323,45 +353,125 @@ context('Utility functions specs', function() context('iterator', function() test('creates an iterator which continuously applies f on an input',function() - local next_even = _.iterator(function(x) return x + 2 end, 0) + local next_even = M.iterator(function(x) return x + 2 end, 0) assert_equal(next_even(), 2) assert_equal(next_even(), 4) assert_equal(next_even(), 6) assert_equal(next_even(), 8) assert_equal(next_even(),10) end) + + test('can be set to run up to a maximum number of calls',function() + local next_even = M.iterator(function(x) return x + 2 end, 0, 3) + assert_equal(next_even(), 2) + assert_equal(next_even(), 4) + assert_equal(next_even(), 6) + assert_nil(next_even()) + end) end) context('array', function() test('iterates a given iterator and returns its values in an array',function() - local letters = _.array(('Lua'):gmatch('.')) - assert_true(_.isEqual(letters,{'L','u','a'})) + local letters = M.array(('Lua'):gmatch('.')) + assert_true(M.isEqual(letters,{'L','u','a'})) - local numbers = _.array(pairs(_.range(1,10))) - assert_true(_.isEqual(numbers,_.range(1,10))) + local numbers = M.array(pairs(M.range(1,10))) + assert_true(M.isEqual(numbers,M.range(1,10))) end) - end) + end) + + context('castArray', function() + + test('converts value to an array',function() + assert_true(M.isEqual(M.castArray(1),{1})) + assert_true(M.isEqual(M.castArray(print),{print})) + assert_true(M.isEqual(M.castArray(true),{true})) + end) + + test('leaves given value untouched if it is an array',function() + local t1 = {1,2} + local t2 = {nil, true, false} + assert_true(M.isEqual(M.castArray(t1),t1)) + assert_true(M.isEqual(M.castArray(t2),t2)) + end) + + end) context('flip', function() test('creates a function which runs f with arguments flipped',function() local function f(...) return table.concat({...}) end - local flipped = _.flip(f) + local flipped = M.flip(f) assert_equal(flipped('a','b','c'),'cba') end) - end) + end) + + context('nthArg', function() + + test('creates a function which returns the nth arg',function() + local f2 = M.nthArg(2) + local f3 = M.nthArg(3) + local f4 = M.nthArg(4) + assert_equal(f2(4,8,5,4,6),8) + assert_equal(f3(4,8,5,4,6),5) + assert_equal(f4(4,8,5,4,6),4) + end) + + test('if n is negative, will count from the end',function() + local f2 = M.nthArg(-2) + local f3 = M.nthArg(-3) + local f4 = M.nthArg(-4) + assert_equal(f2(4,8,5,4,6),4) + assert_equal(f3(4,8,5,4,6),5) + assert_equal(f4(4,8,5,4,6),8) + end) + + end) + + context('unary', function() + + test('creates a function which accepts only one arg',function() + local f = M.unary(function(...) return ... end) + assert_equal(f(1),1) + assert_equal(f(1,2),1) + assert_equal(f(1,2,3),1) + end) + + end) + + context('ary', function() + + test('creates a function which accepts up to n args',function() + local f = M.ary(function(...) return ... end, 2) + assert_true(M.isEqual({f(1,2)},{1,2})) + assert_true(M.isEqual({f(1,2,3)},{1,2})) + assert_true(M.isEqual({f(1,2,3,4)},{1,2})) + end) + + end) + + context('rearg', function() + + test('creates a function with args reordered',function() + local f = M.rearg(function(...) return ... end, {3,2,1}) + assert_true(M.isEqual({f(1,2,3)},{3,2,1})) + assert_true(M.isEqual({f(2,1,3)},{3,1,2})) + assert_true(M.isEqual({f(3,2,1)},{1,2,3})) + end) + + end) context('over', function() test('returns a function which applies a set of transforms to its args',function() - local minmax = _.over(math.min, math.max) - local maxmin = _.over(math.max, math.min) - assert_true(_.isEqual(minmax(5,10,12,4,3),{3,12})) - assert_true(_.isEqual(maxmin(5,10,12,4,3),{12,3})) + local minmax = M.over(math.min, math.max) + local maxmin = M.over(math.max, math.min) + assert_true(M.isEqual(minmax(5,10,12,4,3),{3,12})) + assert_true(M.isEqual(maxmin(5,10,12,4,3),{12,3})) end) end) @@ -383,7 +493,7 @@ context('Utility functions specs', function() end) test('checks if all predicates passes truth with args. ',function() - local allok = _.overEvery(alleven, allpositive) + local allok = M.overEvery(alleven, allpositive) assert_false(allok(2,4,-1,8)) assert_false(allok(10,3,2,6)) assert_true(allok(8,4,6,10)) @@ -408,7 +518,7 @@ context('Utility functions specs', function() end) test('checks if all predicates passes truth with args. ',function() - local anyok = _.overSome(alleven, allpositive) + local anyok = M.overSome(alleven, allpositive) assert_false(anyok(2,4,-1,8)) assert_true(anyok(10,3,2,6)) assert_false(anyok(-1,-5,-3)) @@ -422,27 +532,41 @@ context('Utility functions specs', function() local function f(x, y) return {x, y} end local function triple(x) return x*3 end local function square(x) return x^2 end - local new_f = _.overArgs(f, triple, square) - assert_true(_.isEqual(new_f(1,2), {3,4})) - assert_true(_.isEqual(new_f(10,10), {30,100})) + local new_f = M.overArgs(f, triple, square) + assert_true(M.isEqual(new_f(1,2), {3,4})) + assert_true(M.isEqual(new_f(10,10), {30,100})) end) test('when supplied more args than transforms, remaining are left as-is',function() local function f(x, y, z, k) return {x, y, z, k} end local function triple(x) return x*3 end local function square(x) return x^2 end - local new_f = _.overArgs(f, triple, square) - assert_true(_.isEqual(new_f(1,2,3,4), {3,4,3,4})) - assert_true(_.isEqual(new_f(10,10,10,10), {30,100,10,10})) + local new_f = M.overArgs(f, triple, square) + assert_true(M.isEqual(new_f(1,2,3,4), {3,4,3,4})) + assert_true(M.isEqual(new_f(10,10,10,10), {30,100,10,10})) end) end) + context('converge', function() + + test('', function() + local function pow2(x) return x*x end + local function pow3(x) return x*x*x end + local function sum(a,b) return a+b end + local poly = M.converge(sum, pow2, pow3) + assert_equal(poly(5), 150) + assert_equal(poly(1), 2) + assert_equal(poly(3), 36) + end) + + end) + context('partial', function() test('applies partially f',function() local function diff(a, b) return a - b end - local diffFrom20 = _.partial(diff, 20) + local diffFrom20 = M.partial(diff, 20) assert_equal(diffFrom20(5), 15) assert_equal(diffFrom20(10), 10) assert_equal(diffFrom20(-5), 25) @@ -450,7 +574,7 @@ context('Utility functions specs', function() test('\'_\' can be used as a placeholder',function() local function diff(a, b) return a - b end - local remove10 = _.partial(diff, '_',10) + local remove10 = M.partial(diff, '_',10) assert_equal(remove10(5), -5) assert_equal(remove10(10), 0) assert_equal(remove10(15), 5) @@ -462,16 +586,16 @@ context('Utility functions specs', function() test('applies partial but from the right',function() local function concat(a,b,c,d) return a..b..c..d end - assert_equal(_.partialRight(concat,'a','b','c')('d'), 'dabc') - assert_equal(_.partialRight(concat,'a','b')('c','d'), 'cdab') - assert_equal(_.partialRight(concat,'a')('b','c','d'), 'bcda') + assert_equal(M.partialRight(concat,'a','b','c')('d'), 'dabc') + assert_equal(M.partialRight(concat,'a','b')('c','d'), 'cdab') + assert_equal(M.partialRight(concat,'a')('b','c','d'), 'bcda') end) test('\'_\' can be used as a placeholder',function() local function concat(a,b,c,d) return a..b..c..d end - assert_equal(_.partialRight(concat,'a','_','c')('d','b'), 'badc') - assert_equal(_.partialRight(concat,'a','b','_')('c','d'), 'dabc') - assert_equal(_.partialRight(concat,'_','a')('b','c','d'), 'cdba') + assert_equal(M.partialRight(concat,'a','_','c')('d','b'), 'badc') + assert_equal(M.partialRight(concat,'a','b','_')('c','d'), 'dabc') + assert_equal(M.partialRight(concat,'_','a')('b','c','d'), 'cdba') end) end) @@ -480,20 +604,20 @@ context('Utility functions specs', function() test('curries a function for a specific number of args',function() local function sumOf5args(a,b,c,d,e) return a+b+c+d+e end - local curried_sumOf5args = _.curry(sumOf5args, 5) + local curried_sumOf5args = M.curry(sumOf5args, 5) assert_equal(curried_sumOf5args(1)(2)(3)(4)(5),15) assert_equal(curried_sumOf5args(8)(-2)(4)(-10)(1),1) end) test('n_args defaults to 2 when not supplied',function() local function prod(x,y) return x*y end - local curried_prod = _.curry(prod) - assert_equal(curried_prod(2)(3), (_.curry(prod,2))(2)(3)) - assert_equal(curried_prod(-2)(6), (_.curry(prod,2))(-2)(6)) + local curried_prod = M.curry(prod) + assert_equal(curried_prod(2)(3), (M.curry(prod,2))(2)(3)) + assert_equal(curried_prod(-2)(6), (M.curry(prod,2))(-2)(6)) end) test('n_args can be equal to 1',function() - local curried_identity = _.curry(_.identity,1) + local curried_identity = M.curry(M.identity,1) assert_equal(curried_identity('value'), 'value') assert_equal(curried_identity(1), 1) assert_equal(curried_identity(true), true) @@ -502,14 +626,14 @@ context('Utility functions specs', function() test('giving more args than n_args will raise an error',function() local function add(a,b) return a+b end - local curried_add = _.curry(add, 2) + local curried_add = M.curry(add, 2) assert_error(function() curried_add(1)(2)(3) end) assert_error(function() curried_add(4)(5)(6)(7)(8) end) end) test('When given less than n_args, it will wait for missing args',function() local function add(a,b,c) return a+b+c end - local curried_add = _.curry(add, 3) + local curried_add = M.curry(add, 3) local c1 = curried_add(1) local c2 = c1(2) local c3 = c2(3) @@ -525,11 +649,11 @@ context('Utility functions specs', function() test('returns the execution time of a function and its results', function() local function f(...) return ... end - local duration, r = _.time(f, 'a') + local duration, r = M.time(f, 'a') assert_type(duration, 'number') assert_equal(r, 'a') - local duration, a, b, c = _.time(f, 1, 2, 3) + local duration, a, b, c = M.time(f, 1, 2, 3) assert_type(duration, 'number') assert_true(a == 1 and b == 2 and c == 3) end) diff --git a/spec/import_spec.lua b/spec/import_spec.lua index c158510..1c11c7a 100644 --- a/spec/import_spec.lua +++ b/spec/import_spec.lua @@ -1,4 +1,4 @@ -require 'luacov' +--require 'luacov' local _ = require 'moses' context('Import specs', function() @@ -6,27 +6,15 @@ context('Import specs', function() test('imports all library function to a given context', function() local funcs = _.functions() local context = _.import({}) - assert_true(_.all(funcs, function(k, n) return _.has(context, n) end)) + assert_true(_.all(funcs, function(n) return _.has(context, n) end)) end) test('passing "noConflict" will preserve already existing keys', function() local funcs = _.functions() local context = _.import({each = 1, all = 2}, true) - assert_true(_.all(funcs, function(k, n) return _.has(context, n) end)) + assert_true(_.all(funcs, function(n) return _.has(context, n) end)) assert_equal(context.each, 1) assert_equal(context.all, 2) end) - - test('The context will default to the global _G if not supplied', function() - local oldG = _.clone(_G,true) - assert_not_equal(_G, oldG) - _.import() - local funcs = _.functions() - _.each(funcs, function(__, fname) - assert_not_nil(_G[fname]) - assert_true(type(_G[fname]) == 'function') - end) - _G = oldG - end) end)
\ No newline at end of file diff --git a/spec/object_spec.lua b/spec/object_spec.lua index 139083a..f9d2936 100644 --- a/spec/object_spec.lua +++ b/spec/object_spec.lua @@ -1,14 +1,14 @@ -require 'luacov' -local _ = require 'moses' +--require 'luacov' +local M = require 'moses' context('Object functions specs', function() context('keys', function() test('collects a given object attributes',function() - assert_true(_.isEqual(_.keys({1,2,3}),{1,2,3})) - assert_true(_.isEqual(_.keys({4,5,6}),{1,2,3})) - assert_true(_.same(_.keys({x = 1, y = 2, 3}),{'x','y',1})) + assert_true(M.isEqual(M.keys({1,2,3}),{1,2,3})) + assert_true(M.isEqual(M.keys({4,5,6}),{1,2,3})) + assert_true(M.same(M.keys({x = 1, y = 2, 3}),{'x','y',1})) end) end) @@ -16,21 +16,41 @@ context('Object functions specs', function() context('values', function() test('collects an given object values',function() - assert_true(_.isEqual(_.values({1,2,3}),{1,2,3})) - assert_true(_.isEqual(_.values({4,5,6}),{4,5,6})) - assert_true(_.same(_.values({x = 1, y = 2, 3}),{1,2,3})) + assert_true(M.isEqual(M.values({1,2,3}),{1,2,3})) + assert_true(M.isEqual(M.values({4,5,6}),{4,5,6})) + assert_true(M.same(M.values({x = 1, y = 2, 3}),{1,2,3})) end) - end) + end) + + context('path', function() + + test('return the value at a given path in object',function() + local entity = { + pos = {x = 1}, + engine = { + left = {status = 'active'}, + right = {damage = 10} + }, + boost = false + } + assert_equal(M.path(entity, 'pos','x'), 1) + assert_equal(M.path(entity, 'engine','left','status'), 'active') + assert_equal(M.path(entity, 'engine','right','damage'), 10) + assert_equal(M.path(entity, 'boost'), false) + assert_nil(M.path(entity, 'x')) + end) + + end) context('kvpairs', function() test('converts key-values pairs in object to array-list of k,v pairs',function() - local obj = _.kvpairs({x = 1, y = 2, z = 3}) + local obj = M.kvpairs({x = 1, y = 2, z = 3}) table.sort(obj, function(a,b) return a[1] < b[1] end) - assert_true(_.isEqual(obj[1],{'x',1})) - assert_true(_.isEqual(obj[2],{'y',2})) - assert_true(_.isEqual(obj[3],{'z',3})) + assert_true(M.isEqual(obj[1],{'x',1})) + assert_true(M.isEqual(obj[2],{'y',2})) + assert_true(M.isEqual(obj[3],{'z',3})) end) end) @@ -38,7 +58,7 @@ context('Object functions specs', function() context('toObj', function() test('converts an array-list of {k,v} pairs to an object',function() - local obj = _.toObj({{'x',1},{'y',2},{'z',3}}) + local obj = M.toObj({{'x',1},{'y',2},{'z',3}}) assert_equal(obj.x,1) assert_equal(obj.y,2) assert_equal(obj.z,3) @@ -49,10 +69,10 @@ context('Object functions specs', function() context('property', function() test('Returns a function that will return the key property of any passed-in object.',function() - assert_equal(_.property('sin')(math), math.sin) - assert_equal(_.property('find')(string), string.find) - assert_equal(_.property('insert')(table), table.insert) - assert_equal(_.property('yield')(coroutine), coroutine.yield) + assert_equal(M.property('sin')(math), math.sin) + assert_equal(M.property('find')(string), string.find) + assert_equal(M.property('insert')(table), table.insert) + assert_equal(M.property('yield')(coroutine), coroutine.yield) end) end) @@ -60,10 +80,10 @@ context('Object functions specs', function() context('propertyOf', function() test('Returns a function which will return the value of an object property.',function() - assert_equal(_.propertyOf(math)('cos'), math.cos) - assert_equal(_.propertyOf(string)('char'), string.char) - assert_equal(_.propertyOf(table)('remove'), table.remove) - assert_equal(_.propertyOf(_)('propertyOf'), _.propertyOf) + assert_equal(M.propertyOf(math)('cos'), math.cos) + assert_equal(M.propertyOf(string)('char'), string.char) + assert_equal(M.propertyOf(table)('remove'), table.remove) + assert_equal(M.propertyOf(M)('propertyOf'), M.propertyOf) end) end) @@ -72,19 +92,19 @@ context('Object functions specs', function() context('toBoolean', function() test('converts a value to a boolean',function() - assert_true(type(_.toBoolean(true)) == 'boolean') - assert_true(type(_.toBoolean(1)) == 'boolean') - assert_true(type(_.toBoolean(false)) == 'boolean') - assert_true(type(_.toBoolean(nil)) == 'boolean') - assert_true(type(_.toBoolean({})) == 'boolean') - assert_true(type(_.toBoolean(1/0)) == 'boolean') + assert_true(type(M.toBoolean(true)) == 'boolean') + assert_true(type(M.toBoolean(1)) == 'boolean') + assert_true(type(M.toBoolean(false)) == 'boolean') + assert_true(type(M.toBoolean(nil)) == 'boolean') + assert_true(type(M.toBoolean({})) == 'boolean') + assert_true(type(M.toBoolean(1/0)) == 'boolean') - assert_true(_.toBoolean(true)) - assert_true(_.toBoolean(1)) - assert_false(_.toBoolean(false)) - assert_false(_.toBoolean(nil)) - assert_true(_.toBoolean({})) - assert_true(_.toBoolean(1/0)) + assert_true(M.toBoolean(true)) + assert_true(M.toBoolean(1)) + assert_false(M.toBoolean(false)) + assert_false(M.toBoolean(nil)) + assert_true(M.toBoolean({})) + assert_true(M.toBoolean(1/0)) end) end) @@ -92,32 +112,32 @@ context('Object functions specs', function() context('extend', function() test('extends a destination objects with key-values a source object',function() - assert_true(_.isEqual(_.extend({},{a = 'b'}),{a = 'b'})) + assert_true(M.isEqual(M.extend({},{a = 'b'}),{a = 'b'})) end) test('source properties overrides destination properties',function() - assert_true(_.isEqual(_.extend({a = 'a'},{a = 'b'}),{a = 'b'})) + assert_true(M.isEqual(M.extend({a = 'a'},{a = 'b'}),{a = 'b'})) end) test('leaves source object untouched',function() local source = {i = 'i'} - assert_true(_.isEqual(_.extend({a = 'a'},source),{a = 'a',i = 'i'})) - assert_true(_.isEqual(source,{i = 'i'})) + assert_true(M.isEqual(M.extend({a = 'a'},source),{a = 'a',i = 'i'})) + assert_true(M.isEqual(source,{i = 'i'})) end) test('can extend destination from multiple sources',function() local sourceA = {a = 'a'}; local sourceBC = {b = 'b', c = 'c'} - assert_true(_.isEqual(_.extend({},sourceA, sourceBC),{a = 'a', b = 'b', c = 'c'})) + assert_true(M.isEqual(M.extend({},sourceA, sourceBC),{a = 'a', b = 'b', c = 'c'})) end) test('extending from multiple source, latter properties overrides',function() local sourceA = {a = 'a'}; local sourceBC = {b = 'b', a = 'c'} - assert_true(_.isEqual(_.extend({},sourceA, sourceBC),{a = 'c', b = 'b'})) + assert_true(M.isEqual(M.extend({},sourceA, sourceBC),{a = 'c', b = 'b'})) end) test('will not copy nil values',function() local sourceA = {a = nil}; local sourceBC = {b = 'b', c = nil} - assert_true(_.isEqual(_.extend({},sourceA, sourceBC),{b = 'b'})) + assert_true(M.isEqual(M.extend({},sourceA, sourceBC),{b = 'b'})) end) end) @@ -126,7 +146,7 @@ context('Object functions specs', function() test('collects function names within an object',function() local x = {} function x.a() return end; function x.b() return end - assert_true(_.isEqual(_.functions(x),{'a','b'})) + assert_true(M.isEqual(M.functions(x),{'a','b'})) end) test('collects metatable functions if "recurseMt" arg is supplied',function() @@ -134,14 +154,14 @@ context('Object functions specs', function() function x.a() return end; function x.b() return end local xx = setmetatable({},x) function xx.c() return end - assert_true(_.same(_.functions(xx),{'c'})) - assert_true(_.same(_.functions(xx,true),{'a','b','c'})) + assert_true(M.same(M.functions(xx),{'c'})) + assert_true(M.same(M.functions(xx,true),{'a','b','c'})) end) test('when given no obj as argument, returns all library functions',function() - local functions = _.functions() - _.each(functions, function(k,v) - assert_true(_.isFunction(_[v])) + local functions = M.functions() + M.each(functions, function(v) + assert_true(M.isFunction(M[v])) end) end) @@ -151,32 +171,32 @@ context('Object functions specs', function() test('clones the attributes of an object',function() local vector = {x = 0, y = 0} - assert_true(_.isEqual(_.clone(vector),vector)) + assert_true(M.isEqual(M.clone(vector),vector)) end) test('By default, cloning is deep (clones nested tables)',function() local particle = {position = {x = 0,y=0},mass = 1} - local particle_clone = _.clone (particle) - assert_true(_.isEqual(particle_clone,particle)) + local particle_clone = M.clone (particle) + assert_true(M.isEqual(particle_clone,particle)) particle_clone.position.x = 3 - assert_false(_.isEqual(particle_clone,particle)) + assert_false(M.isEqual(particle_clone,particle)) end) test('Unless "shallow" arg is provided',function() local particle = {position = {x = 0,y=0},mass = 1} - local particle_clone = _.clone (particle,true) - assert_true(_.isEqual(particle_clone,particle)) + local particle_clone = M.clone (particle,true) + assert_true(M.isEqual(particle_clone,particle)) particle_clone.position.x = 3 - assert_true(_.isEqual(particle_clone,particle)) + assert_true(M.isEqual(particle_clone,particle)) end) test('Non objects are simply returned',function() - assert_equal(_.clone(1),1) - assert_equal(_.clone(false),false) - assert_equal(_.clone(true),true) - assert_equal(_.clone(nil),nil) - assert_equal(_.clone('hello'),'hello') - assert_equal(_.clone(print),print) + assert_equal(M.clone(1),1) + assert_equal(M.clone(false),false) + assert_equal(M.clone(true),true) + assert_equal(M.clone(nil),nil) + assert_equal(M.clone('hello'),'hello') + assert_equal(M.clone(print),print) end) end) @@ -185,13 +205,13 @@ context('Object functions specs', function() test('tap-into a method chain', function() local t = {} - local catchMax = function(k) t[#t+1] = _.max(k) end - local catchMin = function(k) t[#t+1] = _.min(k) end + local catchMax = function(k) t[#t+1] = M.max(k) end + local catchMin = function(k) t[#t+1] = M.min(k) end - _.chain({1,2,3}) - :map(function(i,j) return j*2 end) + M.chain({1,2,3}) + :map(function(j) return j*2 end) :tap(catchMax) - :map(function(i,k) return k^2 end) + :map(function(k) return k^2 end) :tap(catchMin) :value() @@ -204,11 +224,11 @@ context('Object functions specs', function() context('has', function() test('checks if an object has an attribute',function() - assert_true(_.has(_,'has')) - assert_true(_.has(table,'concat')) - assert_true(_.has(string,'format')) - assert_true(_.has(os,'time')) - assert_true(_.has(math,'random')) + assert_true(M.has(M,'has')) + assert_true(M.has(table,'concat')) + assert_true(M.has(string,'format')) + assert_true(M.has(os,'time')) + assert_true(M.has(math,'random')) end) end) @@ -217,27 +237,27 @@ context('Object functions specs', function() test('collect specified properties',function() local object = {a = 1, b = 2, c = 3} - assert_true(_.isEqual(_.pick(object,'a','c'),{a = 1, c = 3})) + assert_true(M.isEqual(M.pick(object,'a','c'),{a = 1, c = 3})) end) test('given args can be nested as well',function() local object = {a = 1, b = 2, c = 3} - assert_true(_.isEqual(_.pick(object,{{'b','a'}},'c'),{a = 1,b = 2, c = 3})) + assert_true(M.isEqual(M.pick(object,{{'b','a'}},'c'),{a = 1,b = 2, c = 3})) end) test('will ignore properties the object do not have',function() local object = {a = 1, b = 2, c = 3} - assert_true(_.isEqual(_.pick(object,{{'k'}},'c'),{c = 3})) + assert_true(M.isEqual(M.pick(object,{{'k'}},'c'),{c = 3})) end) test('returns an empty table when given no properties to pick',function() local object = {a = 1, b = 2, c = 3} - assert_true(_.isEqual(_.pick(object),{})) + assert_true(M.isEqual(M.pick(object),{})) end) test('should also pick attributes having falsy values',function() local object = {a = false, b = false, c = true} - assert_true(_.isEqual(_.pick(object,'a','b'),{a = false,b = false})) + assert_true(M.isEqual(M.pick(object,'a','b'),{a = false,b = false})) end) end) @@ -246,22 +266,22 @@ context('Object functions specs', function() test('collect all properties leaving those given as args',function() local object = {a = 1, b = 2, c = 3} - assert_true(_.isEqual(_.omit(object,'a','c'),{b=2})) + assert_true(M.isEqual(M.omit(object,'a','c'),{b=2})) end) test('given args can be nested as well',function() local object = {a = 1, b = 2, c = 3} - assert_true(_.isEqual(_.omit(object,{{'b'}},'c'),{a = 1})) + assert_true(M.isEqual(M.omit(object,{{'b'}},'c'),{a = 1})) end) test('will ignore properties the object do not have',function() local object = {a = 1, b = 2, c = 3} - assert_true(_.isEqual(_.omit(object,{{'k'}},'c'),{a = 1, b=2})) + assert_true(M.isEqual(M.omit(object,{{'k'}},'c'),{a = 1, b=2})) end) test('returns the original object clone when given no properties to omit',function() local object = {a = 1, b = 2, c = 3} - assert_true(_.isEqual(_.omit(object),{a = 1, b = 2, c = 3})) + assert_true(M.isEqual(M.omit(object),{a = 1, b = 2, c = 3})) end) end) @@ -269,15 +289,15 @@ context('Object functions specs', function() context('template', function() test('applies a template on an object',function() - assert_true(_.isEqual(_.template({},{a = 1, b = 2, c = 3}),{a = 1, b = 2, c = 3})) + assert_true(M.isEqual(M.template({},{a = 1, b = 2, c = 3}),{a = 1, b = 2, c = 3})) end) test('does not override existing properies',function() - assert_true(_.isEqual(_.template({a = 10, b = 10},{a = 1, b = 2, c = 3}),{a = 10, b = 10, c = 3})) + assert_true(M.isEqual(M.template({a = 10, b = 10},{a = 1, b = 2, c = 3}),{a = 10, b = 10, c = 3})) end) test('returns the object when given no template arg',function() - assert_true(_.isEqual(_.template({a = 10, b = 10}),{a = 10, b = 10})) + assert_true(M.isEqual(M.template({a = 10, b = 10}),{a = 10, b = 10})) end) end) @@ -285,39 +305,39 @@ context('Object functions specs', function() context('isEqual', function() test('compares values',function() - assert_true(_.isEqual(1,1)) - assert_true(_.isEqual(1.0,1)) - assert_false(_.isEqual(1,2)) - assert_false(_.isEqual(2,2.0001)) + assert_true(M.isEqual(1,1)) + assert_true(M.isEqual(1.0,1)) + assert_false(M.isEqual(1,2)) + assert_false(M.isEqual(2,2.0001)) end) test('compares objects by reference and components',function() local oldprint = print - assert_true(_.isEqual(print,oldprint)) + assert_true(M.isEqual(print,oldprint)) local t = {} local v = t - assert_true(_.isEqual(t,v)) - assert_true(_.isEqual({},{})) + assert_true(M.isEqual(t,v)) + assert_true(M.isEqual({},{})) - assert_false(_.isEqual('a','b')) + assert_false(M.isEqual('a','b')) - assert_false(_.isEqual(true, false)) - assert_false(_.isEqual(nil, false)) - assert_false(_.isEqual(true, nil)) + assert_false(M.isEqual(true, false)) + assert_false(M.isEqual(nil, false)) + assert_false(M.isEqual(true, nil)) end) test('compares nested properties',function() - assert_true(_.isEqual({x = 0,{x1 = 0,{x2 =0}}}, {x = 0,{x1 = 0,{x2 =0}}})) - assert_false(_.isEqual({x = 0,{x1 = 0,{x2 =0}}}, {x = 0,{x1 = 0,{x2 =1}}})) + assert_true(M.isEqual({x = 0,{x1 = 0,{x2 =0}}}, {x = 0,{x1 = 0,{x2 =0}}})) + assert_false(M.isEqual({x = 0,{x1 = 0,{x2 =0}}}, {x = 0,{x1 = 0,{x2 =1}}})) end) test('can compare tables on the basis of their metatable',function() local a, b = {x = 1, y = 2}, {x = 2, y = 1} setmetatable(a,{__eq = function(a,b) return (a.x and b.x and a.y and b.y)~=nil end}) - assert_false(_.isEqual(a, b)) - assert_true(_.isEqual(a, b, true)) + assert_false(M.isEqual(a, b)) + assert_true(M.isEqual(a, b, true)) end) @@ -326,18 +346,18 @@ context('Object functions specs', function() context('result', function() test('calls an object method, passing it as a first arg the object itself',function() - assert_equal(_.result('a','len'),1) - assert_equal(_.result('hello','reverse'),'olleh') - assert_equal(_.result({'a','b','c'},table.concat),'abc') + assert_equal(M.result('a','len'),1) + assert_equal(M.result('hello','reverse'),'olleh') + assert_equal(M.result({'a','b','c'},table.concat),'abc') end) test('handles extra-args to be passed to the so-called method',function() - assert_equal(_.result('Hello','match','%u'),'H') - assert_equal(_.result({'a','b','c'},table.concat,' '),'a b c') + assert_equal(M.result('Hello','match','%u'),'H') + assert_equal(M.result({'a','b','c'},table.concat,' '),'a b c') end) test('returns the property itself if not callable',function() - assert_equal(_.result({size = 0},'size'),0) + assert_equal(M.result({size = 0},'size'),0) end) end) @@ -345,23 +365,23 @@ context('Object functions specs', function() context('isTable', function() test('returns "true" if arg is table or array',function() - assert_true(_.isTable({})) - assert_true(_.isTable({1,2})) - assert_true(_.isTable({x = 1, 2})) - assert_true(_.isTable(string)) - assert_true(_.isTable(table)) - assert_true(_.isTable(math)) + assert_true(M.isTable({})) + assert_true(M.isTable({1,2})) + assert_true(M.isTable({x = 1, 2})) + assert_true(M.isTable(string)) + assert_true(M.isTable(table)) + assert_true(M.isTable(math)) end) test('returns "false" otherwise',function() - assert_false(_.isTable(1)) - assert_false(_.isTable('')) - assert_false(_.isTable(function() end)) - assert_false(_.isTable(print)) - assert_false(_.isTable(false)) - assert_false(_.isTable(nil)) - assert_false(_.isTable(true)) + assert_false(M.isTable(1)) + assert_false(M.isTable('')) + assert_false(M.isTable(function() end)) + assert_false(M.isTable(print)) + assert_false(M.isTable(false)) + assert_false(M.isTable(nil)) + assert_false(M.isTable(true)) end) end) @@ -369,20 +389,20 @@ context('Object functions specs', function() context('isCallable', function() test('returns "true" if arg is callable',function() - assert_true(_.isCallable(print)) - assert_true(_.isCallable(function() end)) - assert_true(_.isCallable(string.gmatch)) - assert_true(_.isCallable(setmetatable({},{__index = string}).upper)) - assert_true(_.isCallable(setmetatable({},{__call = function() return end}))) + assert_true(M.isCallable(print)) + assert_true(M.isCallable(function() end)) + assert_true(M.isCallable(string.gmatch)) + assert_true(M.isCallable(setmetatable({},{__index = string}).upper)) + assert_true(M.isCallable(setmetatable({},{__call = function() return end}))) end) test('returns "false" otherwise',function() - assert_false(_.isCallable(1)) - assert_false(_.isCallable('')) - assert_false(_.isCallable({})) - assert_false(_.isCallable(false)) - assert_false(_.isCallable(nil)) - assert_false(_.isCallable(true)) + assert_false(M.isCallable(1)) + assert_false(M.isCallable('')) + assert_false(M.isCallable({})) + assert_false(M.isCallable(false)) + assert_false(M.isCallable(nil)) + assert_false(M.isCallable(true)) end) end) @@ -390,29 +410,29 @@ context('Object functions specs', function() context('isArray', function() test('returns "true" if arg is an array',function() - assert_true(_.isArray({})) - assert_true(_.isArray({1,2,3})) - assert_true(_.isArray({'a','b','c',{}})) - assert_true(_.isArray({false,true})) - assert_true(_.isArray({1,nil})) + assert_true(M.isArray({})) + assert_true(M.isArray({1,2,3})) + assert_true(M.isArray({'a','b','c',{}})) + assert_true(M.isArray({false,true})) + assert_true(M.isArray({1,nil})) end) test('returns "false" otherwise',function() - assert_false(_.isArray(1)) - assert_false(_.isArray('')) - assert_false(_.isArray(false)) - assert_false(_.isArray(nil)) - assert_false(_.isArray(true)) - assert_false(_.isArray(print)) - assert_false(_.isArray({a = 1, x = 1})) - assert_false(_.isArray({a = 1, 1, 2,3})) - assert_false(_.isArray({1,nil,2})) - assert_false(_.isArray({1,nil,3,k=4})) - assert_false(_.isArray({a=1})) + assert_false(M.isArray(1)) + assert_false(M.isArray('')) + assert_false(M.isArray(false)) + assert_false(M.isArray(nil)) + assert_false(M.isArray(true)) + assert_false(M.isArray(print)) + assert_false(M.isArray({a = 1, x = 1})) + assert_false(M.isArray({a = 1, 1, 2,3})) + assert_false(M.isArray({1,nil,2})) + assert_false(M.isArray({1,nil,3,k=4})) + assert_false(M.isArray({a=1})) end) test('returns false on "sparse arrays"',function() - assert_false(_.isArray({[1] = true, [10] = false})) + assert_false(M.isArray({[1] = true, [10] = false})) end) end) @@ -420,10 +440,10 @@ context('Object functions specs', function() context('isIterable', function() test('checks if the given object is iterable with pairs',function() - assert_true(_.isIterable({})) - assert_false(_.isIterable(function() end)) - assert_false(_.isIterable(false)) - assert_false(_.isIterable(1)) + assert_true(M.isIterable({})) + assert_false(M.isIterable(function() end)) + assert_false(M.isIterable(false)) + assert_false(M.isIterable(1)) end) end) @@ -431,27 +451,27 @@ context('Object functions specs', function() context('isEmpty', function() test('returns "true" if arg is an empty array',function() - assert_true(_.isEmpty({})) + assert_true(M.isEmpty({})) end) test('returns "false" otherwise',function() - assert_false(_.isEmpty({1,2,3})) - assert_false(_.isEmpty({'a','b','c',{}})) - assert_false(_.isEmpty({nil,false,true})) + assert_false(M.isEmpty({1,2,3})) + assert_false(M.isEmpty({'a','b','c',{}})) + assert_false(M.isEmpty({nil,false,true})) end) test('booleans, nil and functions are considered empty',function() - assert_true(_.isEmpty(print)) - assert_true(_.isEmpty(nil)) - assert_true(_.isEmpty(false)) - assert_true(_.isEmpty(true)) + assert_true(M.isEmpty(print)) + assert_true(M.isEmpty(nil)) + assert_true(M.isEmpty(false)) + assert_true(M.isEmpty(true)) end) test('handles strings',function() - assert_true(_.isEmpty('')) - assert_false(_.isEmpty('a')) - assert_false(_.isEmpty('bcd')) - assert_false(_.isEmpty(' ')) + assert_true(M.isEmpty('')) + assert_false(M.isEmpty('a')) + assert_false(M.isEmpty('bcd')) + assert_false(M.isEmpty(' ')) end) end) @@ -459,18 +479,18 @@ context('Object functions specs', function() context('isString', function() test('returns "true" if arg is a string',function() - assert_true(_.isString('')) - assert_true(_.isString('a')) - assert_true(_.isString(' ')) - assert_true(_.isString(type(nil))) + assert_true(M.isString('')) + assert_true(M.isString('a')) + assert_true(M.isString(' ')) + assert_true(M.isString(type(nil))) end) test('returns "false" otherwise',function() - assert_false(_.isString(false)) - assert_false(_.isString(print)) - assert_false(_.isString(nil)) - assert_false(_.isString(true)) - assert_false(_.isString({})) + assert_false(M.isString(false)) + assert_false(M.isString(print)) + assert_false(M.isString(nil)) + assert_false(M.isString(true)) + assert_false(M.isString({})) end) end) @@ -478,17 +498,17 @@ context('Object functions specs', function() context('isFunction', function() test('returns "true" if arg is a function',function() - assert_true(_.isFunction(print)) - assert_true(_.isFunction(string.match)) - assert_true(_.isFunction(function() end)) + assert_true(M.isFunction(print)) + assert_true(M.isFunction(string.match)) + assert_true(M.isFunction(function() end)) end) test('returns "false" otherwise',function() - assert_false(_.isFunction({})) - assert_false(_.isFunction(nil)) - assert_false(_.isFunction(false)) - assert_false(_.isFunction(true)) - assert_false(_.isFunction('a')) + assert_false(M.isFunction({})) + assert_false(M.isFunction(nil)) + assert_false(M.isFunction(false)) + assert_false(M.isFunction(true)) + assert_false(M.isFunction('a')) end) end) @@ -496,17 +516,17 @@ context('Object functions specs', function() context('isNil', function() test('returns "true" if arg is nil',function() - assert_true(_.isNil(nil)) - assert_true(_.isNil()) - assert_true(_.isNil(a)) + assert_true(M.isNil(nil)) + assert_true(M.isNil()) + assert_true(M.isNil(a)) end) test('returns "false" otherwise',function() - assert_false(_.isNil(false)) - assert_false(_.isNil(true)) - assert_false(_.isNil(table)) - assert_false(_.isNil(function() end)) - assert_false(_.isNil('a')) + assert_false(M.isNil(false)) + assert_false(M.isNil(true)) + assert_false(M.isNil(table)) + assert_false(M.isNil(function() end)) + assert_false(M.isNil('a')) end) end) @@ -514,21 +534,21 @@ context('Object functions specs', function() context('isNumber', function() test('returns "true" if arg is a number',function() - assert_true(_.isNumber(1)) - assert_true(_.isNumber(0.5)) - assert_true(_.isNumber(math.pi)) - assert_true(_.isNumber(1/0)) - assert_true(_.isNumber(math.huge)) - assert_true(_.isNumber(0/0)) + assert_true(M.isNumber(1)) + assert_true(M.isNumber(0.5)) + assert_true(M.isNumber(math.pi)) + assert_true(M.isNumber(1/0)) + assert_true(M.isNumber(math.huge)) + assert_true(M.isNumber(0/0)) end) test('returns "false" otherwise',function() - assert_false(_.isNumber(print)) - assert_false(_.isNumber(nil)) - assert_false(_.isNumber(true)) - assert_false(_.isNumber(false)) - assert_false(_.isNumber({1})) - assert_false(_.isNumber('1')) + assert_false(M.isNumber(print)) + assert_false(M.isNumber(nil)) + assert_false(M.isNumber(true)) + assert_false(M.isNumber(false)) + assert_false(M.isNumber({1})) + assert_false(M.isNumber('1')) end) end) @@ -536,20 +556,20 @@ context('Object functions specs', function() context('isNaN', function() test('returns "true" if arg is NaN',function() - assert_true(_.isNaN(0/0)) + assert_true(M.isNaN(0/0)) end) test('returns "false" for not NaN values',function() - assert_false(_.isNaN(1/0)) - assert_false(_.isNaN(math.huge)) - assert_false(_.isNaN(math.pi)) - assert_false(_.isNaN(1)) - assert_false(_.isNaN('')) - assert_false(_.isNaN('0')) - assert_false(_.isNaN({})) - assert_false(_.isNaN(nil)) - assert_false(_.isNaN(false)) - assert_false(_.isNaN(true)) + assert_false(M.isNaN(1/0)) + assert_false(M.isNaN(math.huge)) + assert_false(M.isNaN(math.pi)) + assert_false(M.isNaN(1)) + assert_false(M.isNaN('')) + assert_false(M.isNaN('0')) + assert_false(M.isNaN({})) + assert_false(M.isNaN(nil)) + assert_false(M.isNaN(false)) + assert_false(M.isNaN(true)) end) end) @@ -557,22 +577,22 @@ context('Object functions specs', function() context('isFinite', function() test('returns "true" if arg is a finite number',function() - assert_true(_.isFinite(1)) - assert_true(_.isFinite(0)) - assert_true(_.isFinite(math.pi)) - assert_true(_.isFinite(99e99)) + assert_true(M.isFinite(1)) + assert_true(M.isFinite(0)) + assert_true(M.isFinite(math.pi)) + assert_true(M.isFinite(99e99)) end) test('returns "false" otherwise',function() - assert_false(_.isFinite(math.huge)) - assert_false(_.isFinite(1/0)) - assert_false(_.isFinite(0/0)) + assert_false(M.isFinite(math.huge)) + assert_false(M.isFinite(1/0)) + assert_false(M.isFinite(0/0)) end) test('returns "false" for non-numbers',function() - assert_false(_.isFinite('')) - assert_false(_.isFinite(function() end)) - assert_false(_.isFinite({})) + assert_false(M.isFinite('')) + assert_false(M.isFinite(function() end)) + assert_false(M.isFinite({})) end) end) @@ -580,20 +600,20 @@ context('Object functions specs', function() context('isBoolean', function() test('returns "true" if arg is a boolean or a thruthy statement',function() - assert_true(_.isBoolean(true)) - assert_true(_.isBoolean(false)) - assert_true(_.isBoolean(1==1)) - assert_true(_.isBoolean(print==tostring)) + assert_true(M.isBoolean(true)) + assert_true(M.isBoolean(false)) + assert_true(M.isBoolean(1==1)) + assert_true(M.isBoolean(print==tostring)) end) test('returns "false" otherwise',function() - assert_false(_.isBoolean('')) - assert_false(_.isBoolean(nil)) - assert_false(_.isBoolean({})) - assert_false(_.isBoolean(function() end)) + assert_false(M.isBoolean('')) + assert_false(M.isBoolean(nil)) + assert_false(M.isBoolean({})) + assert_false(M.isBoolean(function() end)) - assert_false(_.isBoolean(0)) - assert_false(_.isBoolean('1')) + assert_false(M.isBoolean(0)) + assert_false(M.isBoolean('1')) end) end) @@ -601,12 +621,12 @@ context('Object functions specs', function() context('isInteger', function() test('returns "true" if arg is a integer, "false" otherwise',function() - assert_true(_.isInteger(1)) - assert_true(_.isInteger(0)) - assert_false(_.isInteger(math.pi)) - assert_true(_.isInteger(1/0)) - assert_true(_.isInteger(math.huge)) - assert_false(_.isInteger(0/0)) + assert_true(M.isInteger(1)) + assert_true(M.isInteger(0)) + assert_false(M.isInteger(math.pi)) + assert_true(M.isInteger(1/0)) + assert_true(M.isInteger(math.huge)) + assert_false(M.isInteger(0/0)) end) end) diff --git a/spec/op_spec.lua b/spec/op_spec.lua new file mode 100644 index 0000000..f603a6b --- /dev/null +++ b/spec/op_spec.lua @@ -0,0 +1,162 @@ +--require 'luacov' +local M = require 'moses' + +context('Operators specs', function() + + context('Arithmetic operators', function() + + test('add returns a + b', function() + assert_equal(M.operator.add(1,2), 3) + assert_equal(M.operator.add(0,0), 0) + assert_equal(M.operator.add(0,-5), -5) + end) + + test('sub returns a - b', function() + assert_equal(M.operator.sub(1,2), -1) + assert_equal(M.operator.sub(0,0), 0) + assert_equal(M.operator.sub(0,-5), 5) + end) + + test('mul returns a * b', function() + assert_equal(M.operator.mul(1,2), 2) + assert_equal(M.operator.mul(0,0), 0) + assert_equal(M.operator.mul(0,-5), 0) + end) + + test('div returns a / b', function() + assert_equal(M.operator.div(1,2), 0.5) + assert_equal(M.operator.div(5,5), 1) + assert_equal(M.operator.div(8,-2), -4) + end) + + test('mod returns a % b', function() + assert_equal(M.operator.mod(6,3), 0) + assert_equal(M.operator.mod(5,2), 1) + end) + + test('exp returns a ^ b', function() + assert_equal(M.operator.exp(3,3), 27) + assert_equal(M.operator.exp(5,2), 25) + end) + + test('unm returns -a', function() + assert_equal(M.operator.unm(3), -3) + assert_equal(M.operator.unm(-5), 5) + end) + + test('floordiv returns a//b', function() + assert_equal(M.operator.floordiv(5,2), 2) + end) + + test('intdiv performs integer division', function() + assert_equal(M.operator.intdiv(5,2), 2) + assert_equal(M.operator.intdiv(-5,2), -2) + end) + + end) + + context('Relational operators', function() + + test('eq returns a == b', function() + assert_equal(M.operator.eq(5,5), true) + assert_equal(M.operator.eq(5,4.99), false) + end) + + test('neq returns a ~= b', function() + assert_equal(M.operator.neq(5,5), false) + assert_equal(M.operator.neq(5,4.99), true) + end) + + test('lt returns a < b', function() + assert_equal(M.operator.lt(5,5), false) + assert_equal(M.operator.lt(4.99,5), true) + end) + + test('gt returns a > b', function() + assert_equal(M.operator.gt(5,5), false) + assert_equal(M.operator.gt(5,4.99), true) + end) + + test('le returns a <= b', function() + assert_equal(M.operator.le(5,5), true) + assert_equal(M.operator.le(4.99,5), true) + assert_equal(M.operator.le(5,4.99), false) + end) + + test('ge returns a >= b', function() + assert_equal(M.operator.ge(5,5), true) + assert_equal(M.operator.ge(4.99,5), false) + assert_equal(M.operator.ge(5,4.99), true) + end) + + end) + + context('Logical operators', function() + + test('land returns a and b', function() + assert_equal(M.operator.land(true, true),true) + assert_equal(M.operator.land(true, false),false) + assert_equal(M.operator.land(false, true),false) + assert_equal(M.operator.land(false, false),false) + assert_equal(M.operator.land(true, nil),nil) + assert_equal(M.operator.land(false, nil),false) + end) + + test('lor returns a or b', function() + assert_equal(M.operator.lor(true, true),true) + assert_equal(M.operator.lor(true, false),true) + assert_equal(M.operator.lor(false, true),true) + assert_equal(M.operator.lor(false, false),false) + assert_equal(M.operator.lor(true, nil),true) + assert_equal(M.operator.lor(false, nil),nil) + end) + + test('lnot returns not a', function() + assert_equal(M.operator.lnot(true),false) + assert_equal(M.operator.lnot(false),true) + assert_equal(M.operator.lnot(nil),true) + end) + + end) + + context('Length operator', function() + + test('length returns #a', function() + assert_equal(M.operator.length({}),0) + assert_equal(M.operator.length({2}),1) + assert_equal(M.operator.length({3,5,3}),3) + assert_equal(M.operator.length('hello'),5) + end) + + end) + + context('Concatenation operator', function() + + test('concat returns a..b', function() + assert_equal(M.operator.concat('a','b'),'ab') + assert_equal(M.operator.concat('1','2'),'12') + end) + + end) + + context('Aliases', function() + + test('op is an alias to operator', function() + assert_equal(M.operator, M.op) + end) + + test('pow is an alias to exp', function() + assert_equal(M.operator.exp, M.operator.pow) + end) + + test('neg is an alias to unm', function() + assert_equal(M.operator.neg, M.operator.unm) + end) + + test('len is alias to length', function() + assert_equal(M.operator.length,M.operator.len) + end) + + end) + +end)
\ No newline at end of file diff --git a/spec/table_spec.lua b/spec/table_spec.lua index 209969a..ac5c46b 100644 --- a/spec/table_spec.lua +++ b/spec/table_spec.lua @@ -1,53 +1,53 @@ -require 'luacov' -local _ = require 'moses' +--require 'luacov' +local M = require 'moses' context('Table functions specs', function() context('clear', function() test('', function() - local t = _.clear({'a', true, 'hello'}) - assert_true(_.isEqual(t,{})) + local t = M.clear({'a', true, 'hello'}) + assert_true(M.isEqual(t,{})) assert_nil(next(t)) end) end) context('each', function() - - test('provides values and iteration count ', function() - local t = {1,2,3} - local inc = 0 - _.each(t,function(i,v) - inc = inc+1 - assert_equal(i,inc) - assert_equal(t[i],v) - end) - end) - - test('can reference the given table', function() - local t = {1,2,3} - _.each(t,function(i,v,mul) - t[i] = v*mul - end,5) - assert_true(_.isEqual(t,{5,10,15})) - end) - - test('iterates over non-numeric keys and objects', function() - local t = {one = 1, two = 2, three = 3} - local copy = {} - _.each(t,function(i,v) copy[i] = v end) - assert_true(_.isEqual(t,copy)) - end) - - end) + + test('provides values and iteration count ', function() + local t = {4,2,1} + local inc = 0 + M.each(t,function(v, i) + inc = inc+1 + assert_equal(i,inc) + assert_equal(t[i],v) + end) + end) + + test('can reference the given table', function() + local t = {1,2,3} + M.each(t,function(v,i,mul) + t[i] = v*mul + end,5) + assert_true(M.isEqual(t,{5,10,15})) + end) + + test('iterates over non-numeric keys and objects', function() + local t = {one = 1, two = 2, three = 3} + local copy = {} + M.each(t,function(v,i) copy[i] = v end) + assert_true(M.isEqual(t,copy)) + end) + + end) context('eachi', function() test('provides values and iteration count for integer keys only, in a sorted way', function() - local t = {1,2,3} + local t = {4,2,1} local inc = 0 - _.eachi(t,function(i,v) + M.eachi(t,function(v,i) inc = inc+1 assert_equal(i,inc) assert_equal(t[i],v) @@ -59,7 +59,7 @@ context('Table functions specs', function() local rk = {-1, 0, 1, 2} local rv = {6, 1, 3, 5} local inc = 0 - _.eachi(t,function(i,v) + M.eachi(t,function(v,i) inc = inc+1 assert_equal(i,rk[inc]) assert_equal(v,rv[inc]) @@ -72,43 +72,66 @@ context('Table functions specs', function() test('returns an array of values at numeric keys', function() local t = {4,5,6} - local values = _.at(t,1,2,3) - assert_true(_.isEqual(values, t)) + local values = M.at(t,1,2,3) + assert_true(M.isEqual(values, t)) local t = {a = 4, bb = true, ccc = false} - local values = _.at(t,'a', 'ccc') - assert_true(_.isEqual(values, {4, false})) + local values = M.at(t,'a', 'ccc') + assert_true(M.isEqual(values, {4, false})) end) end) + context('adjust', function() + + test('adjusts a given value in a table using a function', function() + local double = function(v) return v * 2 end + local t = {1,2,3} + assert_true(M.isEqual(M.adjust(t,1,double),{2,2,3})) + assert_true(M.isEqual(M.adjust(t,2,double),{1,4,3})) + assert_true(M.isEqual(M.adjust(t,3,double),{1,2,6})) + end) + + test('adjusts a given value in a table using a value', function() + local t = {1,2,3} + assert_true(M.isEqual(M.adjust(t,1,5),{5,2,3})) + assert_true(M.isEqual(M.adjust(t,2,-2),{1,-2,3})) + end) + + test('throws an error if key is not found in table', function() + local double = function(v) return v * 2 end + local t = {x = 1} + assert_error(function() M.adjust(t,'y', 2) end) + end) + + end) + context('count', function() test('count the occurences of value in a list', function() - assert_equal(_.count({1,1,2,3,3,3,2,4,3,2},1),2) - assert_equal(_.count({1,1,2,3,3,3,2,4,3,2},2),3) - assert_equal(_.count({1,1,2,3,3,3,2,4,3,2},3),4) - assert_equal(_.count({1,1,2,3,3,3,2,4,3,2},4),1) - assert_equal(_.count({1,1,2,3,3,3,2,4,3,2},5),0) - assert_equal(_.count({false, false, true},false),2) - assert_equal(_.count({false, false, true},true),1) - assert_equal(_.count({{1,1},{1,1},{1,1},{2,2}},{1,1}),3) - assert_equal(_.count({{1,1},{1,1},{1,1},{2,2}},{2,2}),1) + assert_equal(M.count({1,1,2,3,3,3,2,4,3,2},1),2) + assert_equal(M.count({1,1,2,3,3,3,2,4,3,2},2),3) + assert_equal(M.count({1,1,2,3,3,3,2,4,3,2},3),4) + assert_equal(M.count({1,1,2,3,3,3,2,4,3,2},4),1) + assert_equal(M.count({1,1,2,3,3,3,2,4,3,2},5),0) + assert_equal(M.count({false, false, true},false),2) + assert_equal(M.count({false, false, true},true),1) + assert_equal(M.count({{1,1},{1,1},{1,1},{2,2}},{1,1}),3) + assert_equal(M.count({{1,1},{1,1},{1,1},{2,2}},{2,2}),1) end) test('defaults to size when value is not given', function() - assert_equal(_.count({1,1,2,3,3,3,2,4,3,2}),_.size({1,1,2,3,3,3,2,4,3,2})) - assert_equal(_.count({false, false, true}),_.size({false, false, true})) + assert_equal(M.count({1,1,2,3,3,3,2,4,3,2}),M.size({1,1,2,3,3,3,2,4,3,2})) + assert_equal(M.count({false, false, true}),M.size({false, false, true})) end) end) context('countf', function() - test('count the occurences of values passing an iterator test in a list', function() - assert_equal(_.countf({1,2,3,4,5,6}, function(i,v) + assert_equal(M.countf({1,2,3,4,5,6}, function(v) return v%2==0 end),3) - assert_equal(_.countf({print, pairs, os, assert, ipairs}, function(i,v) + assert_equal(M.countf({print, pairs, os, assert, ipairs}, function(v) return type(v)=='function' end),4) end) @@ -120,12 +143,12 @@ context('Table functions specs', function() local times = 3 local t = {1,2,3,4,5} local kv = {} - for k,v in _.cycle(t,times) do + for v,k in M.cycle(t,times) do assert_equal(t[k],v) kv[#kv+1] = v end for k,v in ipairs(kv) do - assert_equal(_.count(kv,v),times) + assert_equal(M.count(kv,v),times) end end) @@ -134,38 +157,38 @@ context('Table functions specs', function() local t = {x = 1, z = 2} local keys = {} local values = {} - for k,v in _.cycle(t,times) do + for v,k in M.cycle(t,times) do assert_equal(t[k],v) keys[#keys+1] = k values[#values+1] = v end for k,v in ipairs(keys) do - assert_equal(_.count(keys,v),times) + assert_equal(M.count(keys,v),times) end for k,v in ipairs(values) do - assert_equal(_.count(values,v),times) + assert_equal(M.count(values,v),times) end end) test('n defaults to 1, if not supplied', function() local t = {1,2,3,4,5} - for k,v in _.cycle(t) do + for v,k in M.cycle(t) do t[k] = v + 1 end - _.each(t, function(k, v) + M.each(t, function(v, k) assert_equal(v, k + 1) end) end) test('if n is negative or equal to 0, it does nothing', function() local t = {1,2,3,4,5} - for k,v in _.cycle(t, 0) do + for v,k in M.cycle(t, 0) do t[k] = v + 1 end - for k,v in _.cycle(t, -2) do + for v,k in M.cycle(t, -2) do t[k] = v + 1 end - _.each(t, function(k, v) + M.each(t, function(v, k) assert_equal(v, k) end) end) @@ -174,19 +197,19 @@ context('Table functions specs', function() context('map', function() test('applies an iterator function over each key-value pair ', function() - assert_true(_.isEqual(_.map({1,2,3},function(i,v) + assert_true(M.isEqual(M.map({1,2,3},function(v) return v+10 end),{11,12,13})) end) test('iterates over non-numeric keys and objects', function() - assert_true(_.isEqual(_.map({a = 1, b = 2},function(k,v) + assert_true(M.isEqual(M.map({a = 1, b = 2},function(v,k) return k..v end),{a = 'a1',b = 'b2'})) end) test('maps key-value pairs to key-value pairs', function() - assert_true(_.isEqual(_.map({a = 1, b = 2}, function(k, v) + assert_true(M.isEqual(M.map({a = 1, b = 2}, function(v, k) return k .. k, v + 10 end), {aa = 11, bb = 12})) end) @@ -196,18 +219,18 @@ context('Table functions specs', function() context('reduce', function() test('folds a collection (left to right) from an initial state', function() - assert_equal(_.reduce({1,2,3,4},function(memo,v) return memo+v end,0),10) + assert_equal(M.reduce({1,2,3,4},function(memo,v) return memo+v end,0),10) end) test('initial state defaults to the first value when not given', function() - assert_equal(_.reduce({'a','b','c'},function(memo,v) return memo..v end),'abc') + assert_equal(M.reduce({'a','b','c'},function(memo,v) return memo..v end),'abc') end) test('supports arrays of booleans', function() - assert_equal(_.reduce({true, false, true, true},function(memo,v) return memo and v end), false) - assert_equal(_.reduce({true, true, true},function(memo,v) return memo and v end), true) - assert_equal(_.reduce({false, false, false},function(memo,v) return memo and v end), false) - assert_equal(_.reduce({false, false, true},function(memo,v) return memo or v end), true) + assert_equal(M.reduce({true, false, true, true},function(memo,v) return memo and v end), false) + assert_equal(M.reduce({true, true, true},function(memo,v) return memo and v end), true) + assert_equal(M.reduce({false, false, false},function(memo,v) return memo and v end), false) + assert_equal(M.reduce({false, false, true},function(memo,v) return memo or v end), true) end) end) @@ -215,10 +238,10 @@ context('Table functions specs', function() context('reduceby', function() test('folds a collection (left to right) for specific values', function() - local function even(_,v) return v%2==0 end - local function odd(_,v) return v%2~=0 end - assert_equal(_.reduceby({1,2,3,4},function(memo,v) return memo+v end,0,even), 6) - assert_equal(_.reduceby({1,2,3,4},function(memo,v) return memo+v end,0,odd), 4) + local function even(v) return v%2==0 end + local function odd(v) return v%2~=0 end + assert_equal(M.reduceby({1,2,3,4},function(memo,v) return memo+v end,even,0), 6) + assert_equal(M.reduceby({1,2,3,4},function(memo,v) return memo+v end,odd,0), 4) end) end) @@ -226,11 +249,11 @@ context('Table functions specs', function() context('reduceRight', function() test('folds a collection (right to left) from an initial state', function() - assert_equal(_.reduceRight({1,2,4,16},function(memo,v) return memo/v end,256),2) + assert_equal(M.reduceRight({1,2,4,16},function(memo,v) return memo/v end,256),2) end) test('initial state defaults to the first value when not given', function() - assert_equal(_.reduceRight({'a','b','c'},function(memo,v) return memo..v end),'cba') + assert_equal(M.reduceRight({'a','b','c'},function(memo,v) return memo..v end),'cba') end) end) @@ -238,13 +261,13 @@ context('Table functions specs', function() context('mapReduce', function() test('folds a collection (left to right) saving intermediate states', function() - assert_true(_.isEqual(_.mapReduce({1,2,4,16},function(memo,v) + assert_true(M.isEqual(M.mapReduce({1,2,4,16},function(memo,v) return memo*v end,0),{0,0,0,0})) end) test('initial state defaults to the first value when not given', function() - assert_true(_.isEqual(_.mapReduce({'a','b','c'},function(memo,v) + assert_true(M.isEqual(M.mapReduce({'a','b','c'},function(memo,v) return memo..v end),{'a','ab','abc'})) end) @@ -254,13 +277,13 @@ context('Table functions specs', function() context('mapReduceRight', function() test('folds a collection (right to left) saving intermediate states', function() - assert_true(_.isEqual(_.mapReduceRight({1,2,4,16},function(memo,v) + assert_true(M.isEqual(M.mapReduceRight({1,2,4,16},function(memo,v) return memo/v end,256),{16,4,2,2})) end) test('initial state defaults to the first value when not given', function() - assert_true(_.isEqual(_.mapReduceRight({'a','b','c'},function(memo,v) + assert_true(M.isEqual(M.mapReduceRight({'a','b','c'},function(memo,v) return memo..v end),{'c','cb','cba'})) end) @@ -270,19 +293,19 @@ context('Table functions specs', function() context('include', function() test('looks for a value in a collection, returns true when found', function() - assert_true(_.include({6,8,10,16,29},16)) + assert_true(M.include({6,8,10,16,29},16)) end) test('returns false when value was not found', function() - assert_false(_.include({6,8,10,16,29},1)) + assert_false(M.include({6,8,10,16,29},1)) end) test('can lookup for a object', function() - assert_true(_.include({6,{18,{2,6}},10,{18,{2,{3}}},29},{18,{2,{3}}})) + assert_true(M.include({6,{18,{2,6}},10,{18,{2,{3}}},29},{18,{2,{3}}})) end) test('given an iterator, return the first value passing a truth test', function() - assert_true(_.include({'a','B','c'}, function(array_value) + assert_true(M.include({'a','B','c'}, function(array_value) return (array_value:upper() == array_value) end)) end) @@ -292,19 +315,19 @@ context('Table functions specs', function() context('detect', function() test('looks for the first occurence of value, returns the key where it was found', function() - assert_equal(_.detect({6,8,10,16},8),2) + assert_equal(M.detect({6,8,10,16},8),2) end) test('returns nil when value was not found', function() - assert_nil(_.detect({nil,true,0,true,true},false)) + assert_nil(M.detect({nil,true,0,true,true},false)) end) test('can lookup for a object', function() - assert_equal(_.detect({6,{18,{2,6}},10,{18,{2,{3}}},29},{18,{2,6}}),2) + assert_equal(M.detect({6,{18,{2,6}},10,{18,{2,{3}}},29},{18,{2,6}}),2) end) test('given an iterator, return the key of the first value passing a truth test', function() - assert_equal(_.detect({'a','B','c'}, function(array_value) + assert_equal(M.detect({'a','B','c'}, function(array_value) return (array_value:upper() == array_value) end),2) end) @@ -320,9 +343,9 @@ context('Table functions specs', function() {a = 2, b = 4}, {a = 3, b = 4} } - assert_true(_.isEqual(_.where(set, {a = 2}), {set[2],set[3]})) - assert_true(_.isEqual(_.where(set, {b = 4}), {set[3],set[4]})) - assert_true(_.isEqual(_.where(set, {a = 2, b = 2}), {set[2]})) + assert_true(M.isEqual(M.where(set, {a = 2}), {set[2],set[3]})) + assert_true(M.isEqual(M.where(set, {b = 4}), {set[3],set[4]})) + assert_true(M.isEqual(M.where(set, {a = 2, b = 2}), {set[2]})) end) test('returns nil when value was not found', function() @@ -330,8 +353,8 @@ context('Table functions specs', function() {a = 1, b = 2}, {a = 2, b = 2}, } - assert_nil(_.where(set, {a = 3})) - assert_nil(_.where(set, {b = 1})) + assert_nil(M.where(set, {a = 3})) + assert_nil(M.where(set, {b = 1})) end) end) @@ -342,14 +365,14 @@ context('Table functions specs', function() local a = {a = 1, b = 2} local b = {a = 2, b = 3} local c = {a = 3, b = 4} - assert_equal(_.findWhere({a, b, c}, {a = 3, b = 4}), c) + assert_equal(M.findWhere({a, b, c}, {a = 3, b = 4}), c) end) test('returns nil when value was not found', function() local a = {a = 1, b = 2} local b = {a = 2, b = 3} local c = {a = 3, b = 4} - assert_nil(_.findWhere({a, b, c}, {a = 3, b = 0})) + assert_nil(M.findWhere({a, b, c}, {a = 3, b = 0})) end) end) @@ -357,13 +380,13 @@ context('Table functions specs', function() context('select', function() test('collects all values passing a truth test with an iterator', function() - assert_true(_.isEqual(_.select({1,2,3,4,5,6,7}, function(key,value) + assert_true(M.isEqual(M.select({7,6,5,4,3,2,1}, function(value) return (value%2==0) - end),{2,4,6})) + end),{6,4,2})) - assert_true(_.isEqual(_.select({1,2,3,4,5,6,7}, function(key,value) + assert_true(M.isEqual(M.select({7,6,5,4,3,2,1}, function(value) return (value%2~=0) - end),{1,3,5,7})) + end),{7,5,3,1})) end) end) @@ -371,13 +394,13 @@ context('Table functions specs', function() context('reject', function() test('collects all values failing a truth test with an iterator', function() - assert_true(_.isEqual(_.reject({1,2,3,4,5,6,7}, function(key,value) + assert_true(M.isEqual(M.reject({7,6,5,4,3,2,1}, function(value) return (value%2==0) - end),{1,3,5,7})) + end),{7,5,3,1})) - assert_true(_.isEqual(_.reject({1,2,3,4,5,6,7}, function(key,value) + assert_true(M.isEqual(M.reject({7,6,5,4,3,2,1}, function(value) return (value%2~=0) - end),{2,4,6})) + end),{6,4,2})) end) end) @@ -385,11 +408,11 @@ context('Table functions specs', function() context('all', function() test('returns whether all elements matches a truth test', function() - assert_true(_.all({2,4,6}, function(key,value) + assert_true(M.all({2,4,6}, function(value) return (value%2==0) end)) - assert_false(_.all({false,true,false}, function(key,value) + assert_false(M.all({false,true,false}, function(value) return value == false end)) end) @@ -399,20 +422,20 @@ context('Table functions specs', function() context('invoke', function() test('calls an iterator over each object, passing it as a first arg', function() - assert_true(_.isEqual(_.invoke({'a','bea','cdhza'},string.len), + assert_true(M.isEqual(M.invoke({'a','bea','cdhza'},string.len), {1,3,5})) - assert_true(_.isEqual(_.invoke({{2,3,2},{13,8,10},{0,-5}},_.sort), + assert_true(M.isEqual(M.invoke({{2,3,2},{13,8,10},{0,-5}},M.sort), {{2,2,3},{8,10,13},{-5,0}})) - assert_true(_.isEqual(_.invoke({{x = 1, y = 2},{x = 3, y=4}},'x'), {1,3})) + assert_true(M.isEqual(M.invoke({{x = 1, y = 2},{x = 3, y=4}},'x'), {1,3})) end) test('given a string, calls the matching object property the same way', function() local a = {}; function a:call() return self end local b, c, d = {}, {}, {} b.call, c.call, d.call = a.call, a.call, a.call - assert_true(_.isEqual(_.invoke({a,b,c,d},'call'), + assert_true(M.isEqual(M.invoke({a,b,c,d},'call'), {a,b,c,d})) end) @@ -426,9 +449,9 @@ context('Table functions specs', function() {name = 'John', age = 23},{name = 'Peter', age = 17}, {name = 'Steve', age = 15},{age = 33}} - assert_true(_.isEqual(_.pluck(peoples,'age'), + assert_true(M.isEqual(M.pluck(peoples,'age'), {23,17,15,33})) - assert_true(_.isEqual(_.pluck(peoples,'name'), + assert_true(M.isEqual(M.pluck(peoples,'name'), {'John','Peter','Steve'})) end) @@ -441,12 +464,12 @@ context('Table functions specs', function() local peoples = { {name = 'John', age = 23},{name = 'Peter', age = 17}, {name = 'Steve', age = 15},{age = 33}} - assert_equal(_.max(_.pluck(peoples,'age')),33) - assert_equal(_.max(peoples,function(people) return people.age end),33) + assert_equal(M.max(M.pluck(peoples,'age')),33) + assert_equal(M.max(peoples,function(people) return people.age end),33) end) test('directly compares items when given no iterator', function() - assert_equal(_.max({'a','b','c'}),'c') + assert_equal(M.max({'a','b','c'}),'c') end) end) @@ -457,35 +480,14 @@ context('Table functions specs', function() local peoples = { {name = 'John', age = 23},{name = 'Peter', age = 17}, {name = 'Steve', age = 15},{age = 33}} - assert_equal(_.min(_.pluck(peoples,'age')),15) - assert_equal(_.min(peoples,function(people) return people.age end),15) + assert_equal(M.min(M.pluck(peoples,'age')),15) + assert_equal(M.min(peoples,function(people) return people.age end),15) end) test('directly compares items when given no iterator', function() - assert_equal(_.min({'a','b','c'}),'a') + assert_equal(M.min({'a','b','c'}),'a') end) - end) - - context('shuffle', function() - - test('shuffles values and objects in a collection', function() - local values = {'a','b','c','d'} - assert_true(_.same(_.shuffle (values),values)) - end) - - test('can accept a seed value to init randomization', function() - local values = {'a','b','c','d'} - local seed = os.time() - assert_true(_.same(_.shuffle(values,seed),values)) - end) - - test('shuffled table has the same elements in a different order', function() - local values = {'a','b','c','d'} - assert_true(_.same(_.shuffle(values),values)) - assert_true(_.same(_.shuffle(values),values)) - end) - end) context('same', function() @@ -493,9 +495,9 @@ context('Table functions specs', function() test('returns whether all objects from both given tables exists in each other', function() local a = {'a','b','c','d'} local b = {'b','a','d','c'} - assert_true(_.same(a,b)) + assert_true(M.same(a,b)) b[#b+1] = 'e' - assert_false(_.same(a,b)) + assert_false(M.same(a,b)) end) end) @@ -503,13 +505,13 @@ context('Table functions specs', function() context('sort', function() test('sorts a collection with respect to a given comparison function', function() - assert_true(_.isEqual(_.sort({'b','a','d','c'}, function(a,b) + assert_true(M.isEqual(M.sort({'b','a','d','c'}, function(a,b) return a:byte() < b:byte() end),{'a','b','c','d'})) end) test('uses "<" operator when no comparison function is given', function() - assert_true(_.isEqual(_.sort({'b','a','d','c'}),{'a','b','c','d'})) + assert_true(M.isEqual(M.sort({'b','a','d','c'}),{'a','b','c','d'})) end) end) @@ -517,24 +519,24 @@ context('Table functions specs', function() context('sortBy', function() test('sort values on the result of a transform function', function() - assert_true(_.isEqual(_.sortBy({1,2,3,4,5}, math.sin), {5,4,3,1,2})) + assert_true(M.isEqual(M.sortBy({1,2,3,4,5}, math.sin), {5,4,3,1,2})) end) - test('the transform function defaults to _.identity', function() - assert_true(_.isEqual(_.sortBy({1,2,3,4,5}), {1,2,3,4,5})) + test('the transform function defaults to M.identity', function() + assert_true(M.isEqual(M.sortBy({1,2,3,4,5}), {1,2,3,4,5})) end) test('transform function can be a string name property', function() local unsorted = {{item = 1, value = 10},{item = 2, value = 5},{item = 3, value = 8}} local sorted = {{item = 2, value = 5},{item = 3, value = 8},{item = 1, value = 10}} - assert_true(_.isEqual(_.sortBy(unsorted, 'value'), sorted)) + assert_true(M.isEqual(M.sortBy(unsorted, 'value'), sorted)) end) test('can use a custom comparison function', function() local unsorted = {{item = 1, value = 10},{item = 2, value = 5},{item = 3, value = 8}} local sorted = {{item = 1, value = 10},{item = 3, value = 8},{item = 2, value = 5}} local function comp(a,b) return a > b end - assert_true(_.isEqual(_.sortBy(unsorted, 'value', comp), sorted)) + assert_true(M.isEqual(M.sortBy(unsorted, 'value', comp), sorted)) end) end) @@ -543,24 +545,20 @@ context('Table functions specs', function() test('splits a collection into subsets of items behaving the same', function() - assert_true(_.isEqual(_.groupBy({0,1,2,3,4,5,6},function(i,value) + assert_true(M.isEqual(M.groupBy({0,1,2,3,4,5,6},function(value) return value%2==0 and 'even' or 'odd' end),{even = {0,2,4,6},odd = {1,3,5}})) - assert_true(_.isEqual(_.groupBy({0,'a',true, false,nil,b,0.5},function(i,value) - return type(value) - end),{number = {0,0.5},string = {'a'},boolean = {true,false}})) + assert_true(M.isEqual(M.groupBy({0,'a',true, false,nil,b,0.5},type),{number = {0,0.5},string = {'a'},boolean = {true,false}})) - assert_true(_.isEqual(_.groupBy({'one','two','three','four','five'},function(i,value) - return value:len() - end),{[3] = {'one','two'},[4] = {'four','five'},[5] = {'three'}})) + assert_true(M.isEqual(M.groupBy({'one','two','three','four','five'},string.len),{[3] = {'one','two'},[4] = {'four','five'},[5] = {'three'}})) end) test('can takes extra-args', function() - assert_true(_.isEqual(_.groupBy({3,9,10,12,15}, function(k,v,x) return v%x == 0 end,2), {[false] = {3,9,15}, [true] = {10,12}})) - assert_true(_.isEqual(_.groupBy({3,9,10,12,15}, function(k,v,x) return v%x == 0 end,3), {[false] = {10}, [true] = {3,9,12,15}})) + assert_true(M.isEqual(M.groupBy({3,9,10,12,15}, function(v,k,x) return v%x == 0 end,2), {[false] = {3,9,15}, [true] = {10,12}})) + assert_true(M.isEqual(M.groupBy({3,9,10,12,15}, function(v,k,x) return v%x == 0 end,3), {[false] = {10}, [true] = {3,9,12,15}})) end) @@ -570,17 +568,13 @@ context('Table functions specs', function() test('splits a collection in subsets and counts items inside', function() - assert_true(_.isEqual(_.countBy({0,1,2,3,4,5,6},function(i,value) + assert_true(M.isEqual(M.countBy({0,1,2,3,4,5,6},function(value) return value%2==0 and 'even' or 'odd' end),{even = 4,odd = 3})) - assert_true(_.isEqual(_.countBy({0,'a',true, false,nil,b,0.5},function(i,value) - return type(value) - end),{number = 2,string = 1,boolean = 2})) + assert_true(M.isEqual(M.countBy({0,'a',true, false,nil,b,0.5},type),{number = 2,string = 1,boolean = 2})) - assert_true(_.isEqual(_.countBy({'one','two','three','four','five'},function(i,value) - return value:len() - end),{[3] = 2,[4] = 2,[5] = 1})) + assert_true(M.isEqual(M.countBy({'one','two','three','four','five'},string.len),{[3] = 2,[4] = 2,[5] = 1})) end) @@ -589,34 +583,34 @@ context('Table functions specs', function() context('size', function() test('counts the very number of objects in a collection', function() - assert_equal(_.size {1,2,3},3) + assert_equal(M.size {1,2,3},3) end) test('counts nested tables elements as an unique value', function() - assert_equal(_.size {1,2,3,{4,5}},4) + assert_equal(M.size {1,2,3,{4,5}},4) end) test('leaves nil values', function() - assert_equal(_.size {1,2,3,nil,8},4) + assert_equal(M.size {1,2,3,nil,8},4) end) test('counts objects', function() - assert_equal(_.size {one = 1,2,b = 3, [{}] = 'nil', 'c', [function() end] = 'foo'},6) + assert_equal(M.size {one = 1,2,b = 3, [{}] = 'nil', 'c', [function() end] = 'foo'},6) end) test('returns the size of the first arg when it is a table', function() - assert_equal(_.size ({1,2},3,4,5),2) + assert_equal(M.size ({1,2},3,4,5),2) end) test('counts the number of non-nil args when the first one is not a table', function() - assert_equal(_.size (1,3,4,5),4) - assert_equal(_.size (nil,1,3,4,5),4) - assert_equal(_.size (nil,1,3,4,nil,5),4) + assert_equal(M.size (1,3,4,5),4) + assert_equal(M.size (nil,1,3,4,5),4) + assert_equal(M.size (nil,1,3,4,nil,5),4) end) test('handles nil', function() - assert_equal(_.size(),0) - assert_equal(_.size(nil),0) + assert_equal(M.size(),0) + assert_equal(M.size(nil),0) end) @@ -625,20 +619,20 @@ context('Table functions specs', function() context('containsKeys', function() test('returns whether a table has all the keys from a given list', function() - assert_true(_.containsKeys({1,2,3},{1,2,3})) - assert_true(_.containsKeys({x = 1, y = 2},{x = 1,y =2})) + assert_true(M.containsKeys({1,2,3},{1,2,3})) + assert_true(M.containsKeys({x = 1, y = 2},{x = 1,y =2})) end) test('does not compare values', function() - assert_true(_.containsKeys({1,2,3},{4,5,6})) - assert_true(_.containsKeys({x = 1, y = 2},{x = 4,y = -1})) + assert_true(M.containsKeys({1,2,3},{4,5,6})) + assert_true(M.containsKeys({x = 1, y = 2},{x = 4,y = -1})) end) test('is not commutative', function() - assert_true(_.containsKeys({1,2,3,4},{4,5,6})) - assert_true(_.containsKeys({x = 1, y = 2,z = 5},{x = 4,y = -1})) - assert_false(_.containsKeys({1,2,3},{4,5,6,7})) - assert_false(_.containsKeys({x = 1, y = 2},{x = 4,y = -1,z = 0})) + assert_true(M.containsKeys({1,2,3,4},{4,5,6})) + assert_true(M.containsKeys({x = 1, y = 2,z = 5},{x = 4,y = -1})) + assert_false(M.containsKeys({1,2,3},{4,5,6,7})) + assert_false(M.containsKeys({x = 1, y = 2},{x = 4,y = -1,z = 0})) end) end) @@ -646,20 +640,20 @@ context('Table functions specs', function() context('sameKeys', function() test('returns whether both tables features the same keys', function() - assert_true(_.sameKeys({1,2,3},{1,2,3})) - assert_true(_.sameKeys({x = 1, y = 2},{x = 1,y =2})) + assert_true(M.sameKeys({1,2,3},{1,2,3})) + assert_true(M.sameKeys({x = 1, y = 2},{x = 1,y =2})) end) test('does not compare values', function() - assert_true(_.sameKeys({1,2,3},{4,5,6})) - assert_true(_.sameKeys({x = 1, y = 2},{x = 4,y = -1})) + assert_true(M.sameKeys({1,2,3},{4,5,6})) + assert_true(M.sameKeys({x = 1, y = 2},{x = 4,y = -1})) end) test('is commutative', function() - assert_false(_.sameKeys({1,2,3,4},{4,5,6})) - assert_false(_.sameKeys({x = 1, y = 2,z = 5},{x = 4,y = -1})) - assert_false(_.sameKeys({1,2,3},{4,5,6,7})) - assert_false(_.sameKeys({x = 1, y = 2},{x = 4,y = -1,z = 0})) + assert_false(M.sameKeys({1,2,3,4},{4,5,6})) + assert_false(M.sameKeys({x = 1, y = 2,z = 5},{x = 4,y = -1})) + assert_false(M.sameKeys({1,2,3},{4,5,6,7})) + assert_false(M.sameKeys({x = 1, y = 2},{x = 4,y = -1,z = 0})) end) end) |