UNPKG

mathjs

Version:

Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser and offers an integrated solution to work with numbers, big numbers, complex numbers, units, and matrices.

286 lines (234 loc) 10.5 kB
// test ConditionalNode var assert = require('assert'), approx = require('../../../tools/approx'), math = require('../../../index'), Node = require('../../../lib/expression/node/Node'), ConstantNode = require('../../../lib/expression/node/ConstantNode'), SymbolNode = require('../../../lib/expression/node/SymbolNode'), AssignmentNode = require('../../../lib/expression/node/AssignmentNode'), ConditionalNode = require('../../../lib/expression/node/ConditionalNode'); describe('ConditionalNode', function() { var condition = new ConstantNode(true); var zero = new ConstantNode(0); var one = new ConstantNode(1); var two = new ConstantNode(2); var three = new ConstantNode(3); var a = new AssignmentNode('a', two); var b = new AssignmentNode('b', three); it ('should create a ConditionalNode', function () { var n = new ConditionalNode(condition, a, b); assert(n instanceof ConditionalNode); assert(n instanceof Node); assert.equal(n.type, 'ConditionalNode'); }); it ('should throw an error when calling without new operator', function () { assert.throws(function () {ConditionalNode()}, SyntaxError); }); it ('should throw an error when creating without arguments', function () { assert.throws(function () {new ConditionalNode()}, TypeError); assert.throws(function () {new ConditionalNode(condition)}, TypeError); assert.throws(function () {new ConditionalNode(condition, a)}, TypeError); assert.throws(function () {new ConditionalNode(condition, null, b)}, TypeError); }); it ('should lazy evaluate a ConditionalNode', function () { var n = new ConditionalNode(condition, a, b); var expr = n.compile(math); var scope = {}; assert.equal(expr.eval(scope), 2); assert.deepEqual(scope, {a: 2}); }); describe('evaluate', function () { var condition = new ConditionalNode(new SymbolNode('a'), one, zero); it('should evaluate boolean conditions', function() { assert.equal(condition.compile(math).eval({a: true}), 1); assert.equal(condition.compile(math).eval({a: false}), 0); }); it('should evaluate number conditions', function() { assert.equal(condition.compile(math).eval({a: 1}), 1); assert.equal(condition.compile(math).eval({a: 4}), 1); assert.equal(condition.compile(math).eval({a: -1}), 1); assert.equal(condition.compile(math).eval({a: 0}), 0); }); it('should evaluate bignumber conditions', function() { assert.equal(condition.compile(math).eval({a: math.bignumber(1)}), 1); assert.equal(condition.compile(math).eval({a: math.bignumber(4)}), 1); assert.equal(condition.compile(math).eval({a: math.bignumber(-1)}), 1); assert.equal(condition.compile(math).eval({a: math.bignumber(0)}), 0); }); it('should evaluate complex number conditions', function() { assert.equal(condition.compile(math).eval({a: math.complex(2, 3)}), 1); assert.equal(condition.compile(math).eval({a: math.complex(2, 0)}), 1); assert.equal(condition.compile(math).eval({a: math.complex(0, 3)}), 1); assert.equal(condition.compile(math).eval({a: math.complex(0, 0)}), 0); }); it('should evaluate string conditions', function() { assert.equal(condition.compile(math).eval({a: 'hello'}), 1); assert.equal(condition.compile(math).eval({a: ''}), 0); }); it('should evaluate unit conditions', function() { assert.equal(condition.compile(math).eval({a: math.unit('5cm')}), 1); assert.equal(condition.compile(math).eval({a: math.unit('0 inch')}), 0); assert.equal(condition.compile(math).eval({a: math.unit('meter')}), 0); }); it('should evaluate null conditions', function() { assert.equal(condition.compile(math).eval({a: null}), 0); }); it('should evaluate undefined conditions', function() { assert.equal(condition.compile(math).eval({a: undefined}), 0); }); it('should throw an error in case of unsupported type of conditions', function() { assert.throws(function () {condition.compile(math).eval({a: {}})}); assert.throws(function () {condition.compile(math).eval({a: []})}); assert.throws(function () {condition.compile(math).eval({a: math.matrix()})}); }); }); it ('should filter a ConditionalNode', function () { var n = new ConditionalNode(condition, a, b); assert.deepEqual(n.filter(function (node) {return node instanceof ConditionalNode}), [n]); assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode}), [condition, two, three]); assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '2'}), [two]); }); it ('should run forEach on a ConditionalNode', function () { var condition = new ConstantNode(1); var a = new ConstantNode(2); var b = new ConstantNode(3); var n = new ConditionalNode(condition, a, b); var nodes = []; var paths = []; n.forEach(function (node, path, parent) { nodes.push(node); paths.push(path); assert.strictEqual(parent, n); }); assert.equal(nodes.length, 3); assert.strictEqual(nodes[0], condition); assert.strictEqual(nodes[1], a); assert.strictEqual(nodes[2], b); assert.deepEqual(paths, ['condition', 'trueExpr', 'falseExpr']); }); it ('should map a ConditionalNode', function () { var condition = new ConstantNode(1); var a = new ConstantNode(2); var b = new ConstantNode(3); var n = new ConditionalNode(condition, a, b); var nodes = []; var paths = []; var e = new ConstantNode(4); var f = n.map(function (node, path, parent) { nodes.push(node); paths.push(path); assert.strictEqual(parent, n); return node instanceof ConstantNode && node.value == '1' ? e : node; }); assert.equal(nodes.length, 3); assert.strictEqual(nodes[0], condition); assert.strictEqual(nodes[1], a); assert.strictEqual(nodes[2], b); assert.deepEqual(paths, ['condition', 'trueExpr', 'falseExpr']); assert.notStrictEqual(f, n); assert.strictEqual(f.condition, e); assert.strictEqual(f.trueExpr, a); assert.strictEqual(f.falseExpr, b); }); it ('should throw an error when the map callback does not return a node', function () { var condition = new ConstantNode(1); var a = new ConstantNode(2); var b = new ConstantNode(3); var n = new ConditionalNode(condition, a, b); assert.throws(function () { n.map(function () {}); }, /Callback function must return a Node/) }); it ('should transform a ConditionalNodes condition', function () { var condition = new ConstantNode(1); var a = new ConstantNode(2); var b = new ConstantNode(3); var n = new ConditionalNode(condition, a, b); var e = new ConstantNode(4); var f = n.transform(function (node) { return node instanceof ConstantNode && node.value == '1' ? e : node; }); assert.notStrictEqual(f, n); assert.strictEqual(f.condition, e); assert.deepEqual(f.trueExpr, a); assert.deepEqual(f.falseExpr, b); }); it ('should transform a ConditionalNodes trueExpr', function () { var condition = new ConstantNode(1); var a = new ConstantNode(2); var b = new ConstantNode(3); var n = new ConditionalNode(condition, a, b); var e = new ConstantNode(4); var f = n.transform(function (node) { return node instanceof ConstantNode && node.value == '2' ? e : node; }); assert.notStrictEqual(f, n); assert.deepEqual(f.condition, condition); assert.strictEqual(f.trueExpr, e); assert.deepEqual(f.falseExpr, b); }); it ('should transform a ConditionalNodes falseExpr', function () { var condition = new ConstantNode(1); var a = new ConstantNode(2); var b = new ConstantNode(3); var n = new ConditionalNode(condition, a, b); var e = new ConstantNode(4); var f = n.transform(function (node) { return node instanceof ConstantNode && node.value == '3' ? e : node; }); assert.notStrictEqual(f, n); assert.deepEqual(f.condition, condition); assert.deepEqual(f.trueExpr, a); assert.strictEqual(f.falseExpr, e); }); it ('should transform a ConditionalNode itself', function () { var condition = new ConstantNode(1); var a = new ConstantNode(2); var b = new ConstantNode(3); var n = new ConditionalNode(condition, a, b); var e = new ConstantNode(5); var f = n.transform(function (node) { return node instanceof ConditionalNode ? e : node; }); assert.strictEqual(f, e); }); it ('should clone a ConditionalNode itself', function () { var condition = new ConstantNode(1); var a = new ConstantNode(2); var b = new ConstantNode(3); var c = new ConditionalNode(condition, a, b); var d = c.clone(); assert(d instanceof ConditionalNode); assert.deepEqual(d, c); assert.notStrictEqual(d, c); assert.strictEqual(d.condition, c.condition); assert.strictEqual(d.trueExpr, c.trueExpr); assert.strictEqual(d.falseExpr, c.falseExpr); }); it ('should stringify a ConditionalNode', function () { var n = new ConditionalNode(condition, a, b); assert.equal(n.toString(), 'true ? (a = 2) : (b = 3)'); }); it ('should LaTeX a ConditionalNode', function () { var n = new ConditionalNode(condition, a, b); assert.equal(n.toTex(), '\\left\\{\\begin{array}{l l}{{a}={2}}, &\\quad{\\text{if}\\;true}\\\\{{b}={3}}, &\\quad{\\text{otherwise}}\\end{array}\\right.'); }); it ('should LaTeX a ConditionalNode with custom toTex', function () { //Also checks if the custom functions get passed on to the children var customFunction = function (node, callback) { if (node.type === 'ConditionalNode') { return 'if ' + node.condition.toTex(callback) + ' then ' + node.trueExpr.toTex(callback) + ' else ' + node.falseExpr.toTex(callback); } else if (node.type === 'ConstantNode') { return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)' } }; var a = new ConstantNode(1); var b = new ConstantNode(2); var c = new ConstantNode(3); var n = new ConditionalNode(a, b, c); assert.equal(n.toTex(customFunction), 'if const\\left(1, number\\right) then const\\left(2, number\\right) else const\\left(3, number\\right)'); }); });