UNPKG

@onlabsorg/swan-js

Version:

A simple yet powerful expression language written in JavaScript

1,366 lines (1,049 loc) 75.9 kB
const expect = require("./expect"); const { Term, Tuple, Item, Bool, Numb, Func, Undefined, Mapping, Sequence, Text, List, Namespace, wrap, unwrap } = require('../lib/types'); describe("types", () => { describe("Bool", () => { describe(".items()", () => { it("should yield the item itself", () => { const item = new Bool(true); expect(item.items()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.items())).to.deep.equal([item]); }); }); describe(".values()", () => { it("should yield the item value", () => { const item = new Bool(true); expect(item.values()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.values())).to.deep.equal([true]); }); }); describe("[Symbol.iterator]()", () => { it("should yield the item value", () => { const item = new Bool(true); expect(Array.from(item)).to.deep.equal([true]); }); }); describe(".iterPairs(other)", () => { it("should yield corresponding pairs of the two terms", () => { const item1 = new Bool(true); const item2 = new Bool(false); expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a("function"); const pairs = Array.from(item1.iterPairs(item2)); expect(pairs.length).to.equal(1); expect(pairs[0][0]).to.be.Bool(true); expect(pairs[0][1]).to.be.Bool(false); }); }); describe(".imapSync(fn)", () => { it("should synchronously apply fn to the item and return the wrapped output", () => { const item = new Bool(true); const fn = item => [item.unwrap()]; expect(item.imapSync(fn)).to.be.List([true]); }); }); describe(".vmapSync(fn)", () => { it("should synchronously apply fn to the item value and return the wrapped output", () => { const item = new Bool(true); const fn = value => [value]; expect(item.vmapSync(fn)).to.be.List([true]); }); }); describe(".imapAsync(fn)", () => { it("should asynchronously apply fn to the item and return the wrapped output", async () => { const item = new Bool(true); const fn = async item => [item.unwrap()]; expect(await item.imapAsync(fn)).to.be.List([true]); }); }); describe(".vmapAsync(fn)", () => { it("should asynchronously apply fn to the item value and return the wrapped output", async () => { const item = new Bool(true); const fn = async value => [value]; expect(await item.vmapAsync(fn)).to.be.List([true]); }); }); describe(".toBoolean()", () => { it("should return the term value", () => { expect((new Bool(true)).toBoolean()).to.be.true; expect((new Bool(false)).toBoolean()).to.be.false; }); }); describe(".toString()", () => { it("should return 'TRUE' if the value is true", () => { expect((new Bool(true)).toString()).to.equal("TRUE") }); it("should return 'FALSE' if the value is true", () => { expect((new Bool(false)).toString()).to.equal("FALSE") }); }); describe(".typeName", () => { it("should return the item class name", () => { expect(new Bool(true).typeName).to.equal("Bool"); }); }); describe(".isNothing()", () => { it("should return false", () => { expect(new Bool(true).isNothing()).to.be.false; }); }); describe(".normalize()", () => { it("should return the item as it is", () => { const item = new Bool(true); expect(item.normalize()).to.equal(item); }); }); describe(".unwrap()", () => { it("should return the item value", () => { expect(new Bool(true).unwrap() ).to.equal(true); expect(new Bool(false).unwrap()).to.equal(false); }); }); describe(".sum(other)", () => { it("should return the logical OR", () => { const TRUE = new Bool(true); const FALSE = new Bool(false); expect(TRUE.sum(TRUE) ).to.be.Bool(true); expect(TRUE.sum(FALSE) ).to.be.Bool(true); expect(FALSE.sum(TRUE) ).to.be.Bool(true); expect(FALSE.sum(FALSE)).to.be.Bool(false); }); }); describe(".negate()", () => { it("should not be defined", () => { const item = new Bool(true); expect(item.negate).to.be.undefined; }); }); describe(".isNull()", () => { it("should return true if the item is FALSE", () => { expect(new Bool(true).isNull()).to.be.false; expect(new Bool(false).isNull()).to.be.true; }); }); describe("Bool.null", () => { it("should return FALSE", () => { expect(Bool.null).to.be.Bool(false); }); }); describe(".mul(other)", () => { it("should return the logical AND", () => { const TRUE = new Bool(true); const FALSE = new Bool(false); expect(TRUE.mul(TRUE) ).to.be.Bool(true); expect(TRUE.mul(FALSE) ).to.be.Bool(false); expect(FALSE.mul(TRUE) ).to.be.Bool(false); expect(FALSE.mul(FALSE)).to.be.Bool(false); }); }); describe(".invert()", () => { it("should not be defined", () => { const item = new Bool(true); expect(item.invert).to.be.undefined; }); }); describe(".isUnit()", () => { it("should return true if the item is TRUE", () => { expect(new Bool(true).isUnit()).to.be.true; expect(new Bool(false).isUnit()).to.be.false; }); }); describe("Bool.unit", () => { it("should return TRUE", () => { expect(Bool.unit).to.be.Bool(true); }); }); describe(".pow(other)", () => { it("should not be defined", () => { const item = new Bool(true); expect(item.pow).to.be.undefined; }); }); describe(".compare(other)", () => { it("should return 0 if the items are both TRUE or both FALSE", () => { const TRUE = new Bool(true); const FALSE = new Bool(false); expect(TRUE.compare(TRUE)).to.equal(0); expect(FALSE.compare(FALSE)).to.equal(0); }); it("should consider FALSE less than TRUE", () => { const TRUE = new Bool(true); const FALSE = new Bool(false); expect(TRUE.compare(FALSE)).to.equal(+1); expect(FALSE.compare(TRUE)).to.equal(-1); }); }); }); describe("Numb", () => { describe(".items()", () => { it("should yield the item itself", () => { const item = new Numb(10); expect(item.items()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.items())).to.deep.equal([item]); }); }); describe(".values()", () => { it("should yield the item value", () => { const item = new Numb(10); expect(item.values()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.values())).to.deep.equal([10]); }); }); describe("[Symbol.iterator]()", () => { it("should yield the item value", () => { const item = new Numb(10); expect(Array.from(item)).to.deep.equal([10]); }); }); describe(".iterPairs(other)", () => { it("should yield corresponding pairs of the two terms", () => { const item1 = new Numb(10); const item2 = new Numb(20); expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a("function"); const pairs = Array.from(item1.iterPairs(item2)); expect(pairs.length).to.equal(1); expect(pairs[0][0]).to.be.Numb(10); expect(pairs[0][1]).to.be.Numb(20); }); }); describe(".imapSync(fn)", () => { it("should synchronously apply fn to the item and return the wrapped output", () => { const item = new Numb(10); const fn = item => [item.unwrap()]; expect(item.imapSync(fn)).to.be.List([10]); }); }); describe(".vmapSync(fn)", () => { it("should synchronously apply fn to the item value and return the wrapped output", () => { const item = new Numb(10); const fn = value => [value]; expect(item.vmapSync(fn)).to.be.List([10]); }); }); describe(".imapAsync(fn)", () => { it("should asynchronously apply fn to the item and return the wrapped output", async () => { const item = new Numb(10); const fn = async item => [item.unwrap()]; expect(await item.imapAsync(fn)).to.be.List([10]); }); }); describe(".vmapAsync(fn)", () => { it("should asynchronously apply fn to the item value and return the wrapped output", async () => { const item = new Numb(10); const fn = async value => [value]; expect(await item.vmapAsync(fn)).to.be.List([10]); }); }); describe(".toBoolean()", () => { it("should return true if the number is not null", () => { expect((new Numb(9)).toBoolean()).to.be.true; expect((new Numb(0)).toBoolean()).to.be.false; }); }); describe(".toString()", () => { it("should return the stringified value", () => { expect((new Numb(-1.23)).toString()).to.equal("-1.23"); }); }); describe(".typeName", () => { it("should return the item class name", () => { expect(new Numb(10).typeName).to.equal("Numb"); }); }); describe(".isNothing()", () => { it("should return false", () => { expect(new Numb(10).isNothing()).to.be.false; expect(new Numb( 0).isNothing()).to.be.false; }); }); describe(".normalize()", () => { it("should return the item as it is", () => { const item = new Numb(10); expect(item.normalize()).to.equal(item); }); }); describe(".unwrap()", () => { it("should return the item value", () => { expect(new Numb(10).unwrap()).to.equal(10); expect(new Numb( 0).unwrap()).to.equal( 0); }); }); describe(".sum(other)", () => { it("should return the sum of the two numbers", () => { const item1 = new Numb(10); const item2 = new Numb(20); expect(item1.sum(item2)).to.be.Numb(30); }); }); describe(".negate()", () => { it("should return the negation of the item", () => { const item = new Numb(10); expect(item.negate()).to.be.Numb(-10); }); }); describe(".isNull()", () => { it("should return true if the item is 0", () => { expect(new Numb(10).isNull()).to.be.false; expect(new Numb( 0).isNull()).to.be.true; }); }); describe("Numb.null", () => { it("should return 0", () => { expect(Numb.null).to.be.Numb(0); }); }); describe(".mul(other)", () => { it("should return the product of the two numbers", () => { const item1 = new Numb(10); const item2 = new Numb(20); expect(item1.mul(item2)).to.be.Numb(200); }); }); describe(".invert()", () => { it("should return the reciprocal of the Numb item", () => { const item = new Numb(10); expect(item.invert()).to.be.Numb(0.1); }); }); describe(".isUnit()", () => { it("should return true if the item is 1", () => { expect(new Numb(1).isUnit()).to.be.true; expect(new Numb(0).isUnit()).to.be.false; }); }); describe("Numb.unit", () => { it("should return 1", () => { expect(Numb.unit).to.be.Numb(1); }); }); describe(".pow(other)", () => { it("should return the exponentiation of the two numbers", () => { const item1 = new Numb(10); const item2 = new Numb(3); expect(item1.pow(item2)).to.be.Numb(1000); }); }); describe(".compare(other)", () => { it("should compare the two numbers according to the real numbers order rules", () => { const item1 = new Numb(10); const item2 = new Numb(20); expect(item1.compare(item1)).to.equal(0); expect(item2.compare(item2)).to.equal(0); expect(item1.compare(item2)).to.equal(-1); expect(item2.compare(item1)).to.equal(+1); }); }); }); describe("Text", () => { describe(".items()", () => { it("should yield the item itself", () => { const item = new Text("abc"); expect(item.items()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.items())).to.deep.equal([item]); }); }); describe(".values()", () => { it("should yield the item value", () => { const item = new Text("abc"); expect(item.values()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.values())).to.deep.equal(["abc"]); }); }); describe("[Symbol.iterator]()", () => { it("should yield the item value", () => { const item = new Text("abc"); expect(Array.from(item)).to.deep.equal(["abc"]); }); }); describe(".iterPairs(other)", () => { it("should yield corresponding pairs of the two terms", () => { const item1 = new Text("abc"); const item2 = new Text("def"); expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a("function"); const pairs = Array.from(item1.iterPairs(item2)); expect(pairs.length).to.equal(1); expect(pairs[0][0]).to.be.Text("abc"); expect(pairs[0][1]).to.be.Text("def"); }); }); describe(".imapSync(fn)", () => { it("should synchronously apply fn to the item and return the wrapped output", () => { const item = new Text("abc"); const fn = item => [item.unwrap()]; expect(item.imapSync(fn)).to.be.List(["abc"]); }); }); describe(".vmapSync(fn)", () => { it("should synchronously apply fn to the item value and return the wrapped output", () => { const item = new Text("abc"); const fn = value => [value]; expect(item.vmapSync(fn)).to.be.List(["abc"]); }); }); describe(".imapAsync(fn)", () => { it("should asynchronously apply fn to the item and return the wrapped output", async () => { const item = new Text("abc"); const fn = async item => [item.unwrap()]; expect(await item.imapAsync(fn)).to.be.List(["abc"]); }); }); describe(".vmapAsync(fn)", () => { it("should asynchronously apply fn to the item value and return the wrapped output", async () => { const item = new Text("abc"); const fn = async value => [value]; expect(await item.vmapAsync(fn)).to.be.List(["abc"]); }); }); describe(".toBoolean()", () => { it("should return true if the string value is not empty", () => { expect((new Text("abc")).toBoolean()).to.be.true; expect((new Text("")).toBoolean()).to.be.false; }); }); describe(".toString()", () => { it("should return the text value as it is", () => { expect((new Text("abc")).toString()).to.equal("abc"); }); }); describe(".typeName", () => { it("should return the item class name", () => { expect(new Text("abc").typeName).to.equal("Text"); }); }); describe(".isNothing()", () => { it("should return false", () => { expect(new Text("abc").isNothing()).to.be.false; expect(new Text("" ).isNothing()).to.be.false; }); }); describe(".normalize()", () => { it("should return the item as it is", () => { const item = new Text("abc"); expect(item.normalize()).to.equal(item); }); }); describe(".unwrap()", () => { it("should return the item value", () => { expect(new Text("abc").unwrap()).to.equal("abc"); expect(new Text("" ).unwrap()).to.equal(""); }); }); describe(".sum(other)", () => { it("should concatenate the two strings", () => { const item1 = new Text("abc"); const item2 = new Text("def"); expect(item1.sum(item2)).to.be.Text("abcdef"); }); }); describe(".negate()", () => { it("should not be defined", () => { const item = new Text("abc"); expect(item.negate).to.be.undefined; }); }); describe(".isNull()", () => { it("should return true if the string is empty", () => { expect(new Text("abc").isNull()).to.be.false; expect(new Text("" ).isNull()).to.be.true; }); }); describe("Text.null", () => { it("should return an empty Text item", () => { expect(Text.null).to.be.Text(""); }); }); describe(".mul(other)", () => { it("should not be defined", () => { const item = new Text("abc"); expect(item.mul).to.be.undefined; }); }); describe(".invert()", () => { it("should not be defined", () => { const item = new Text("abc"); expect(item.invert).to.be.undefined; }); }); describe(".isUnit()", () => { it("should not be defined", () => { const item = new Text("abc"); expect(item.isUnit).to.be.undefined; }); }); describe("Text.unit", () => { it("should not be defined", () => { expect(Text.unit).to.be.undefined; }); }); describe(".pow(other)", () => { it("should not be defined", () => { const item = new Text("abc"); expect(item.pow).to.be.undefined; }); }); describe(".compare(other)", () => { it("should compare the two strings alphabetically", () => { const item1 = new Text("abc"); const item2 = new Text("def"); expect(item1.compare(item1)).to.equal(0); expect(item2.compare(item2)).to.equal(0); expect(item1.compare(item2)).to.equal(-1); expect(item2.compare(item1)).to.equal(+1); expect(new Text("aaa").compare(new Text("aa"))).to.equal(+1); }); }); describe(".domain", () => { it("should return the array of integers between 0 and the string length minus one", () => { expect(new Text("abc").domain).to.deep.equal([0,1,2]); expect(new Text("" ).domain).to.deep.equal([]); }); }); describe(".vget(i)", () => { it("should return i-th character of the string", () => { expect(new Text("abc").vget(1)).to.equal('b') }); it("should return undefined if i is not in the Text domain", () => { const item = new Text("abc"); expect(item.vget(-1)).to.be.undefined; expect(item.vget(10)).to.be.undefined; expect(item.vget('xx')).to.be.undefined; }); }); describe(".size", () => { it("should contain the number of characters of the string", () => { expect(new Text("abc").size).to.equal(3); expect(new Text("").size).to.equal(0); }); }); describe(".image", () => { it("should return the tuple of characters of the string", () => { const item = new Text("abc"); expect(item.image).to.deep.equal(['a','b','c']); }); }); describe(".apply(...X)", () => { it("should return the tuple of Text characters mapped to the arguments", () => { const item = new Text("abcdef"); expect(item.apply(1,3,5)).to.be.Tuple(['b','d','f']); }); it("should normalize the returned tuple", () => { const item = new Text("abcdef"); expect(item.apply(1)).to.be.Text('b'); }); it("should return Undefined Mapping if the index is not in the Text item domain", () => { const item = new Text("abcdef"); expect(item.apply(-1)).to.be.Undefined('Mapping', arg0 => { expect(arg0).to.equal(-1); }); const tuple = item.apply(1, -1, 3); expect(tuple).to.be.instanceof(Tuple); expect(Array.from(tuple)[0]).to.equal('b'); expect(Array.from(tuple)[1]).to.be.Undefined('Mapping', arg0 => { expect(arg0).to.equal(-1); }); expect(Array.from(tuple)[2]).to.equal('d'); }); }) }); describe("List", () => { describe(".items()", () => { it("should yield the item itself", () => { const item = new List([10,20,30]); expect(item.items()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.items())).to.deep.equal([item]); }); }); describe(".values()", () => { it("should yield the item value", () => { const item = new List([10,20,30]); expect(item.values()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.values())).to.deep.equal([[10,20,30]]); }); }); describe("[Symbol.iterator]()", () => { it("should yield the item value", () => { const item = new List([10,20,30]); expect(Array.from(item)).to.deep.equal([[10,20,30]]); }); }); describe(".iterPairs(other)", () => { it("should yield corresponding pairs of the two terms", () => { const item1 = new List([10,20,30]); const item2 = new List([40,50,60]); expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a("function"); const pairs = Array.from(item1.iterPairs(item2)); expect(pairs.length).to.equal(1); expect(pairs[0][0]).to.be.List([10,20,30]); expect(pairs[0][1]).to.be.List([40,50,60]); }); }); describe(".imapSync(fn)", () => { it("should synchronously apply fn to the item and return the wrapped output", () => { const item = new List([10,20,30]); const fn = item => [item.unwrap()]; expect(item.imapSync(fn)).to.be.List([[10,20,30]]); }); }); describe(".vmapSync(fn)", () => { it("should synchronously apply fn to the item value and return the wrapped output", () => { const item = new List([10,20,30]); const fn = value => [value]; expect(item.vmapSync(fn)).to.be.List([[10,20,30]]); }); }); describe(".imapAsync(fn)", () => { it("should asynchronously apply fn to the item and return the wrapped output", async () => { const item = new List([10,20,30]); const fn = async item => [item.unwrap()]; expect(await item.imapAsync(fn)).to.be.List([[10,20,30]]); }); }); describe(".vmapAsync(fn)", () => { it("should asynchronously apply fn to the item value and return the wrapped output", async () => { const item = new List([10,20,30]); const fn = async value => [value]; expect(await item.vmapAsync(fn)).to.be.List([[10,20,30]]); }); }); describe(".toBoolean()", () => { it("should return true if the array value is not empty", () => { expect((new List([10,20,30])).toBoolean()).to.be.true; expect((new List([ ])).toBoolean()).to.be.false; }); }); describe(".toString()", () => { it("should return '[[List of n items]]'", () => { expect(new List([10,20,30]).toString()).to.equal("[[List of 3 items]]"); expect(new List([10 ]).toString()).to.equal("[[List of 1 item]]"); expect(new List([ ]).toString()).to.equal("[[List of 0 items]]"); }); }); describe(".typeName", () => { it("should return the item class name", () => { expect(new List([10,20,30]).typeName).to.equal("List"); }); }); describe(".isNothing()", () => { it("should return false", () => { expect(new List([10,20,30]).isNothing()).to.be.false; expect(new List([ ]).isNothing()).to.be.false; }); }); describe(".normalize()", () => { it("should return the item as it is", () => { const item = new List([10,20,30]); expect(item.normalize()).to.equal(item); }); }); describe(".unwrap()", () => { it("should return the item value", () => { expect(new List([10,20,30]).unwrap()).to.deep.equal([10,20,30]); expect(new List([ ]).unwrap()).to.deep.equal([]); }); }); describe(".sum(other)", () => { it("should concatenate the two lists", () => { const item1 = new List([10,20,30]); const item2 = new List([40,50,60]); expect(item1.sum(item2)).to.be.List([10,20,30,40,50,60]); }); }); describe(".negate()", () => { it("should not be defined", () => { const item = new List([10,20,30]); expect(item.negate).to.be.undefined; }); }); describe(".isNull()", () => { it("should return true if the list is empty", () => { expect(new List([10,20,30]).isNull()).to.be.false; expect(new List([ ]).isNull()).to.be.true; }); }); describe("List.null", () => { it("should return an empty Text item", () => { expect(List.null).to.be.List([]); }); }); describe(".mul(other)", () => { it("should not be defined", () => { const item = new List([10,20,30]); expect(item.mul).to.be.undefined; }); }); describe(".invert()", () => { it("should not be defined", () => { const item = new List([10,20,30]); expect(item.invert).to.be.undefined; }); }); describe(".isUnit()", () => { it("should not be defined", () => { const item = new List([10,20,30]); expect(item.isUnit).to.be.undefined; }); }); describe("List.unit", () => { it("should not be defined", () => { expect(List.unit).to.be.undefined; }); }); describe(".pow(other)", () => { it("should not be defined", () => { const item = new List([10,20,30]); expect(item.pow).to.be.undefined; }); }); describe(".compare(other)", () => { it("should compare the two lists lexicographically", () => { const item1 = new List([10,20,30]); const item2 = new List([40,50,60]); expect(item1.compare(item1)).to.equal(0); expect(item2.compare(item2)).to.equal(0); expect(item1.compare(item2)).to.equal(-1); expect(item2.compare(item1)).to.equal(+1); expect(new List([10,10,10]).compare(new List([10,10]))).to.equal(+1); }); }); describe(".domain", () => { it("should return the array of integers between 0 and the list length minus one", () => { expect(new List([10,20,30]).domain).to.deep.equal([0,1,2]); expect(new List([ ]).domain).to.deep.equal([]); }); }); describe(".vget(i)", () => { it("should return i-th value of the list", () => { expect(new List([10,20,30]).vget(1)).to.equal(20) }); it("should return undefined if i is not in the List domain", () => { const item = new List([10,20,30]); expect(item.vget(-1)).to.be.undefined; expect(item.vget(10)).to.be.undefined; expect(item.vget('xx')).to.be.undefined; }); }); describe(".size", () => { it("should contain the number of items of the list", () => { expect(new List([10,20,30]).size).to.equal(3); expect(new List([ ]).size).to.equal(0); }); }); describe(".image", () => { it("should return the tuple of characters of the string", () => { const item = new List([10,20,30]); expect(item.image).to.be.deep.equal([10,20,30]); }); }); describe(".apply(...X)", () => { it("should return the tuple of List items mapped to the arguments", () => { const item = new List([10,20,30,40,50,60]); expect(item.apply(1,3,5)).to.be.Tuple([20,40,60]); }); it("should normalize the returned tuple", () => { const item = new List([10,20,30,40,50,60]); expect(item.apply(1)).to.be.Numb(20); }); it("should return Undefined Mapping if the index is not in the List item domain", () => { const item = new List([10,20,30,40,50,60]); expect(item.apply(-1)).to.be.Undefined('Mapping', arg0 => { expect(arg0).to.equal(-1); }); const tuple = item.apply(1, -1, 3); expect(tuple).to.be.instanceof(Tuple); expect(Array.from(tuple)[0]).to.equal(20); expect(Array.from(tuple)[1]).to.be.Undefined('Mapping', arg0 => { expect(arg0).to.equal(-1); }); expect(Array.from(tuple)[2]).to.equal(40); }); }) }); describe("Namespace", () => { describe(".items()", () => { it("should yield the item itself", () => { const item = new Namespace({k1:1, k2:2, k3:3}); expect(item.items()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.items())).to.deep.equal([item]); }); }); describe(".values()", () => { it("should yield the item value", () => { const item = new Namespace({k1:1, k2:2, k3:3}); expect(item.values()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.values())).to.deep.equal([{k1:1, k2:2, k3:3}]); }); }); describe("[Symbol.iterator]()", () => { it("should yield the item value", () => { const item = new Namespace({k1:1, k2:2, k3:3}); expect(Array.from(item)).to.deep.equal([{k1:1, k2:2, k3:3}]); }); }); describe(".iterPairs(other)", () => { it("should yield corresponding pairs of the two terms", () => { const item1 = new Namespace({k1:1, k2:2, k3:3}); const item2 = new Namespace({k4:4, k5:5, k6:6}); expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a("function"); const pairs = Array.from(item1.iterPairs(item2)); expect(pairs.length).to.equal(1); expect(pairs[0][0]).to.be.Namespace({k1:1, k2:2, k3:3}); expect(pairs[0][1]).to.be.Namespace({k4:4, k5:5, k6:6}); }); }); describe(".imapSync(fn)", () => { it("should synchronously apply fn to the item and return the wrapped output", () => { const item = new Namespace({k1:1, k2:2, k3:3}); const fn = item => [item.unwrap()]; expect(item.imapSync(fn)).to.be.List([{k1:1, k2:2, k3:3}]); }); }); describe(".vmapSync(fn)", () => { it("should synchronously apply fn to the item value and return the wrapped output", () => { const item = new Namespace({k1:1, k2:2, k3:3}); const fn = value => [value]; expect(item.vmapSync(fn)).to.be.List([{k1:1, k2:2, k3:3}]); }); }); describe(".imapAsync(fn)", () => { it("should asynchronously apply fn to the item and return the wrapped output", async () => { const item = new Namespace({k1:1, k2:2, k3:3}); const fn = async item => [item.unwrap()]; expect(await item.imapAsync(fn)).to.be.List([{k1:1, k2:2, k3:3}]); }); }); describe(".vmapAsync(fn)", () => { it("should asynchronously apply fn to the item value and return the wrapped output", async () => { const item = new Namespace({k1:1, k2:2, k3:3}); const fn = async value => [value]; expect(await item.vmapAsync(fn)).to.be.List([{k1:1, k2:2, k3:3}]); }); }); describe(".toBoolean()", () => { it("should return true if the namespace value is not empty", () => { expect((new Namespace({a:1})).toBoolean()).to.be.true; expect((new Namespace({})).toBoolean()).to.be.false; }); it("should consider empty a namespace containing only non-valid identifiers", () => { expect((new Namespace({$key:1})).toBoolean()).to.be.false; }); }); describe(".toString()", () => { it("should retun '[[Namespace of n items]]'", () => { expect((new Namespace({key1:1, key2:2, key3:3, $key4:4})).toString()).to.equal("[[Namespace of 3 items]]"); expect((new Namespace({key1:1 })).toString()).to.equal("[[Namespace of 1 item]]"); expect((new Namespace({ })).toString()).to.equal("[[Namespace of 0 items]]"); }); }); describe(".typeName", () => { it("should return the item class name", () => { expect(new Namespace({k1:1, k2:2, k3:3}).typeName).to.equal("Namespace"); }); }); describe(".isNothing()", () => { it("should return false", () => { expect(new Namespace({k1:1, k2:2, k3:3}).isNothing()).to.be.false; expect(new Namespace({ }).isNothing()).to.be.false; }); }); describe(".normalize()", () => { it("should return the item as it is", () => { const item = new Namespace({k1:1, k2:2, k3:3}); expect(item.normalize()).to.equal(item); }); }); describe(".unwrap()", () => { it("should return the item value", () => { expect(new Namespace({k1:1, k2:2, k3:3}).unwrap()).to.deep.equal({k1:1, k2:2, k3:3}); expect(new Namespace({ }).unwrap()).to.deep.equal({}); }); }); describe(".sum(other)", () => { it("should concatenate the two lists", () => { const item1 = new Namespace({k1:1, k2:2, k3:3}); const item2 = new Namespace({k3:4, k4:5, k5:6}); expect(item1.sum(item2)).to.be.Namespace({k1:1, k2:2, k3:4, k4:5, k5:6}); }); }); describe(".negate()", () => { it("should not be defined", () => { const item = new Namespace({k1:1, k2:2, k3:3}); expect(item.negate).to.be.undefined; }); }); describe(".isNull()", () => { it("should return true if the list is empty", () => { expect(new Namespace({k1:1, k2:2, k3:3}).isNull()).to.be.false; expect(new Namespace({ }).isNull()).to.be.true; }); }); describe("Namespace.null", () => { it("should return an empty Text item", () => { expect(Namespace.null).to.be.Namespace({}); }); }); describe(".mul(other)", () => { it("should not be defined", () => { const item = new Namespace({k1:1, k2:2, k3:3}); expect(item.mul).to.be.undefined; }); }); describe(".invert()", () => { it("should not be defined", () => { const item = new Namespace({k1:1, k2:2, k3:3}); expect(item.invert).to.be.undefined; }); }); describe(".isUnit()", () => { it("should not be defined", () => { const item = new Namespace({k1:1, k2:2, k3:3}); expect(item.isUnit).to.be.undefined; }); }); describe("Namespace.unit", () => { it("should not be defined", () => { expect(Namespace.unit).to.be.undefined; }); }); describe(".pow(other)", () => { it("should not be defined", () => { const item = new Namespace({k1:1, k2:2, k3:3}); expect(item.pow).to.be.undefined; }); }); describe(".compare(other)", () => { it("should return equal if two namespace have the same identifiers and equal values", () => { const item1 = new Namespace({k1:1, k2:2, k3:3}); const item2 = new Namespace({k4:4, k5:5, k6:6}); expect(item1.compare(item1)).to.equal(0); expect(item2.compare(item2)).to.equal(0); expect(item1.compare(item2)).to.be.NaN; expect(item2.compare(item1)).to.be.NaN; expect(new Namespace({k1:1, k2:2, $k3:3}).compare(new Namespace({k1:1, k2:2}))).to.equal(0); }); }); describe(".domain", () => { it("should return the array of the namespace identifiers", () => { expect(new Namespace({k1:1, k2:2, k3:3}).domain).to.deep.equal(['k1','k2','k3']); expect(new Namespace({ }).domain).to.deep.equal([]); }); }); describe(".vget(key)", () => { it("should return the value mapped to the given identifier", () => { expect(new Namespace({k1:1, k2:2, k3:3}).vget('k2')).to.equal(2) }); it("should return undefined if key is not in the Namespace domain", () => { const item = new Namespace({k1:1, k2:2, k3:3, $k4:4}); expect(item.vget(10)).to.be.undefined; expect(item.vget('xx')).to.be.undefined; expect(item.vget('$k4')).to.be.undefined; }); }); describe(".size", () => { it("should contain the number of names in the namespace", () => { expect(new Namespace({x:10,y:20,z:30}).size).to.equal(3); expect(new Namespace({}).size).to.equal(0); }); it("should ignore non-valid identifiers", () => { expect(new Namespace({x:10,y:20,$z:30}).size).to.equal(2); }); }); describe(".image", () => { it("should return the array of values of the namespace", () => { const item = new Namespace({k1:1, k2:2, k3:3, $k4:4}); expect(item.image).to.be.deep.equal([1,2,3]); }); }); describe(".apply(...X)", () => { it("should return the tuple of values mapped to the arguments", () => { const item = new Namespace({k1:1, k2:2, k3:3, k4:4, k5:5, k6:6}); expect(item.apply('k2','k4','k6')).to.be.Tuple([2,4,6]); }); it("should normalize the returned tuple", () => { const item = new Namespace({k1:1, k2:2, k3:3, k4:4, k5:5, k6:6}); expect(item.apply('k2')).to.be.Numb(2); }); it("should return Undefined Mapping if the key is not in the Namespace domain", () => { const item = new Namespace({k1:1, k2:2, k3:3, k4:4, k5:5, k6:6}); expect(item.apply(-1)).to.be.Undefined('Mapping', arg0 => { expect(arg0).to.equal(-1); }); const tuple = item.apply('k2', -1, 'k4'); expect(tuple).to.be.instanceof(Tuple); expect(Array.from(tuple)[0]).to.equal(2); expect(Array.from(tuple)[1]).to.be.Undefined('Mapping', arg0 => { expect(arg0).to.equal(-1); }); expect(Array.from(tuple)[2]).to.equal(4); }); it("should call the __apply__ item if it is a function", async () => { const item = new Namespace({__apply__: (x, y) => x + y}); expect(await item.apply(10, 100)).to.be.Numb(110); }); }) }); describe("Func", () => { describe(".items()", () => { it("should yield the item itself", () => { const item = new Func(x=>x); expect(item.items()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.items())).to.deep.equal([item]); }); }); describe(".values()", () => { it("should yield the item value", () => { const item = new Func(x=>x); expect(item.values()[Symbol.iterator]).to.be.a("function"); expect(Array.from(item.values())).to.deep.equal([item.unwrap()]); }); }); describe("[Symbol.iterator]()", () => { it("should yield the item value", () => { const item = new Func(x=>x); expect(Array.from(item)).to.deep.equal([item.unwrap()]); }); }); describe(".iterPairs(other)", () => { it("should yield corresponding pairs of the two terms", () => { const item1 = new Func(x=>x); const item2 = new Func(x=>x); expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a("function"); const pairs = Array.from(item1.iterPairs(item2)); expect(pairs.length).to.equal(1); expect(pairs[0][0]).to.equal(item1); expect(pairs[0][1]).to.equal(item2); }); }); describe(".imapSync(fn)", () => { it("should synchronously apply fn to the item and return the wrapped output", () => { const item = new Func(x=>x); const fn = item => [item.unwrap()]; expect(item.imapSync(fn)).to.be.List([item.unwrap()]); }); }); describe(".vmapSync(fn)", () => { it("should synchronously apply fn to the item value and return the wrapped output", () => { const item = new Func(x=>x); const fn = value => [value]; expect(item.vmapSync(fn)).to.be.List([item.unwrap()]); }); }); describe(".imapAsync(fn)", () => { it("should asynchronously apply fn to the item and return the wrapped output", async () => { const item = new Func(x=>x); const fn = async item => [item.unwrap()]; expect(await item.imapAsync(fn)).to.be.List([item.unwrap()]); }); }); describe(".vmapAsync(fn)", () => {