mirror of
https://github.com/josdejong/mathjs.git
synced 2025-12-08 19:46:04 +00:00
269 lines
8.2 KiB
JavaScript
269 lines
8.2 KiB
JavaScript
// test ObjectNode
|
|
var assert = require('assert');
|
|
var approx = require('../../../tools/approx');
|
|
var math = require('../../../index');
|
|
var Node = math.expression.node.Node;
|
|
var ConstantNode = math.expression.node.ConstantNode;
|
|
var SymbolNode = math.expression.node.SymbolNode;
|
|
var RangeNode = math.expression.node.RangeNode;
|
|
var ObjectNode = math.expression.node.ObjectNode;
|
|
|
|
// FIXME: a lot of tests depend on order of object keys, whilst the order is officially undeterministic
|
|
|
|
describe('ObjectNode', function() {
|
|
|
|
it ('should create an ObjectNode', function () {
|
|
var c = new ConstantNode(1);
|
|
var a = new ObjectNode({c: c});
|
|
var b = new ObjectNode();
|
|
assert(a instanceof ObjectNode);
|
|
assert(b instanceof ObjectNode);
|
|
assert.equal(a.type, 'ObjectNode');
|
|
assert.equal(b.type, 'ObjectNode');
|
|
});
|
|
|
|
it ('should have isObjectNode', function () {
|
|
var node = new ObjectNode({});
|
|
|
|
assert(node.isObjectNode);
|
|
});
|
|
|
|
it ('should throw an error when calling without new operator', function () {
|
|
assert.throws(function () {ObjectNode()}, SyntaxError);
|
|
});
|
|
|
|
it ('should throw an error on wrong constructor arguments', function () {
|
|
assert.throws(function () {new ObjectNode(2)}, TypeError);
|
|
assert.throws(function () {new ObjectNode({a: 2, b: 3})}, TypeError);
|
|
});
|
|
|
|
it ('should evaluate an ObjectNode', function () {
|
|
var c = new ConstantNode(1);
|
|
var a = new ObjectNode({c: c});
|
|
var b = new ObjectNode();
|
|
|
|
assert.deepEqual(a.compile().eval(), {c: 1});
|
|
assert.deepEqual(b.compile().eval(), {});
|
|
});
|
|
|
|
it ('should compile nested ObjectNodes', function () {
|
|
var a = new ConstantNode(1);
|
|
var b = new ConstantNode(2);
|
|
var c = new ConstantNode(3);
|
|
var d = new ConstantNode(4);
|
|
|
|
var n2 = new ObjectNode({a: a, b: b});
|
|
var n3 = new ObjectNode({c: c, d: d});
|
|
var n4 = new ObjectNode({n2: n2, n3: n3});
|
|
|
|
var expr = n4.compile();
|
|
assert.deepEqual(expr.eval(), {n2: {a: 1, b: 2}, n3: {c: 3, d: 4}});
|
|
});
|
|
|
|
it ('should filter an ObjectNode', function () {
|
|
var a = new ConstantNode(1);
|
|
var b = new SymbolNode('x');
|
|
var c = new ConstantNode(2);
|
|
var d = new ObjectNode({a: a, b: b, c: c});
|
|
|
|
assert.deepEqual(d.filter(function (node) {return node instanceof ObjectNode}), [d]);
|
|
assert.deepEqual(d.filter(function (node) {return node instanceof SymbolNode}), [b]);
|
|
assert.deepEqual(d.filter(function (node) {return node instanceof RangeNode}), []);
|
|
assert.deepEqual(d.filter(function (node) {return node instanceof ConstantNode}), [a, c]);
|
|
assert.deepEqual(d.filter(function (node) {return node instanceof ConstantNode && node.value == '2'}), [c]);
|
|
});
|
|
|
|
it ('should run forEach on an ObjectNode', function () {
|
|
var a = new SymbolNode('x');
|
|
var b = new ConstantNode(2);
|
|
var c = new ObjectNode({a: a, b: b});
|
|
|
|
var nodes = [];
|
|
var paths = [];
|
|
c.forEach(function (node, path, parent) {
|
|
nodes.push(node);
|
|
paths.push(path);
|
|
assert.strictEqual(parent, c);
|
|
});
|
|
|
|
assert.deepEqual(paths, ['properties["a"]', 'properties["b"]']);
|
|
assert.equal(nodes.length, 2);
|
|
assert.strictEqual(nodes[0], a);
|
|
assert.strictEqual(nodes[1], b);
|
|
});
|
|
|
|
it ('should map an ObjectNode', function () {
|
|
var a = new SymbolNode('x');
|
|
var b = new ConstantNode(2);
|
|
var c = new ObjectNode({a: a, b: b});
|
|
|
|
var d = new ConstantNode(3);
|
|
var nodes = [];
|
|
var paths = [];
|
|
var e = c.map(function (node, path, parent) {
|
|
nodes.push(node);
|
|
paths.push(path);
|
|
assert.strictEqual(parent, c);
|
|
|
|
return (node instanceof SymbolNode) && (node.name == 'x') ? d : node;
|
|
});
|
|
|
|
assert.deepEqual(paths, ['properties["a"]', 'properties["b"]']);
|
|
assert.equal(nodes.length, 2);
|
|
assert.strictEqual(nodes[0], a);
|
|
assert.strictEqual(nodes[1], b);
|
|
|
|
assert.notStrictEqual(e, c);
|
|
assert.deepEqual(e.properties["a"], d);
|
|
assert.deepEqual(e.properties["b"], b);
|
|
});
|
|
|
|
it ('should throw an error when the map callback does not return a node', function () {
|
|
var a = new SymbolNode('x');
|
|
var b = new ConstantNode(2);
|
|
var c = new ObjectNode({a: a, b: b});
|
|
|
|
assert.throws(function () {
|
|
c.map(function () {});
|
|
}, /Callback function must return a Node/)
|
|
});
|
|
|
|
it ('should transform an ObjectNodes parameters', function () {
|
|
var a = new SymbolNode('x');
|
|
var b = new ConstantNode(2);
|
|
var c = new ObjectNode({a: a, b: b});
|
|
|
|
var d = new ConstantNode(3);
|
|
var e = c.transform(function (node) {
|
|
return (node instanceof SymbolNode) && (node.name == 'x') ? d : node;
|
|
});
|
|
|
|
assert.notStrictEqual(e, c);
|
|
assert.deepEqual(e.properties["a"], d);
|
|
assert.deepEqual(e.properties["b"], b);
|
|
});
|
|
|
|
it ('should transform an ObjectNode itself', function () {
|
|
var a = new SymbolNode('x');
|
|
var b = new ConstantNode(2);
|
|
var c = new ObjectNode({a: a, b: b});
|
|
|
|
var d = new ConstantNode(3);
|
|
var e = c.transform(function (node) {
|
|
return (node instanceof ObjectNode) ? d : node;
|
|
});
|
|
|
|
assert.notStrictEqual(e, c);
|
|
assert.deepEqual(e, d);
|
|
});
|
|
|
|
it ('should traverse an ObjectNode', function () {
|
|
var a = new ConstantNode(1);
|
|
var b = new ConstantNode(2);
|
|
var c = new ConstantNode(3);
|
|
var d = new ObjectNode({a: a, b: b});
|
|
var e = new ObjectNode({c: c, d: d});
|
|
|
|
var count = 0;
|
|
e.traverse(function (node, path, parent) {
|
|
count++;
|
|
|
|
switch(count) {
|
|
case 1:
|
|
assert.strictEqual(path, null);
|
|
assert.strictEqual(node, e);
|
|
assert.strictEqual(parent, null);
|
|
break;
|
|
|
|
case 2:
|
|
assert.strictEqual(path, 'properties["c"]');
|
|
assert.strictEqual(node, c);
|
|
assert.strictEqual(parent, e);
|
|
break;
|
|
|
|
case 3:
|
|
assert.strictEqual(path, 'properties["d"]');
|
|
assert.strictEqual(node, d);
|
|
assert.strictEqual(parent, e);
|
|
break;
|
|
|
|
case 4:
|
|
assert.strictEqual(path, 'properties["a"]');
|
|
assert.strictEqual(node, a);
|
|
assert.strictEqual(parent, d);
|
|
break;
|
|
|
|
case 5:
|
|
assert.strictEqual(path, 'properties["b"]');
|
|
assert.strictEqual(node, b);
|
|
assert.strictEqual(parent, d);
|
|
break;
|
|
}
|
|
});
|
|
|
|
assert.equal(count, 5);
|
|
});
|
|
|
|
it ('should clone an ObjectNode', function () {
|
|
var a = new SymbolNode('x');
|
|
var b = new ConstantNode(2);
|
|
var c = new ObjectNode({a: a, b: b});
|
|
|
|
var d = c.clone();
|
|
assert(d instanceof ObjectNode);
|
|
assert.deepEqual(c, d);
|
|
assert.notStrictEqual(c, d);
|
|
assert.strictEqual(c.properties["a"], d.properties["a"]);
|
|
assert.strictEqual(c.properties["b"], d.properties["b"]);
|
|
});
|
|
|
|
it ('should stringify an ObjectNode', function () {
|
|
var a = new ConstantNode(1);
|
|
var b = new ConstantNode(2);
|
|
var c = new ConstantNode(3);
|
|
var n1 = new ObjectNode({a: a, b: b});
|
|
var n2 = new ObjectNode({c: c, n1: n1});
|
|
|
|
assert.equal(n2.toString(), '{"c": 3, "n1": {"a": 1, "b": 2}}');
|
|
});
|
|
|
|
it ('should stringify an ObjectNode with custom toString', function () {
|
|
var customFunction = function (node, options) {
|
|
if (node.type === 'ConstantNode') {
|
|
return 'const(' + node.value + ', ' + node.valueType + ')'
|
|
}
|
|
};
|
|
|
|
var a = new ConstantNode(1);
|
|
var b = new ConstantNode(2);
|
|
var n = new ObjectNode({a: a, b: b});
|
|
|
|
assert.equal(n.toString({handler: customFunction}), '{"a": const(1, number), "b": const(2, number)}');
|
|
});
|
|
|
|
it ('should LaTeX an ObjectNode', function () {
|
|
var a = new ConstantNode(1);
|
|
var b = new ConstantNode(2);
|
|
var c = new ConstantNode(3);
|
|
var n1 = new ObjectNode({a: a, b: b});
|
|
var n2 = new ObjectNode({c: c, n1: n1});
|
|
|
|
assert.equal(n2.toTex(), '\\{"c": 3, "n1": \\{"a": 1, "b": 2\\}\\}');
|
|
});
|
|
|
|
it ('should LaTeX an ObjectNode with custom toTex', function () {
|
|
var customFunction = function (node, options) {
|
|
if (node.type === 'ConstantNode') {
|
|
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
|
}
|
|
};
|
|
|
|
var a = new ConstantNode(1);
|
|
var b = new ConstantNode(2);
|
|
var n = new ObjectNode({a: a, b: b});
|
|
|
|
assert.equal(n.toTex({handler: customFunction}), '\\{"a": const\\left(1, number\\right), "b": const\\left(2, number\\right)\\}');
|
|
});
|
|
|
|
});
|