Move vector code out of the way
This commit is contained in:
979
old/test/spec/ol/expr/expression.test.js
Normal file
979
old/test/spec/ol/expr/expression.test.js
Normal file
@@ -0,0 +1,979 @@
|
||||
goog.provide('ol.test.expression');
|
||||
|
||||
|
||||
describe('ol.expr.parse()', function() {
|
||||
|
||||
it('parses a subset of ECMAScript 5.1 expressions', function() {
|
||||
var expr = ol.expr.parse('foo');
|
||||
expect(expr).to.be.a(ol.expr.Expression);
|
||||
});
|
||||
|
||||
describe('11.1 - primary expressions', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.1
|
||||
|
||||
it('parses identifier expressions', function() {
|
||||
var expr = ol.expr.parse('foo');
|
||||
expect(expr).to.be.a(ol.expr.Identifier);
|
||||
expect(expr.evaluate({foo: 'bar'})).to.be('bar');
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected', function() {
|
||||
var expr = ol.expr.parse(' foo ');
|
||||
expect(expr).to.be.a(ol.expr.Identifier);
|
||||
expect(expr.evaluate({foo: 'bar'})).to.be('bar');
|
||||
});
|
||||
|
||||
it('throws on invalid identifier expressions', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse('3foo');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('f');
|
||||
expect(token.index).to.be(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('parses string literal expressions', function() {
|
||||
var expr = ol.expr.parse('"foo"');
|
||||
expect(expr).to.be.a(ol.expr.Literal);
|
||||
expect(expr.evaluate()).to.be('foo');
|
||||
});
|
||||
|
||||
it('throws on unterminated string', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse('"foo');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.type).to.be(ol.expr.TokenType.EOF);
|
||||
expect(token.index).to.be(4);
|
||||
});
|
||||
});
|
||||
|
||||
it('parses numeric literal expressions', function() {
|
||||
var expr = ol.expr.parse('.42e+2');
|
||||
expect(expr).to.be.a(ol.expr.Literal);
|
||||
expect(expr.evaluate()).to.be(42);
|
||||
});
|
||||
|
||||
it('throws on invalid number', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse('.42eX');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('X');
|
||||
expect(token.index).to.be(4);
|
||||
});
|
||||
});
|
||||
|
||||
it('parses boolean literal expressions', function() {
|
||||
var expr = ol.expr.parse('false');
|
||||
expect(expr).to.be.a(ol.expr.Literal);
|
||||
expect(expr.evaluate()).to.be(false);
|
||||
});
|
||||
|
||||
it('parses null literal expressions', function() {
|
||||
var expr = ol.expr.parse('null');
|
||||
expect(expr).to.be.a(ol.expr.Literal);
|
||||
expect(expr.evaluate()).to.be(null);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('11.2 - left-hand-side expressions', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.2
|
||||
|
||||
it('parses member expressions with dot notation', function() {
|
||||
var expr = ol.expr.parse('foo.bar.baz');
|
||||
expect(expr).to.be.a(ol.expr.Member);
|
||||
var scope = {foo: {bar: {baz: 42}}};
|
||||
expect(expr.evaluate(scope)).to.be(42);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected', function() {
|
||||
var expr = ol.expr.parse(' foo . bar . baz ');
|
||||
expect(expr).to.be.a(ol.expr.Member);
|
||||
var scope = {foo: {bar: {baz: 42}}};
|
||||
expect(expr.evaluate(scope)).to.be(42);
|
||||
});
|
||||
|
||||
it('throws on invalid member expression', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse('foo.4bar');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('b');
|
||||
expect(token.index).to.be(5);
|
||||
});
|
||||
});
|
||||
|
||||
it('parses call expressions with literal arguments', function() {
|
||||
var expr = ol.expr.parse('foo(42, "bar")');
|
||||
expect(expr).to.be.a(ol.expr.Call);
|
||||
var scope = {
|
||||
foo: function(num, str) {
|
||||
expect(num).to.be(42);
|
||||
expect(str).to.be('bar');
|
||||
return str + num;
|
||||
}
|
||||
};
|
||||
expect(expr.evaluate(scope)).to.be('bar42');
|
||||
});
|
||||
|
||||
it('throws on calls with unterminated arguments', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse('foo(42,)');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be(')');
|
||||
expect(token.index).to.be(7);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('11.3 - postfix expressions', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.3
|
||||
it('not supported');
|
||||
});
|
||||
|
||||
|
||||
describe('11.4 - unary operators', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.4
|
||||
|
||||
it('parses logical not operator', function() {
|
||||
var expr = ol.expr.parse('!foo');
|
||||
expect(expr).to.be.a(ol.expr.Not);
|
||||
expect(expr.evaluate({foo: true})).to.be(false);
|
||||
expect(expr.evaluate({foo: false})).to.be(true);
|
||||
expect(expr.evaluate({foo: ''})).to.be(true);
|
||||
expect(expr.evaluate({foo: 'foo'})).to.be(false);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected', function() {
|
||||
var expr = ol.expr.parse(' ! foo');
|
||||
expect(expr).to.be.a(ol.expr.Not);
|
||||
expect(expr.evaluate({foo: true})).to.be(false);
|
||||
expect(expr.evaluate({foo: false})).to.be(true);
|
||||
});
|
||||
|
||||
it('parses not preceeding call expression', function() {
|
||||
var lib = {
|
||||
foo: function() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
var expr = ol.expr.parse('!foo()');
|
||||
expect(expr).to.be.a(ol.expr.Not);
|
||||
expect(expr.evaluate(null, lib)).to.be(false);
|
||||
});
|
||||
|
||||
it('parses not in call argument', function() {
|
||||
var lib = {
|
||||
foo: function(arg) {
|
||||
return arg;
|
||||
}
|
||||
};
|
||||
var expr = ol.expr.parse('foo(!bar)');
|
||||
expect(expr).to.be.a(ol.expr.Call);
|
||||
expect(expr.evaluate({bar: true}, lib)).to.be(false);
|
||||
expect(expr.evaluate({bar: false}, lib)).to.be(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('11.5 - multiplicitave operators', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.5
|
||||
|
||||
it('parses * operator', function() {
|
||||
var expr = ol.expr.parse('foo*bar');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({foo: 10, bar: 20})).to.be(200);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with *', function() {
|
||||
var expr = ol.expr.parse(' foo * bar ');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({foo: 15, bar: 2})).to.be(30);
|
||||
});
|
||||
|
||||
it('parses / operator', function() {
|
||||
var expr = ol.expr.parse('foo/12');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({foo: 10})).to.be(10 / 12);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with /', function() {
|
||||
var expr = ol.expr.parse(' 4 / bar ');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({bar: 3})).to.be(4 / 3);
|
||||
});
|
||||
|
||||
it('parses % operator', function() {
|
||||
var expr = ol.expr.parse('12%foo');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({foo: 10})).to.be(2);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with %', function() {
|
||||
var expr = ol.expr.parse(' 4 %bar ');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({bar: 3})).to.be(1);
|
||||
});
|
||||
|
||||
it('parses * in call argument', function() {
|
||||
var lib = {
|
||||
foo: function(arg) {
|
||||
return arg;
|
||||
}
|
||||
};
|
||||
var expr = ol.expr.parse('foo(2 * bar)');
|
||||
expect(expr).to.be.a(ol.expr.Call);
|
||||
expect(expr.evaluate({bar: 3}, lib)).to.be(6);
|
||||
expect(expr.evaluate({bar: 4}, lib)).to.be(8);
|
||||
});
|
||||
|
||||
it('evaluates left to right for equal precedence', function() {
|
||||
var expr = ol.expr.parse('2 / 4 * 20 % 15');
|
||||
expect(expr.evaluate()).to.be(10);
|
||||
});
|
||||
|
||||
it('respects group precedence', function() {
|
||||
expect(ol.expr.parse('2 / 4 * (20 % 15)').evaluate()).to.be(2.5);
|
||||
expect(ol.expr.parse('2 / (4 * (20 % 15))').evaluate()).to.be(0.1);
|
||||
expect(ol.expr.parse('2 / ((4 * 20) % 15)').evaluate()).to.be(0.4);
|
||||
expect(ol.expr.parse('2 / (4 * 20) % 15').evaluate()).to.be(0.025);
|
||||
expect(ol.expr.parse('(2 / (4 * 20)) % 15').evaluate()).to.be(0.025);
|
||||
expect(ol.expr.parse('(2 / 4) * 20 % 15').evaluate()).to.be(10);
|
||||
expect(ol.expr.parse('((2 / 4) * 20) % 15').evaluate()).to.be(10);
|
||||
});
|
||||
|
||||
it('parses * in left side of comparison expression', function() {
|
||||
var expr = ol.expr.parse('foo * 2 >bar');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 4, bar: 7})).to.be(true);
|
||||
expect(expr.evaluate({foo: 4, bar: 8})).to.be(false);
|
||||
});
|
||||
|
||||
it('parses * in right side of comparison expression', function() {
|
||||
var expr = ol.expr.parse('foo > 2 * bar');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 4, bar: 1})).to.be(true);
|
||||
expect(expr.evaluate({foo: 4, bar: 2})).to.be(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('11.6 - additive operators', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.6
|
||||
|
||||
it('parses + operator', function() {
|
||||
var expr = ol.expr.parse('foo+bar');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({foo: 10, bar: 20})).to.be(30);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with +', function() {
|
||||
var expr = ol.expr.parse(' foo +10 ');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({foo: 15})).to.be(25);
|
||||
});
|
||||
|
||||
it('parses - operator', function() {
|
||||
var expr = ol.expr.parse('foo-bar');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({foo: 10, bar: 20})).to.be(-10);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with -', function() {
|
||||
var expr = ol.expr.parse(' foo- 10 ');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({foo: 15})).to.be(5);
|
||||
});
|
||||
|
||||
it('respects precedence', function() {
|
||||
expect(ol.expr.parse('2 + 4 * 20 - 15').evaluate()).to.be(67);
|
||||
expect(ol.expr.parse('(2 + 4) * 20 - 15').evaluate()).to.be(105);
|
||||
expect(ol.expr.parse('((2 + 4) * 20) - 15').evaluate()).to.be(105);
|
||||
expect(ol.expr.parse('(2 + (4 * 20)) - 15').evaluate()).to.be(67);
|
||||
expect(ol.expr.parse('2 + (4 * 20) - 15').evaluate()).to.be(67);
|
||||
expect(ol.expr.parse('2 + ((4 * 20) - 15)').evaluate()).to.be(67);
|
||||
expect(ol.expr.parse('2 + (4 * (20 - 15))').evaluate()).to.be(22);
|
||||
expect(ol.expr.parse('2 + 4 * (20 - 15)').evaluate()).to.be(22);
|
||||
});
|
||||
|
||||
it('parses + in call argument', function() {
|
||||
var lib = {
|
||||
foo: function(arg) {
|
||||
return arg;
|
||||
}
|
||||
};
|
||||
var expr = ol.expr.parse('foo(2 + bar)');
|
||||
expect(expr).to.be.a(ol.expr.Call);
|
||||
expect(expr.evaluate({bar: 3}, lib)).to.be(5);
|
||||
expect(expr.evaluate({bar: 4}, lib)).to.be(6);
|
||||
});
|
||||
|
||||
it('parses + in left side of comparison expression', function() {
|
||||
var expr = ol.expr.parse('foo+2>bar');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 4, bar: 5})).to.be(true);
|
||||
expect(expr.evaluate({foo: 4, bar: 6})).to.be(false);
|
||||
});
|
||||
|
||||
it('parses + in right side of comparison expression', function() {
|
||||
var expr = ol.expr.parse('foo >2 +bar');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 4, bar: 1})).to.be(true);
|
||||
expect(expr.evaluate({foo: 4, bar: 2})).to.be(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('11.7 - bitwise shift operators', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.7
|
||||
it('not supported');
|
||||
});
|
||||
|
||||
describe('11.8 - relational operators', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.8
|
||||
|
||||
it('parses < operator', function() {
|
||||
var expr = ol.expr.parse('foo<bar');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 10, bar: 20})).to.be(true);
|
||||
expect(expr.evaluate({foo: 100, bar: 20})).to.be(false);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with <', function() {
|
||||
var expr = ol.expr.parse(' foo <10 ');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 15})).to.be(false);
|
||||
expect(expr.evaluate({foo: 5})).to.be(true);
|
||||
});
|
||||
|
||||
it('parses > operator', function() {
|
||||
var expr = ol.expr.parse('foo>bar');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 10, bar: 20})).to.be(false);
|
||||
expect(expr.evaluate({foo: 100, bar: 20})).to.be(true);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with >', function() {
|
||||
var expr = ol.expr.parse(' foo> 10 ');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 15})).to.be(true);
|
||||
expect(expr.evaluate({foo: 5})).to.be(false);
|
||||
});
|
||||
|
||||
it('parses <= operator', function() {
|
||||
var expr = ol.expr.parse('foo<=bar');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 10, bar: 20})).to.be(true);
|
||||
expect(expr.evaluate({foo: 100, bar: 20})).to.be(false);
|
||||
expect(expr.evaluate({foo: 20, bar: 20})).to.be(true);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with <=', function() {
|
||||
var expr = ol.expr.parse(' foo<= 10 ');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 15})).to.be(false);
|
||||
expect(expr.evaluate({foo: 5})).to.be(true);
|
||||
expect(expr.evaluate({foo: 10})).to.be(true);
|
||||
});
|
||||
|
||||
it('throws for invalid spacing with <=', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse(' foo< = 10 ');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('=');
|
||||
expect(token.index).to.be(6);
|
||||
});
|
||||
});
|
||||
|
||||
it('parses >= operator', function() {
|
||||
var expr = ol.expr.parse('foo>=bar');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 10, bar: 20})).to.be(false);
|
||||
expect(expr.evaluate({foo: 100, bar: 20})).to.be(true);
|
||||
expect(expr.evaluate({foo: 20, bar: 20})).to.be(true);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with >=', function() {
|
||||
var expr = ol.expr.parse(' foo >=10 ');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 15})).to.be(true);
|
||||
expect(expr.evaluate({foo: 5})).to.be(false);
|
||||
expect(expr.evaluate({foo: 10})).to.be(true);
|
||||
});
|
||||
|
||||
it('throws for invalid spacing with >=', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse(' 10 > =foo ');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('=');
|
||||
expect(token.index).to.be(6);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('11.9 - equality operators', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.9
|
||||
|
||||
it('parses == operator', function() {
|
||||
var expr = ol.expr.parse('foo==42');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 42})).to.be(true);
|
||||
expect(expr.evaluate({foo: 41})).to.be(false);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(true);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with ==', function() {
|
||||
var expr = ol.expr.parse(' 42 ==foo ');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 42})).to.be(true);
|
||||
expect(expr.evaluate({foo: 41})).to.be(false);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(true);
|
||||
});
|
||||
|
||||
it('throws for invalid spacing with ==', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse(' 10 = =foo ');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('=');
|
||||
expect(token.index).to.be(4);
|
||||
});
|
||||
});
|
||||
|
||||
it('parses != operator', function() {
|
||||
var expr = ol.expr.parse('foo!=42');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 42})).to.be(false);
|
||||
expect(expr.evaluate({foo: 41})).to.be(true);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(false);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with !=', function() {
|
||||
var expr = ol.expr.parse(' 42 !=foo ');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 42})).to.be(false);
|
||||
expect(expr.evaluate({foo: 41})).to.be(true);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(false);
|
||||
});
|
||||
|
||||
it('throws for invalid spacing with !=', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse(' 10! =foo ');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('!');
|
||||
expect(token.index).to.be(3);
|
||||
});
|
||||
});
|
||||
|
||||
it('parses === operator', function() {
|
||||
var expr = ol.expr.parse('42===foo');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 42})).to.be(true);
|
||||
expect(expr.evaluate({foo: 41})).to.be(false);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(false);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with ===', function() {
|
||||
var expr = ol.expr.parse(' foo ===42 ');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 42})).to.be(true);
|
||||
expect(expr.evaluate({foo: 41})).to.be(false);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(false);
|
||||
});
|
||||
|
||||
it('throws for invalid spacing with ===', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse(' 10 = == foo ');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('=');
|
||||
expect(token.index).to.be(4);
|
||||
});
|
||||
});
|
||||
|
||||
it('parses !== operator', function() {
|
||||
var expr = ol.expr.parse('foo!==42');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 42})).to.be(false);
|
||||
expect(expr.evaluate({foo: 41})).to.be(true);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(true);
|
||||
});
|
||||
|
||||
it('consumes whitespace as expected with !==', function() {
|
||||
var expr = ol.expr.parse(' 42 !== foo ');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate({foo: 42})).to.be(false);
|
||||
expect(expr.evaluate({foo: 41})).to.be(true);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(true);
|
||||
});
|
||||
|
||||
it('throws for invalid spacing with !==', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse(' 10 != = foo ');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('=');
|
||||
expect(token.index).to.be(7);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('11.10 - binary bitwise operators', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.10
|
||||
it('not supported');
|
||||
});
|
||||
|
||||
describe('11.11 - binary logical operators', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.11
|
||||
|
||||
it('parses && operator', function() {
|
||||
var expr = ol.expr.parse('foo&&bar');
|
||||
expect(expr).to.be.a(ol.expr.Logical);
|
||||
expect(expr.evaluate({foo: true, bar: true})).to.be(true);
|
||||
expect(expr.evaluate({foo: true, bar: false})).to.be(false);
|
||||
expect(expr.evaluate({foo: false, bar: true})).to.be(false);
|
||||
expect(expr.evaluate({foo: false, bar: false})).to.be(false);
|
||||
});
|
||||
|
||||
it('consumes space as expected with &&', function() {
|
||||
var expr = ol.expr.parse(' foo && bar ');
|
||||
expect(expr).to.be.a(ol.expr.Logical);
|
||||
expect(expr.evaluate({foo: true, bar: true})).to.be(true);
|
||||
expect(expr.evaluate({foo: true, bar: false})).to.be(false);
|
||||
expect(expr.evaluate({foo: false, bar: true})).to.be(false);
|
||||
expect(expr.evaluate({foo: false, bar: false})).to.be(false);
|
||||
});
|
||||
|
||||
it('throws for invalid spacing with &&', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse('true & & false');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('&');
|
||||
expect(token.index).to.be(5);
|
||||
});
|
||||
});
|
||||
|
||||
it('parses || operator', function() {
|
||||
var expr = ol.expr.parse('foo||bar');
|
||||
expect(expr).to.be.a(ol.expr.Logical);
|
||||
expect(expr.evaluate({foo: true, bar: true})).to.be(true);
|
||||
expect(expr.evaluate({foo: true, bar: false})).to.be(true);
|
||||
expect(expr.evaluate({foo: false, bar: true})).to.be(true);
|
||||
expect(expr.evaluate({foo: false, bar: false})).to.be(false);
|
||||
});
|
||||
|
||||
it('consumes space as expected with ||', function() {
|
||||
var expr = ol.expr.parse(' foo || bar ');
|
||||
expect(expr).to.be.a(ol.expr.Logical);
|
||||
expect(expr.evaluate({foo: true, bar: true})).to.be(true);
|
||||
expect(expr.evaluate({foo: true, bar: false})).to.be(true);
|
||||
expect(expr.evaluate({foo: false, bar: true})).to.be(true);
|
||||
expect(expr.evaluate({foo: false, bar: false})).to.be(false);
|
||||
});
|
||||
|
||||
it('throws for invalid spacing with ||', function() {
|
||||
expect(function() {
|
||||
ol.expr.parse('true | | false');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('|');
|
||||
expect(token.index).to.be(5);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('11.12 - conditional operator', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.12
|
||||
it('not supported');
|
||||
});
|
||||
|
||||
describe('11.13 - assignment operators', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.13
|
||||
it('not supported');
|
||||
});
|
||||
|
||||
describe('11.14 - comma operator', function() {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.14
|
||||
it('not supported');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('ol.expr.lib', function() {
|
||||
|
||||
var parse = ol.expr.parse;
|
||||
var evaluate = ol.expr.evaluateFeature;
|
||||
|
||||
describe('concat()', function() {
|
||||
var feature = new ol.Feature({
|
||||
str: 'bar',
|
||||
num: 42,
|
||||
bool: false,
|
||||
nul: null
|
||||
});
|
||||
|
||||
it('concatenates strings', function() {
|
||||
expect(evaluate(parse('concat(str, "after")'), feature))
|
||||
.to.be('barafter');
|
||||
expect(evaluate(parse('concat("before", str)'), feature))
|
||||
.to.be('beforebar');
|
||||
expect(evaluate(parse('concat("a", str, "b")'), feature))
|
||||
.to.be('abarb');
|
||||
});
|
||||
|
||||
it('concatenates numbers as strings', function() {
|
||||
expect(evaluate(parse('concat(num, 0)'), feature))
|
||||
.to.be('420');
|
||||
expect(evaluate(parse('concat(0, num)'), feature))
|
||||
.to.be('042');
|
||||
expect(evaluate(parse('concat(42, 42)'), feature))
|
||||
.to.be('4242');
|
||||
expect(evaluate(parse('concat(str, num)'), feature))
|
||||
.to.be('bar42');
|
||||
});
|
||||
|
||||
it('concatenates booleans as strings', function() {
|
||||
expect(evaluate(parse('concat(bool, "foo")'), feature))
|
||||
.to.be('falsefoo');
|
||||
expect(evaluate(parse('concat(true, str)'), feature))
|
||||
.to.be('truebar');
|
||||
expect(evaluate(parse('concat(true, false)'), feature))
|
||||
.to.be('truefalse');
|
||||
});
|
||||
|
||||
it('concatenates nulls as strings', function() {
|
||||
expect(evaluate(parse('concat(nul, "foo")'), feature))
|
||||
.to.be('nullfoo');
|
||||
expect(evaluate(parse('concat(str, null)'), feature))
|
||||
.to.be('barnull');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('counter()', function() {
|
||||
|
||||
it('increases the counter with every call', function() {
|
||||
var counter = parse('counter()');
|
||||
var start = evaluate(counter);
|
||||
expect(evaluate(counter)).to.be(start + 1);
|
||||
expect(evaluate(counter)).to.be(start + 2);
|
||||
});
|
||||
|
||||
it('increases the counter, starting with a custom value', function() {
|
||||
var counterWithStart = parse('counter(1000)');
|
||||
var start = evaluate(counterWithStart);
|
||||
expect(start > 1000).to.be(true);
|
||||
expect(evaluate(counterWithStart)).to.be(start + 1);
|
||||
expect(evaluate(counterWithStart)).to.be(start + 2);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('extent()', function() {
|
||||
|
||||
var nw = new ol.Feature({
|
||||
geom: new ol.geom.Polygon([[
|
||||
[-180, 90], [0, 90], [0, 0], [-180, 0], [-180, 90]
|
||||
]])
|
||||
});
|
||||
|
||||
var se = new ol.Feature({
|
||||
geom: new ol.geom.Polygon([[
|
||||
[180, -90], [0, -90], [0, 0], [180, 0], [180, -90]
|
||||
]])
|
||||
});
|
||||
|
||||
var north = parse('extent(-100, 40, 100, 60)');
|
||||
var south = parse('extent(-100, -60, 100, -40)');
|
||||
var east = parse('extent(80, -50, 100, 50)');
|
||||
var west = parse('extent(-100, -50, -80, 50)');
|
||||
|
||||
it('evaluates to true for features within given extent', function() {
|
||||
|
||||
expect(evaluate(north, nw)).to.be(true);
|
||||
expect(evaluate(south, nw)).to.be(false);
|
||||
expect(evaluate(east, nw)).to.be(false);
|
||||
expect(evaluate(west, nw)).to.be(true);
|
||||
|
||||
expect(evaluate(north, se)).to.be(false);
|
||||
expect(evaluate(south, se)).to.be(true);
|
||||
expect(evaluate(east, se)).to.be(true);
|
||||
expect(evaluate(west, se)).to.be(false);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('fid()', function() {
|
||||
|
||||
var one = new ol.Feature();
|
||||
one.setId('one');
|
||||
|
||||
var two = new ol.Feature();
|
||||
two.setId('two');
|
||||
|
||||
var three = new ol.Feature();
|
||||
three.setId('three');
|
||||
|
||||
var four = new ol.Feature();
|
||||
four.setId('four');
|
||||
|
||||
var odd = parse('fid("one", "three")');
|
||||
var even = parse('fid("two", "four")');
|
||||
var first = parse('fid("one")');
|
||||
var last = parse('fid("four")');
|
||||
var none = parse('fid("foo")');
|
||||
|
||||
it('evaluates to true if feature id matches', function() {
|
||||
expect(evaluate(odd, one)).to.be(true);
|
||||
expect(evaluate(odd, three)).to.be(true);
|
||||
expect(evaluate(even, two)).to.be(true);
|
||||
expect(evaluate(even, four)).to.be(true);
|
||||
expect(evaluate(first, one)).to.be(true);
|
||||
expect(evaluate(last, four)).to.be(true);
|
||||
});
|
||||
|
||||
it('evaluates to false if feature id doesn\'t match', function() {
|
||||
expect(evaluate(odd, two)).to.be(false);
|
||||
expect(evaluate(odd, four)).to.be(false);
|
||||
expect(evaluate(even, one)).to.be(false);
|
||||
expect(evaluate(even, three)).to.be(false);
|
||||
expect(evaluate(first, two)).to.be(false);
|
||||
expect(evaluate(first, three)).to.be(false);
|
||||
expect(evaluate(first, four)).to.be(false);
|
||||
expect(evaluate(last, one)).to.be(false);
|
||||
expect(evaluate(last, two)).to.be(false);
|
||||
expect(evaluate(last, three)).to.be(false);
|
||||
expect(evaluate(none, one)).to.be(false);
|
||||
expect(evaluate(none, two)).to.be(false);
|
||||
expect(evaluate(none, three)).to.be(false);
|
||||
expect(evaluate(none, four)).to.be(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('geometryType()', function() {
|
||||
|
||||
var point = new ol.Feature({
|
||||
geom: new ol.geom.Point([0, 0])
|
||||
});
|
||||
|
||||
var line = new ol.Feature({
|
||||
geom: new ol.geom.LineString([[180, -90], [-180, 90]])
|
||||
});
|
||||
|
||||
var poly = new ol.Feature({
|
||||
geom: new ol.geom.Polygon([[
|
||||
[180, -90], [0, -90], [0, 0], [180, 0], [180, -90]
|
||||
]])
|
||||
});
|
||||
|
||||
var isPoint = parse('geometryType("point")');
|
||||
var isLine = parse('geometryType("linestring")');
|
||||
var isPoly = parse('geometryType("polygon")');
|
||||
var pointOrPoly = parse('geometryType("point") || geometryType("polygon")');
|
||||
|
||||
it('distinguishes point features', function() {
|
||||
expect(evaluate(isPoint, point)).to.be(true);
|
||||
expect(evaluate(isPoint, line)).to.be(false);
|
||||
expect(evaluate(isPoint, poly)).to.be(false);
|
||||
});
|
||||
|
||||
it('distinguishes line features', function() {
|
||||
expect(evaluate(isLine, point)).to.be(false);
|
||||
expect(evaluate(isLine, line)).to.be(true);
|
||||
expect(evaluate(isLine, poly)).to.be(false);
|
||||
});
|
||||
|
||||
it('distinguishes polygon features', function() {
|
||||
expect(evaluate(isPoly, point)).to.be(false);
|
||||
expect(evaluate(isPoly, line)).to.be(false);
|
||||
expect(evaluate(isPoly, poly)).to.be(true);
|
||||
});
|
||||
|
||||
it('can be composed in a logical expression', function() {
|
||||
expect(evaluate(pointOrPoly, point)).to.be(true);
|
||||
expect(evaluate(pointOrPoly, line)).to.be(false);
|
||||
expect(evaluate(pointOrPoly, poly)).to.be(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('like()', function() {
|
||||
|
||||
var one = new ol.Feature({foo: 'bar'});
|
||||
var two = new ol.Feature({foo: 'baz'});
|
||||
var three = new ol.Feature({foo: 'foo'});
|
||||
|
||||
var like = parse('like(foo, "ba")');
|
||||
|
||||
it('First and second feature match, third does not', function() {
|
||||
expect(evaluate(like, one), true);
|
||||
expect(evaluate(like, two), true);
|
||||
expect(evaluate(like, three), false);
|
||||
});
|
||||
|
||||
var uclike = parse('like(foo, "BA")');
|
||||
it('Matchcase is true by default', function() {
|
||||
expect(evaluate(uclike, one), false);
|
||||
expect(evaluate(uclike, two), false);
|
||||
expect(evaluate(uclike, three), false);
|
||||
});
|
||||
|
||||
var ilike = parse('like(foo, "BA", "*", ".", "!", false)');
|
||||
it('Using matchcase false, first two features match again', function() {
|
||||
expect(evaluate(ilike, one), true);
|
||||
expect(evaluate(ilike, two), true);
|
||||
expect(evaluate(uclike, three), false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('ieq()', function() {
|
||||
|
||||
var one = new ol.Feature({foo: 'Bar'});
|
||||
var two = new ol.Feature({bar: 'Foo'});
|
||||
|
||||
var ieq1 = parse('ieq(foo, "bar")');
|
||||
var ieq2 = parse('ieq("foo", bar)');
|
||||
|
||||
it('case-insensitive equality for an attribute', function() {
|
||||
expect(evaluate(ieq1, one), true);
|
||||
});
|
||||
|
||||
it('case-insensitive equality for an attribute as second argument',
|
||||
function() {
|
||||
expect(evaluate(ieq2, two), true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('ineq()', function() {
|
||||
|
||||
var one = new ol.Feature({foo: 'Bar'});
|
||||
var two = new ol.Feature({bar: 'Foo'});
|
||||
|
||||
var ieq1 = parse('ineq(foo, "bar")');
|
||||
var ieq2 = parse('ineq("foo", bar)');
|
||||
|
||||
it('case-insensitive non-equality for an attribute', function() {
|
||||
expect(evaluate(ieq1, one), false);
|
||||
});
|
||||
|
||||
it('case-insensitive non-equality for an attribute as second argument',
|
||||
function() {
|
||||
expect(evaluate(ieq2, two), false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('renderIntent()', function() {
|
||||
|
||||
var feature = new ol.Feature();
|
||||
feature.setRenderIntent('foo');
|
||||
|
||||
var isFoo = parse('renderIntent("foo")');
|
||||
var isBar = parse('renderIntent("bar")');
|
||||
|
||||
it('True when renderIntent matches', function() {
|
||||
expect(evaluate(isFoo, feature), true);
|
||||
});
|
||||
|
||||
it('False when renderIntent does not match', function() {
|
||||
expect(evaluate(isBar, feature), false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('ol.expr.register()', function() {
|
||||
|
||||
var spy;
|
||||
beforeEach(function() {
|
||||
spy = sinon.spy();
|
||||
});
|
||||
|
||||
it('registers custom functions in ol.expr.lib', function() {
|
||||
ol.expr.register('someFunc', spy);
|
||||
expect(ol.expr.lib.someFunc).to.be(spy);
|
||||
});
|
||||
|
||||
it('allows custom functions to be called', function() {
|
||||
ol.expr.register('myFunc', spy);
|
||||
var expr = ol.expr.parse('myFunc(42)');
|
||||
expr.evaluate(null, ol.expr.lib);
|
||||
expect(spy.calledOnce);
|
||||
expect(spy.calledWithExactly(42));
|
||||
});
|
||||
|
||||
it('allows custom functions to be called with identifiers', function() {
|
||||
ol.expr.register('myFunc', spy);
|
||||
var expr = ol.expr.parse('myFunc(foo, 42)');
|
||||
expr.evaluate({foo: 'bar'}, ol.expr.lib);
|
||||
expect(spy.calledOnce).to.be(true);
|
||||
expect(spy.calledWithExactly('bar', 42)).to.be(true);
|
||||
});
|
||||
|
||||
it('allows custom functions to be called with custom this obj', function() {
|
||||
ol.expr.register('myFunc', spy);
|
||||
var expr = ol.expr.parse('myFunc(foo, 42)');
|
||||
var that = {};
|
||||
expr.evaluate({foo: 'bar'}, ol.expr.lib, that);
|
||||
expect(spy.calledOnce).to.be(true);
|
||||
expect(spy.calledWithExactly('bar', 42)).to.be(true);
|
||||
expect(spy.calledOn(that)).to.be(true);
|
||||
});
|
||||
|
||||
it('allows overriding existing ol.expr.lib functions', function() {
|
||||
var orig = ol.expr.lib.extent;
|
||||
expect(orig).not.to.be(spy);
|
||||
ol.expr.register('extent', spy);
|
||||
expect(ol.expr.lib.extent).to.be(spy);
|
||||
ol.expr.lib.extent = orig;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.expr');
|
||||
goog.require('ol.expr.Call');
|
||||
goog.require('ol.expr.Comparison');
|
||||
goog.require('ol.expr.Expression');
|
||||
goog.require('ol.expr.Identifier');
|
||||
goog.require('ol.expr.Literal');
|
||||
goog.require('ol.expr.Logical');
|
||||
goog.require('ol.expr.Math');
|
||||
goog.require('ol.expr.Member');
|
||||
goog.require('ol.expr.Not');
|
||||
goog.require('ol.expr.TokenType');
|
||||
goog.require('ol.expr.UnexpectedToken');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
638
old/test/spec/ol/expr/expressions.test.js
Normal file
638
old/test/spec/ol/expr/expressions.test.js
Normal file
@@ -0,0 +1,638 @@
|
||||
goog.provide('ol.test.expression.Expression');
|
||||
|
||||
|
||||
describe('ol.expr.Call', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
it('creates a new expression', function() {
|
||||
var expr = new ol.expr.Call(
|
||||
new ol.expr.Identifier('sqrt'),
|
||||
[new ol.expr.Literal(42)]);
|
||||
expect(expr).to.be.a(ol.expr.Expression);
|
||||
expect(expr).to.be.a(ol.expr.Call);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#evaluate()', function() {
|
||||
var fns = {
|
||||
sqrt: function(value) {
|
||||
return Math.sqrt(value);
|
||||
},
|
||||
strConcat: function() {
|
||||
return Array.prototype.join.call(arguments, '');
|
||||
},
|
||||
discouraged: function() {
|
||||
return this.message;
|
||||
}
|
||||
};
|
||||
|
||||
it('calls method on scope with literal args', function() {
|
||||
var expr = new ol.expr.Call(
|
||||
new ol.expr.Identifier('sqrt'),
|
||||
[new ol.expr.Literal(42)]);
|
||||
expect(expr.evaluate(fns)).to.be(Math.sqrt(42));
|
||||
});
|
||||
|
||||
it('accepts a separate scope for functions', function() {
|
||||
var expr = new ol.expr.Call(
|
||||
new ol.expr.Identifier('sqrt'),
|
||||
[new ol.expr.Identifier('foo')]);
|
||||
expect(expr.evaluate({foo: 42}, fns)).to.be(Math.sqrt(42));
|
||||
});
|
||||
|
||||
it('accepts multiple expression arguments', function() {
|
||||
var expr = new ol.expr.Call(
|
||||
new ol.expr.Identifier('strConcat'),
|
||||
[
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(' comes after '),
|
||||
new ol.expr.Math(
|
||||
ol.expr.MathOp.SUBTRACT,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(1))
|
||||
]);
|
||||
expect(expr.evaluate({foo: 42}, fns)).to.be('42 comes after 41');
|
||||
});
|
||||
|
||||
it('accepts optional this arg', function() {
|
||||
var expr = new ol.expr.Call(
|
||||
new ol.expr.Identifier('discouraged'), []);
|
||||
|
||||
var thisArg = {
|
||||
message: 'avoid this'
|
||||
};
|
||||
|
||||
expect(expr.evaluate(fns, null, thisArg)).to.be('avoid this');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var callee = new ol.expr.Identifier('sqrt');
|
||||
var args = [new ol.expr.Literal(42)];
|
||||
var expr = new ol.expr.Call(callee, args);
|
||||
|
||||
describe('#getArgs()', function() {
|
||||
it('gets the callee expression', function() {
|
||||
expect(expr.getArgs()).to.be(args);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCallee()', function() {
|
||||
it('gets the callee expression', function() {
|
||||
expect(expr.getCallee()).to.be(callee);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('ol.expr.Comparison', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
it('creates a new expression', function() {
|
||||
var expr = new ol.expr.Comparison(
|
||||
ol.expr.ComparisonOp.EQ,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(42));
|
||||
expect(expr).to.be.a(ol.expr.Expression);
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#evaluate()', function() {
|
||||
it('compares with ==', function() {
|
||||
var expr = new ol.expr.Comparison(
|
||||
ol.expr.ComparisonOp.EQ,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(42));
|
||||
|
||||
expect(expr.evaluate({foo: 42})).to.be(true);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(true);
|
||||
expect(expr.evaluate({foo: true})).to.be(false);
|
||||
expect(expr.evaluate({bar: true})).to.be(false);
|
||||
});
|
||||
|
||||
it('compares with !=', function() {
|
||||
var expr = new ol.expr.Comparison(
|
||||
ol.expr.ComparisonOp.NEQ,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(42));
|
||||
|
||||
expect(expr.evaluate({foo: 42})).to.be(false);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(false);
|
||||
expect(expr.evaluate({foo: true})).to.be(true);
|
||||
expect(expr.evaluate({bar: true})).to.be(true);
|
||||
});
|
||||
|
||||
it('compares with ===', function() {
|
||||
var expr = new ol.expr.Comparison(
|
||||
ol.expr.ComparisonOp.STRICT_EQ,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(42));
|
||||
|
||||
expect(expr.evaluate({foo: 42})).to.be(true);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(false);
|
||||
expect(expr.evaluate({foo: true})).to.be(false);
|
||||
expect(expr.evaluate({bar: true})).to.be(false);
|
||||
});
|
||||
|
||||
it('compares with !==', function() {
|
||||
var expr = new ol.expr.Comparison(
|
||||
ol.expr.ComparisonOp.STRICT_NEQ,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(42));
|
||||
|
||||
expect(expr.evaluate({foo: 42})).to.be(false);
|
||||
expect(expr.evaluate({foo: '42'})).to.be(true);
|
||||
expect(expr.evaluate({foo: true})).to.be(true);
|
||||
expect(expr.evaluate({bar: true})).to.be(true);
|
||||
});
|
||||
|
||||
it('compares with >', function() {
|
||||
var expr = new ol.expr.Comparison(
|
||||
ol.expr.ComparisonOp.GT,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(42));
|
||||
|
||||
expect(expr.evaluate({foo: 42})).to.be(false);
|
||||
expect(expr.evaluate({foo: 41})).to.be(false);
|
||||
expect(expr.evaluate({foo: 43})).to.be(true);
|
||||
});
|
||||
|
||||
it('compares with <', function() {
|
||||
var expr = new ol.expr.Comparison(
|
||||
ol.expr.ComparisonOp.LT,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(42));
|
||||
|
||||
expect(expr.evaluate({foo: 42})).to.be(false);
|
||||
expect(expr.evaluate({foo: 41})).to.be(true);
|
||||
expect(expr.evaluate({foo: 43})).to.be(false);
|
||||
});
|
||||
|
||||
it('compares with >=', function() {
|
||||
var expr = new ol.expr.Comparison(
|
||||
ol.expr.ComparisonOp.GTE,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(42));
|
||||
|
||||
expect(expr.evaluate({foo: 42})).to.be(true);
|
||||
expect(expr.evaluate({foo: 41})).to.be(false);
|
||||
expect(expr.evaluate({foo: 43})).to.be(true);
|
||||
});
|
||||
|
||||
it('compares with <=', function() {
|
||||
var expr = new ol.expr.Comparison(
|
||||
ol.expr.ComparisonOp.LTE,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(42));
|
||||
|
||||
expect(expr.evaluate({foo: 42})).to.be(true);
|
||||
expect(expr.evaluate({foo: 41})).to.be(true);
|
||||
expect(expr.evaluate({foo: 43})).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isValidOp()', function() {
|
||||
it('determines if a string is a valid operator', function() {
|
||||
expect(ol.expr.Comparison.isValidOp('<')).to.be(true);
|
||||
expect(ol.expr.Comparison.isValidOp('<')).to.be(true);
|
||||
expect(ol.expr.Comparison.isValidOp('<=')).to.be(true);
|
||||
expect(ol.expr.Comparison.isValidOp('<=')).to.be(true);
|
||||
expect(ol.expr.Comparison.isValidOp('==')).to.be(true);
|
||||
expect(ol.expr.Comparison.isValidOp('!=')).to.be(true);
|
||||
expect(ol.expr.Comparison.isValidOp('===')).to.be(true);
|
||||
expect(ol.expr.Comparison.isValidOp('!==')).to.be(true);
|
||||
|
||||
expect(ol.expr.Comparison.isValidOp('')).to.be(false);
|
||||
expect(ol.expr.Comparison.isValidOp('+')).to.be(false);
|
||||
expect(ol.expr.Comparison.isValidOp('-')).to.be(false);
|
||||
expect(ol.expr.Comparison.isValidOp('&&')).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
var op = ol.expr.ComparisonOp.LTE;
|
||||
var left = new ol.expr.Identifier('foo');
|
||||
var right = new ol.expr.Literal(42);
|
||||
var expr = new ol.expr.Comparison(op, left, right);
|
||||
|
||||
describe('#getOperator()', function() {
|
||||
it('gets the operator', function() {
|
||||
expect(expr.getOperator()).to.be(op);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getLeft()', function() {
|
||||
it('gets the left expression', function() {
|
||||
expect(expr.getLeft()).to.be(left);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getRight()', function() {
|
||||
it('gets the right expression', function() {
|
||||
expect(expr.getRight()).to.be(right);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('ol.expr.Identifier', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
it('creates a new expression', function() {
|
||||
var expr = new ol.expr.Identifier('foo');
|
||||
expect(expr).to.be.a(ol.expr.Expression);
|
||||
expect(expr).to.be.a(ol.expr.Identifier);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#evaluate()', function() {
|
||||
it('returns a number from the scope', function() {
|
||||
var expr = new ol.expr.Identifier('foo');
|
||||
expect(expr.evaluate({foo: 42})).to.be(42);
|
||||
});
|
||||
|
||||
it('returns a string from the scope', function() {
|
||||
var expr = new ol.expr.Identifier('foo');
|
||||
expect(expr.evaluate({foo: 'chicken'})).to.be('chicken');
|
||||
});
|
||||
|
||||
it('returns a boolean from the scope', function() {
|
||||
var expr = new ol.expr.Identifier('bar');
|
||||
expect(expr.evaluate({bar: false})).to.be(false);
|
||||
expect(expr.evaluate({bar: true})).to.be(true);
|
||||
});
|
||||
|
||||
it('returns a null from the scope', function() {
|
||||
var expr = new ol.expr.Identifier('nada');
|
||||
expect(expr.evaluate({nada: null})).to.be(null);
|
||||
});
|
||||
|
||||
it('works for unicode identifiers', function() {
|
||||
var expr = new ol.expr.Identifier('\u03c0');
|
||||
expect(expr.evaluate({'\u03c0': Math.PI})).to.be(Math.PI);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getName()', function() {
|
||||
var expr = new ol.expr.Identifier('asdf');
|
||||
expect(expr.getName()).to.be('asdf');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('ol.expr.Literal', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
it('creates a new expression', function() {
|
||||
var expr = new ol.expr.Literal(true);
|
||||
expect(expr).to.be.a(ol.expr.Expression);
|
||||
expect(expr).to.be.a(ol.expr.Literal);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#evaluate()', function() {
|
||||
it('works for numeric literal', function() {
|
||||
var expr = new ol.expr.Literal(42e-11);
|
||||
expect(expr.evaluate()).to.be(4.2e-10);
|
||||
});
|
||||
|
||||
it('works for string literal', function() {
|
||||
var expr = new ol.expr.Literal('asdf');
|
||||
expect(expr.evaluate()).to.be('asdf');
|
||||
});
|
||||
|
||||
it('works for boolean literal', function() {
|
||||
var expr = new ol.expr.Literal(true);
|
||||
expect(expr.evaluate()).to.be(true);
|
||||
});
|
||||
|
||||
it('works for null literal', function() {
|
||||
var expr = new ol.expr.Literal(null);
|
||||
expect(expr.evaluate()).to.be(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getValue()', function() {
|
||||
var expr = new ol.expr.Literal('asdf');
|
||||
expect(expr.getValue()).to.be('asdf');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('ol.expr.Logical', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
it('creates a new expression', function() {
|
||||
var expr = new ol.expr.Logical(
|
||||
ol.expr.LogicalOp.OR,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Identifier('bar'));
|
||||
expect(expr).to.be.a(ol.expr.Expression);
|
||||
expect(expr).to.be.a(ol.expr.Logical);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#evaluate()', function() {
|
||||
it('applies || to resolved identifiers', function() {
|
||||
var expr = new ol.expr.Logical(
|
||||
ol.expr.LogicalOp.OR,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Identifier('bar'));
|
||||
|
||||
expect(expr.evaluate({foo: true, bar: true})).to.be(true);
|
||||
expect(expr.evaluate({foo: true, bar: false})).to.be(true);
|
||||
expect(expr.evaluate({foo: false, bar: true})).to.be(true);
|
||||
expect(expr.evaluate({foo: false, bar: false})).to.be(false);
|
||||
});
|
||||
|
||||
it('applies && to resolved identifiers', function() {
|
||||
var expr = new ol.expr.Logical(
|
||||
ol.expr.LogicalOp.AND,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Identifier('bar'));
|
||||
|
||||
expect(expr.evaluate({foo: true, bar: true})).to.be(true);
|
||||
expect(expr.evaluate({foo: true, bar: false})).to.be(false);
|
||||
expect(expr.evaluate({foo: false, bar: true})).to.be(false);
|
||||
expect(expr.evaluate({foo: false, bar: false})).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isValidOp()', function() {
|
||||
it('determines if a string is a valid operator', function() {
|
||||
expect(ol.expr.Logical.isValidOp('||')).to.be(true);
|
||||
expect(ol.expr.Logical.isValidOp('&&')).to.be(true);
|
||||
|
||||
expect(ol.expr.Logical.isValidOp('')).to.be(false);
|
||||
expect(ol.expr.Logical.isValidOp('+')).to.be(false);
|
||||
expect(ol.expr.Logical.isValidOp('<')).to.be(false);
|
||||
expect(ol.expr.Logical.isValidOp('|')).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
var op = ol.expr.LogicalOp.AND;
|
||||
var left = new ol.expr.Identifier('foo');
|
||||
var right = new ol.expr.Literal(false);
|
||||
var expr = new ol.expr.Logical(op, left, right);
|
||||
|
||||
describe('#getOperator()', function() {
|
||||
it('gets the operator', function() {
|
||||
expect(expr.getOperator()).to.be(op);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getLeft()', function() {
|
||||
it('gets the left expression', function() {
|
||||
expect(expr.getLeft()).to.be(left);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getRight()', function() {
|
||||
it('gets the right expression', function() {
|
||||
expect(expr.getRight()).to.be(right);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('ol.expr.Math', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
it('creates a new expression', function() {
|
||||
var expr = new ol.expr.Math(
|
||||
ol.expr.MathOp.ADD,
|
||||
new ol.expr.Literal(40),
|
||||
new ol.expr.Literal(2));
|
||||
expect(expr).to.be.a(ol.expr.Expression);
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#evaluate()', function() {
|
||||
it('does + with numeric literal', function() {
|
||||
var expr = new ol.expr.Math(
|
||||
ol.expr.MathOp.ADD,
|
||||
new ol.expr.Literal(40),
|
||||
new ol.expr.Literal(2));
|
||||
|
||||
expect(expr.evaluate()).to.be(42);
|
||||
});
|
||||
|
||||
it('does + with string literal (note: subject to change)', function() {
|
||||
var expr = new ol.expr.Math(
|
||||
ol.expr.MathOp.ADD,
|
||||
new ol.expr.Literal('foo'),
|
||||
new ol.expr.Literal('bar'));
|
||||
|
||||
expect(expr.evaluate()).to.be('foobar');
|
||||
});
|
||||
|
||||
it('does + with identifiers', function() {
|
||||
var expr = new ol.expr.Math(
|
||||
ol.expr.MathOp.ADD,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Identifier('bar'));
|
||||
|
||||
expect(expr.evaluate({foo: 40, bar: 2})).to.be(42);
|
||||
});
|
||||
|
||||
it('does - with identifiers', function() {
|
||||
var expr = new ol.expr.Math(
|
||||
ol.expr.MathOp.SUBTRACT,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(2));
|
||||
|
||||
expect(expr.evaluate({foo: 40})).to.be(38);
|
||||
});
|
||||
|
||||
it('casts to number with - (note: this may throw later)', function() {
|
||||
var expr = new ol.expr.Math(
|
||||
ol.expr.MathOp.SUBTRACT,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(2));
|
||||
|
||||
expect(expr.evaluate({foo: '40'})).to.be(38);
|
||||
});
|
||||
|
||||
it('does * with identifiers', function() {
|
||||
var expr = new ol.expr.Math(
|
||||
ol.expr.MathOp.MULTIPLY,
|
||||
new ol.expr.Literal(2),
|
||||
new ol.expr.Identifier('foo'));
|
||||
|
||||
expect(expr.evaluate({foo: 21})).to.be(42);
|
||||
});
|
||||
|
||||
it('casts to number with * (note: this may throw later)', function() {
|
||||
var expr = new ol.expr.Math(
|
||||
ol.expr.MathOp.MULTIPLY,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(2));
|
||||
|
||||
expect(expr.evaluate({foo: '21'})).to.be(42);
|
||||
});
|
||||
|
||||
it('does % with identifiers', function() {
|
||||
var expr = new ol.expr.Math(
|
||||
ol.expr.MathOp.MOD,
|
||||
new ol.expr.Literal(97),
|
||||
new ol.expr.Identifier('foo'));
|
||||
|
||||
expect(expr.evaluate({foo: 55})).to.be(42);
|
||||
});
|
||||
|
||||
it('casts to number with % (note: this may throw later)', function() {
|
||||
var expr = new ol.expr.Math(
|
||||
ol.expr.MathOp.MOD,
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Literal(100));
|
||||
|
||||
expect(expr.evaluate({foo: '150'})).to.be(50);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isValidOp()', function() {
|
||||
it('determines if a string is a valid operator', function() {
|
||||
expect(ol.expr.Math.isValidOp('+')).to.be(true);
|
||||
expect(ol.expr.Math.isValidOp('-')).to.be(true);
|
||||
expect(ol.expr.Math.isValidOp('*')).to.be(true);
|
||||
expect(ol.expr.Math.isValidOp('/')).to.be(true);
|
||||
expect(ol.expr.Math.isValidOp('%')).to.be(true);
|
||||
|
||||
expect(ol.expr.Math.isValidOp('')).to.be(false);
|
||||
expect(ol.expr.Math.isValidOp('|')).to.be(false);
|
||||
expect(ol.expr.Math.isValidOp('&')).to.be(false);
|
||||
expect(ol.expr.Math.isValidOp('<')).to.be(false);
|
||||
expect(ol.expr.Math.isValidOp('||')).to.be(false);
|
||||
expect(ol.expr.Math.isValidOp('.')).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
var op = ol.expr.MathOp.MOD;
|
||||
var left = new ol.expr.Identifier('foo');
|
||||
var right = new ol.expr.Literal(20);
|
||||
var expr = new ol.expr.Math(op, left, right);
|
||||
|
||||
describe('#getOperator()', function() {
|
||||
it('gets the operator', function() {
|
||||
expect(expr.getOperator()).to.be(op);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getLeft()', function() {
|
||||
it('gets the left expression', function() {
|
||||
expect(expr.getLeft()).to.be(left);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getRight()', function() {
|
||||
it('gets the right expression', function() {
|
||||
expect(expr.getRight()).to.be(right);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('ol.expr.Member', function() {
|
||||
describe('constructor', function() {
|
||||
it('creates a new expression', function() {
|
||||
var expr = new ol.expr.Member(
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Identifier('bar'));
|
||||
|
||||
expect(expr).to.be.a(ol.expr.Expression);
|
||||
expect(expr).to.be.a(ol.expr.Member);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#evaluate()', function() {
|
||||
it('accesses an object property', function() {
|
||||
|
||||
var expr = new ol.expr.Member(
|
||||
new ol.expr.Identifier('foo'),
|
||||
new ol.expr.Identifier('bar'));
|
||||
|
||||
var scope = {foo: {bar: 42}};
|
||||
expect(expr.evaluate(scope)).to.be(42);
|
||||
});
|
||||
});
|
||||
|
||||
var object = new ol.expr.Identifier('foo');
|
||||
var property = new ol.expr.Identifier('bar');
|
||||
var expr = new ol.expr.Member(object, property);
|
||||
|
||||
describe('#getObject()', function() {
|
||||
expect(expr.getObject()).to.be(object);
|
||||
});
|
||||
|
||||
describe('#getProperty()', function() {
|
||||
expect(expr.getProperty()).to.be(property);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('ol.expr.Not', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
it('creates a new expression', function() {
|
||||
var expr = new ol.expr.Not(
|
||||
new ol.expr.Literal(true));
|
||||
expect(expr).to.be.a(ol.expr.Expression);
|
||||
expect(expr).to.be.a(ol.expr.Not);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#evaluate()', function() {
|
||||
it('returns the logical complement', function() {
|
||||
var expr = new ol.expr.Not(new ol.expr.Literal(true));
|
||||
expect(expr.evaluate()).to.be(false);
|
||||
|
||||
expr = new ol.expr.Not(new ol.expr.Literal(false));
|
||||
expect(expr.evaluate()).to.be(true);
|
||||
});
|
||||
|
||||
it('negates a truthy string', function() {
|
||||
var expr = new ol.expr.Not(new ol.expr.Literal('asdf'));
|
||||
expect(expr.evaluate()).to.be(false);
|
||||
});
|
||||
|
||||
it('negates a falsy string', function() {
|
||||
var expr = new ol.expr.Not(new ol.expr.Literal(''));
|
||||
expect(expr.evaluate()).to.be(true);
|
||||
});
|
||||
|
||||
it('negates a truthy number', function() {
|
||||
var expr = new ol.expr.Not(new ol.expr.Literal(42));
|
||||
expect(expr.evaluate()).to.be(false);
|
||||
});
|
||||
|
||||
it('negates a falsy number', function() {
|
||||
var expr = new ol.expr.Not(new ol.expr.Literal(NaN));
|
||||
expect(expr.evaluate()).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getArgument()', function() {
|
||||
var argument = new ol.expr.Literal(true);
|
||||
var expr = new ol.expr.Not(argument);
|
||||
expect(expr.getArgument()).to.be(argument);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
goog.require('ol.expr.Call');
|
||||
goog.require('ol.expr.Comparison');
|
||||
goog.require('ol.expr.ComparisonOp');
|
||||
goog.require('ol.expr.Expression');
|
||||
goog.require('ol.expr.Identifier');
|
||||
goog.require('ol.expr.Literal');
|
||||
goog.require('ol.expr.Logical');
|
||||
goog.require('ol.expr.LogicalOp');
|
||||
goog.require('ol.expr.Math');
|
||||
goog.require('ol.expr.MathOp');
|
||||
goog.require('ol.expr.Member');
|
||||
goog.require('ol.expr.Not');
|
||||
509
old/test/spec/ol/expr/lexer.test.js
Normal file
509
old/test/spec/ol/expr/lexer.test.js
Normal file
@@ -0,0 +1,509 @@
|
||||
goog.provide('ol.test.expression.Lexer');
|
||||
|
||||
describe('ol.expr.Lexer', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
it('creates a new lexer', function() {
|
||||
var lexer = new ol.expr.Lexer('foo');
|
||||
expect(lexer).to.be.a(ol.expr.Lexer);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#next()', function() {
|
||||
|
||||
it('returns one token at a time', function() {
|
||||
var source = 'foo === "bar"';
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
|
||||
// scan first token
|
||||
var token = lexer.next();
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
expect(token.value).to.be('foo');
|
||||
|
||||
// scan second token
|
||||
token = lexer.next();
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
expect(token.value).to.be('===');
|
||||
|
||||
// scan third token
|
||||
token = lexer.next();
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
expect(token.value).to.be('bar');
|
||||
|
||||
// scan again
|
||||
token = lexer.next();
|
||||
expect(token.type).to.be(ol.expr.TokenType.EOF);
|
||||
|
||||
// and again
|
||||
token = lexer.next();
|
||||
expect(token.type).to.be(ol.expr.TokenType.EOF);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#peek()', function() {
|
||||
|
||||
var lexer;
|
||||
beforeEach(function() {
|
||||
lexer = new ol.expr.Lexer('foo > 42 && bar == "chicken"');
|
||||
});
|
||||
|
||||
it('looks ahead without consuming token', function() {
|
||||
var token = lexer.peek();
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
expect(token.value).to.be('foo');
|
||||
|
||||
token = lexer.next();
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
expect(token.value).to.be('foo');
|
||||
});
|
||||
|
||||
it('works after a couple scans', function() {
|
||||
var token = lexer.next();
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
expect(token.value).to.be('foo');
|
||||
|
||||
token = lexer.next();
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
expect(token.value).to.be('>');
|
||||
|
||||
token = lexer.peek();
|
||||
expect(token.type).to.be(ol.expr.TokenType.NUMERIC_LITERAL);
|
||||
expect(token.value).to.be(42);
|
||||
|
||||
token = lexer.next();
|
||||
expect(token.type).to.be(ol.expr.TokenType.NUMERIC_LITERAL);
|
||||
expect(token.value).to.be(42);
|
||||
});
|
||||
|
||||
it('returns the same thing when called multiple times', function() {
|
||||
var token = lexer.peek();
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
expect(token.value).to.be('foo');
|
||||
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
token = lexer.peek();
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
expect(token.value).to.be('foo');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('#scanIdentifier_()', function() {
|
||||
|
||||
function scan(source, part) {
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
var token = lexer.scanIdentifier_(lexer.getCurrentCharCode_());
|
||||
if (!part) {
|
||||
expect(token.index).to.be(0);
|
||||
expect(lexer.peek().type).to.be(ol.expr.TokenType.EOF);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
it('works for short identifiers', function() {
|
||||
var token = scan('a');
|
||||
expect(token.value).to.be('a');
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
});
|
||||
|
||||
it('works for longer identifiers', function() {
|
||||
var token = scan('foo');
|
||||
expect(token.value).to.be('foo');
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
});
|
||||
|
||||
it('works for $ anywhere', function() {
|
||||
var token = scan('$foo$bar$');
|
||||
expect(token.value).to.be('$foo$bar$');
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
});
|
||||
|
||||
it('works for _ anywhere', function() {
|
||||
var token = scan('_foo_bar_');
|
||||
expect(token.value).to.be('_foo_bar_');
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
});
|
||||
|
||||
it('works for keywords', function() {
|
||||
var token = scan('delete');
|
||||
expect(token.value).to.be('delete');
|
||||
expect(token.type).to.be(ol.expr.TokenType.KEYWORD);
|
||||
});
|
||||
|
||||
it('works for null', function() {
|
||||
var token = scan('null');
|
||||
expect(token.value).to.be('null');
|
||||
expect(token.type).to.be(ol.expr.TokenType.NULL_LITERAL);
|
||||
});
|
||||
|
||||
it('works for boolean true', function() {
|
||||
var token = scan('true');
|
||||
expect(token.value).to.be('true');
|
||||
expect(token.type).to.be(ol.expr.TokenType.BOOLEAN_LITERAL);
|
||||
});
|
||||
|
||||
it('works for boolean false', function() {
|
||||
var token = scan('false');
|
||||
expect(token.value).to.be('false');
|
||||
expect(token.type).to.be(ol.expr.TokenType.BOOLEAN_LITERAL);
|
||||
});
|
||||
|
||||
it('works with unicode escape sequences', function() {
|
||||
var token = scan('\u006f\u006c\u0033');
|
||||
expect(token.value).to.be('ol3');
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
});
|
||||
|
||||
it('works with hex escape sequences', function() {
|
||||
var token = scan('\x6f\x6c\x33');
|
||||
expect(token.value).to.be('ol3');
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
});
|
||||
|
||||
it('throws for identifiers starting with a number', function() {
|
||||
expect(function() {
|
||||
scan('4foo');
|
||||
}).throwException();
|
||||
});
|
||||
|
||||
it('throws for identifiers starting with a punctuation char', function() {
|
||||
expect(function() {
|
||||
scan('!foo');
|
||||
}).throwException();
|
||||
});
|
||||
|
||||
it('only scans valid identifier part', function() {
|
||||
var token = scan('foo>bar', true);
|
||||
expect(token.value).to.be('foo');
|
||||
expect(token.type).to.be(ol.expr.TokenType.IDENTIFIER);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#scanNumericLiteral_()', function() {
|
||||
|
||||
function scan(source) {
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
var token = lexer.scanNumericLiteral_(lexer.getCurrentCharCode_());
|
||||
expect(token.index).to.be(0);
|
||||
expect(lexer.peek().type).to.be(ol.expr.TokenType.EOF);
|
||||
return token;
|
||||
}
|
||||
|
||||
it('works for integers', function() {
|
||||
var token = scan('123');
|
||||
expect(token.value).to.be(123);
|
||||
expect(token.type).to.be(ol.expr.TokenType.NUMERIC_LITERAL);
|
||||
});
|
||||
|
||||
it('throws for bogus integer', function() {
|
||||
expect(function() {
|
||||
scan('123z');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('z');
|
||||
expect(token.index).to.be(3);
|
||||
});
|
||||
});
|
||||
|
||||
it('works for float', function() {
|
||||
var token = scan('123.456');
|
||||
expect(token.value).to.be(123.456);
|
||||
expect(token.type).to.be(ol.expr.TokenType.NUMERIC_LITERAL);
|
||||
});
|
||||
|
||||
it('throws for bogus float', function() {
|
||||
expect(function() {
|
||||
scan('123.4x4');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('x');
|
||||
expect(token.index).to.be(5);
|
||||
});
|
||||
});
|
||||
|
||||
it('works with exponent', function() {
|
||||
var token = scan('1.234e5');
|
||||
expect(token.value).to.be(1.234e5);
|
||||
expect(token.type).to.be(ol.expr.TokenType.NUMERIC_LITERAL);
|
||||
});
|
||||
|
||||
it('works with explicit positive exponent', function() {
|
||||
var token = scan('1.234e+5');
|
||||
expect(token.value).to.be(1.234e5);
|
||||
expect(token.type).to.be(ol.expr.TokenType.NUMERIC_LITERAL);
|
||||
});
|
||||
|
||||
it('works with negative exponent', function() {
|
||||
var token = scan('1.234e-5');
|
||||
expect(token.value).to.be(1.234e-5);
|
||||
expect(token.type).to.be(ol.expr.TokenType.NUMERIC_LITERAL);
|
||||
});
|
||||
|
||||
it('throws for bogus float', function() {
|
||||
expect(function() {
|
||||
scan('1.234eo4');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('o');
|
||||
expect(token.index).to.be(6);
|
||||
});
|
||||
});
|
||||
|
||||
it('works with octals', function() {
|
||||
var token = scan('02322');
|
||||
expect(token.value).to.be(1234);
|
||||
expect(token.type).to.be(ol.expr.TokenType.NUMERIC_LITERAL);
|
||||
});
|
||||
|
||||
it('throws for bogus octal', function() {
|
||||
// note that this is more strict than most es5 engines
|
||||
expect(function() {
|
||||
scan('02392');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('9');
|
||||
expect(token.index).to.be(3);
|
||||
});
|
||||
});
|
||||
|
||||
it('works with hex', function() {
|
||||
var token = scan('0x4d2');
|
||||
expect(token.value).to.be(1234);
|
||||
expect(token.type).to.be(ol.expr.TokenType.NUMERIC_LITERAL);
|
||||
});
|
||||
|
||||
it('throws for bogus hex', function() {
|
||||
// note that this is more strict than most es5 engines
|
||||
expect(function() {
|
||||
scan('0x4G');
|
||||
}).throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.value).to.be('G');
|
||||
expect(token.index).to.be(3);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#scanPunctuator_()', function() {
|
||||
|
||||
function scan(source) {
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
var token = lexer.scanPunctuator_(lexer.getCurrentCharCode_());
|
||||
expect(token.index).to.be(0);
|
||||
expect(lexer.peek().type).to.be(ol.expr.TokenType.EOF);
|
||||
return token;
|
||||
}
|
||||
|
||||
it('works for dot', function() {
|
||||
var token = scan('.');
|
||||
expect(token.value).to.be('.');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for bang', function() {
|
||||
var token = scan('!');
|
||||
expect(token.value).to.be('!');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for double equal', function() {
|
||||
var token = scan('==');
|
||||
expect(token.value).to.be('==');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for triple equal', function() {
|
||||
var token = scan('===');
|
||||
expect(token.value).to.be('===');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for not double equal', function() {
|
||||
var token = scan('!=');
|
||||
expect(token.value).to.be('!=');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for not triple equal', function() {
|
||||
var token = scan('!==');
|
||||
expect(token.value).to.be('!==');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for logical or', function() {
|
||||
var token = scan('||');
|
||||
expect(token.value).to.be('||');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for logical and', function() {
|
||||
var token = scan('&&');
|
||||
expect(token.value).to.be('&&');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for plus', function() {
|
||||
var token = scan('+');
|
||||
expect(token.value).to.be('+');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for minus', function() {
|
||||
var token = scan('-');
|
||||
expect(token.value).to.be('-');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for star', function() {
|
||||
var token = scan('*');
|
||||
expect(token.value).to.be('*');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for slash', function() {
|
||||
var token = scan('/');
|
||||
expect(token.value).to.be('/');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
it('works for percent', function() {
|
||||
var token = scan('%');
|
||||
expect(token.value).to.be('%');
|
||||
expect(token.type).to.be(ol.expr.TokenType.PUNCTUATOR);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#scanStringLiteral_()', function() {
|
||||
|
||||
function scan(source) {
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
var token = lexer.scanStringLiteral_(lexer.getCurrentCharCode_());
|
||||
expect(token.index).to.be(0);
|
||||
expect(lexer.peek().type).to.be(ol.expr.TokenType.EOF);
|
||||
return token;
|
||||
}
|
||||
|
||||
it('parses double quoted string', function() {
|
||||
var token = scan('"my string"');
|
||||
expect(token.value).to.be('my string');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses double quoted string with internal single quotes', function() {
|
||||
var token = scan('"my \'quoted\' string"');
|
||||
expect(token.value).to.be('my \'quoted\' string');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses double quoted string with escaped double quotes', function() {
|
||||
var token = scan('"my \\"quoted\\" string"');
|
||||
expect(token.value).to.be('my "quoted" string');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses double quoted string with escaped backslash', function() {
|
||||
var token = scan('"my \\\ string"');
|
||||
expect(token.value).to.be('my \ string');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses double quoted string with unicode escape sequences', function() {
|
||||
var token = scan('"\u006f\u006c\u0033"');
|
||||
expect(token.value).to.be('ol3');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses double quoted string with hex escape sequences', function() {
|
||||
var token = scan('"\x6f\x6c\x33"');
|
||||
expect(token.value).to.be('ol3');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses double quoted string with tab', function() {
|
||||
var token = scan('"a\ttab"');
|
||||
expect(token.value).to.be('a\ttab');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('throws on unterminated double quote', function() {
|
||||
expect(function() {
|
||||
scan('"never \'ending\' string');
|
||||
}).to.throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.type).to.be(ol.expr.TokenType.EOF);
|
||||
expect(token.index).to.be(22);
|
||||
});
|
||||
});
|
||||
|
||||
it('parses single quoted string', function() {
|
||||
var token = scan('\'my string\'');
|
||||
expect(token.value).to.be('my string');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses single quoted string with internal double quotes', function() {
|
||||
var token = scan('\'my "quoted" string\'');
|
||||
expect(token.value).to.be('my "quoted" string');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses single quoted string with escaped single quotes', function() {
|
||||
var token = scan('\'my \\\'quoted\\\' string\'');
|
||||
expect(token.value).to.be('my \'quoted\' string');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses single quoted string with escaped backslash', function() {
|
||||
var token = scan('\'my \\\ string\'');
|
||||
expect(token.value).to.be('my \ string');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses single quoted string with unicode escape sequences', function() {
|
||||
var token = scan('\'\u006f\u006c\u0033\'');
|
||||
expect(token.value).to.be('ol3');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses single quoted string with hex escape sequences', function() {
|
||||
var token = scan('\'\x6f\x6c\x33\'');
|
||||
expect(token.value).to.be('ol3');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('parses single quoted string with tab', function() {
|
||||
var token = scan('\'a\ttab\'');
|
||||
expect(token.value).to.be('a\ttab');
|
||||
expect(token.type).to.be(ol.expr.TokenType.STRING_LITERAL);
|
||||
});
|
||||
|
||||
it('throws on unterminated single quote', function() {
|
||||
expect(function() {
|
||||
scan('\'never "ending" string');
|
||||
}).to.throwException(function(err) {
|
||||
expect(err).to.be.an(ol.expr.UnexpectedToken);
|
||||
var token = err.token;
|
||||
expect(token.type).to.be(ol.expr.TokenType.EOF);
|
||||
expect(token.index).to.be(22);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
goog.require('ol.expr.Lexer');
|
||||
goog.require('ol.expr.TokenType');
|
||||
goog.require('ol.expr.UnexpectedToken');
|
||||
275
old/test/spec/ol/expr/parser.test.js
Normal file
275
old/test/spec/ol/expr/parser.test.js
Normal file
@@ -0,0 +1,275 @@
|
||||
goog.provide('ol.test.expression.Parser');
|
||||
|
||||
describe('ol.expr.Parser', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
it('creates a new expression parser', function() {
|
||||
var parser = new ol.expr.Parser();
|
||||
expect(parser).to.be.a(ol.expr.Parser);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#parseArguments_()', function() {
|
||||
|
||||
function parse(source) {
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
var parser = new ol.expr.Parser();
|
||||
var expr = parser.parseArguments_(lexer);
|
||||
expect(lexer.peek().type).to.be(ol.expr.TokenType.EOF);
|
||||
return expr;
|
||||
}
|
||||
|
||||
it('parses comma separated expressions in parens', function() {
|
||||
var args = parse('(1/3, "foo", true)');
|
||||
expect(args).length(3);
|
||||
|
||||
expect(args[0]).to.be.a(ol.expr.Math);
|
||||
expect(args[0].evaluate()).to.be(1 / 3);
|
||||
|
||||
expect(args[1]).to.be.a(ol.expr.Literal);
|
||||
expect(args[1].evaluate()).to.be('foo');
|
||||
|
||||
expect(args[2]).to.be.a(ol.expr.Literal);
|
||||
expect(args[2].evaluate()).to.be(true);
|
||||
});
|
||||
|
||||
it('throws on invalid arg expression', function() {
|
||||
expect(function() {
|
||||
parse('(6e)');
|
||||
}).throwException();
|
||||
});
|
||||
|
||||
it('throws on unterminated args', function() {
|
||||
expect(function() {
|
||||
parse('("foo", 42, )');
|
||||
}).throwException();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#parseBinaryExpression_()', function() {
|
||||
|
||||
function parse(source) {
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
var parser = new ol.expr.Parser();
|
||||
var expr = parser.parseBinaryExpression_(lexer);
|
||||
expect(lexer.peek().type).to.be(ol.expr.TokenType.EOF);
|
||||
return expr;
|
||||
}
|
||||
|
||||
it('works with multiplicitave operators', function() {
|
||||
var expr = parse('4 * 1e4');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate()).to.be(40000);
|
||||
|
||||
expect(parse('10/3').evaluate()).to.be(10 / 3);
|
||||
});
|
||||
|
||||
it('works with additive operators', function() {
|
||||
var expr = parse('4 +1e4');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate()).to.be(10004);
|
||||
|
||||
expect(parse('10-3').evaluate()).to.be(7);
|
||||
});
|
||||
|
||||
it('works with relational operators', function() {
|
||||
var expr = parse('4 < 1e4');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate()).to.be(true);
|
||||
|
||||
expect(parse('10<3').evaluate()).to.be(false);
|
||||
expect(parse('10 <= "10"').evaluate()).to.be(true);
|
||||
expect(parse('10 > "10"').evaluate()).to.be(false);
|
||||
expect(parse('10 >= 9').evaluate()).to.be(true);
|
||||
});
|
||||
|
||||
it('works with equality operators', function() {
|
||||
var expr = parse('4 == 1e4');
|
||||
expect(expr).to.be.a(ol.expr.Comparison);
|
||||
expect(expr.evaluate()).to.be(false);
|
||||
|
||||
expect(parse('10!=3').evaluate()).to.be(true);
|
||||
expect(parse('10 == "10"').evaluate()).to.be(true);
|
||||
expect(parse('10 === "10"').evaluate()).to.be(false);
|
||||
expect(parse('10 !== "10"').evaluate()).to.be(true);
|
||||
});
|
||||
|
||||
it('works with binary logical operators', function() {
|
||||
var expr = parse('true && false');
|
||||
expect(expr).to.be.a(ol.expr.Logical);
|
||||
expect(expr.evaluate()).to.be(false);
|
||||
|
||||
expect(parse('false||true').evaluate()).to.be(true);
|
||||
expect(parse('false || false').evaluate()).to.be(false);
|
||||
expect(parse('true &&true').evaluate()).to.be(true);
|
||||
});
|
||||
|
||||
it('throws for invalid binary expression', function() {
|
||||
expect(function() {
|
||||
parse('4 * / 2');
|
||||
}).throwException();
|
||||
|
||||
expect(function() {
|
||||
parse('4 < / 2');
|
||||
}).throwException();
|
||||
|
||||
expect(function() {
|
||||
parse('4 * && 2');
|
||||
}).throwException();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#parseGroupExpression_()', function() {
|
||||
|
||||
function parse(source) {
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
var parser = new ol.expr.Parser();
|
||||
var expr = parser.parseGroupExpression_(lexer);
|
||||
expect(lexer.peek().type).to.be(ol.expr.TokenType.EOF);
|
||||
return expr;
|
||||
}
|
||||
|
||||
it('parses grouped expressions', function() {
|
||||
var expr = parse('(3 * (foo + 2))');
|
||||
expect(expr).to.be.a(ol.expr.Math);
|
||||
expect(expr.evaluate({foo: 3})).to.be(15);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#parseLeftHandSideExpression_()', function() {
|
||||
|
||||
function parse(source) {
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
var parser = new ol.expr.Parser();
|
||||
var expr = parser.parseLeftHandSideExpression_(lexer);
|
||||
expect(lexer.peek().type).to.be(ol.expr.TokenType.EOF);
|
||||
return expr;
|
||||
}
|
||||
|
||||
it('parses member expressions', function() {
|
||||
var expr = parse('foo.bar.bam');
|
||||
expect(expr).to.be.a(ol.expr.Member);
|
||||
});
|
||||
|
||||
it('throws on invalid member expression', function() {
|
||||
expect(function() {
|
||||
parse('foo.4');
|
||||
}).throwException();
|
||||
});
|
||||
|
||||
it('parses call expressions', function() {
|
||||
var expr = parse('foo(bar)');
|
||||
expect(expr).to.be.a(ol.expr.Call);
|
||||
var fns = {
|
||||
foo: function(arg) {
|
||||
expect(arguments).length(1);
|
||||
expect(arg).to.be('chicken');
|
||||
return 'got ' + arg;
|
||||
}
|
||||
};
|
||||
var scope = {
|
||||
bar: 'chicken'
|
||||
};
|
||||
expect(expr.evaluate(scope, fns)).to.be('got chicken');
|
||||
});
|
||||
|
||||
it('throws on invalid call expression', function() {
|
||||
expect(function() {
|
||||
parse('foo(*)');
|
||||
}).throwException();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('#parsePrimaryExpression_()', function() {
|
||||
|
||||
function parse(source) {
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
var parser = new ol.expr.Parser();
|
||||
var expr = parser.parsePrimaryExpression_(lexer);
|
||||
expect(lexer.peek().type).to.be(ol.expr.TokenType.EOF);
|
||||
return expr;
|
||||
}
|
||||
|
||||
it('parses string literal', function() {
|
||||
var expr = parse('"foo"');
|
||||
expect(expr).to.be.a(ol.expr.Literal);
|
||||
expect(expr.evaluate()).to.be('foo');
|
||||
});
|
||||
|
||||
it('parses numeric literal', function() {
|
||||
var expr = parse('.42e2');
|
||||
expect(expr).to.be.a(ol.expr.Literal);
|
||||
expect(expr.evaluate()).to.be(42);
|
||||
});
|
||||
|
||||
it('parses boolean literal', function() {
|
||||
var expr = parse('.42e2');
|
||||
expect(expr).to.be.a(ol.expr.Literal);
|
||||
expect(expr.evaluate()).to.be(42);
|
||||
});
|
||||
|
||||
it('parses null literal', function() {
|
||||
var expr = parse('null');
|
||||
expect(expr).to.be.a(ol.expr.Literal);
|
||||
expect(expr.evaluate()).to.be(null);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#parseUnaryExpression_()', function() {
|
||||
|
||||
function parse(source) {
|
||||
var lexer = new ol.expr.Lexer(source);
|
||||
var parser = new ol.expr.Parser();
|
||||
var expr = parser.parseUnaryExpression_(lexer);
|
||||
expect(lexer.peek().type).to.be(ol.expr.TokenType.EOF);
|
||||
return expr;
|
||||
}
|
||||
|
||||
it('parses logical not', function() {
|
||||
var expr = parse('!foo');
|
||||
expect(expr).to.be.a(ol.expr.Not);
|
||||
expect(expr.evaluate({foo: true})).to.be(false);
|
||||
});
|
||||
|
||||
it('works with string literal', function() {
|
||||
var expr = parse('!"foo"');
|
||||
expect(expr).to.be.a(ol.expr.Not);
|
||||
expect(expr.evaluate()).to.be(false);
|
||||
});
|
||||
|
||||
it('works with empty string', function() {
|
||||
var expr = parse('!""');
|
||||
expect(expr).to.be.a(ol.expr.Not);
|
||||
expect(expr.evaluate()).to.be(true);
|
||||
});
|
||||
|
||||
it('works with null', function() {
|
||||
var expr = parse('!null');
|
||||
expect(expr).to.be.a(ol.expr.Not);
|
||||
expect(expr.evaluate()).to.be(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
goog.require('ol.expr.Expression');
|
||||
goog.require('ol.expr.Call');
|
||||
goog.require('ol.expr.Comparison');
|
||||
goog.require('ol.expr.Lexer');
|
||||
goog.require('ol.expr.Literal');
|
||||
goog.require('ol.expr.Logical');
|
||||
goog.require('ol.expr.Math');
|
||||
goog.require('ol.expr.Member');
|
||||
goog.require('ol.expr.Not');
|
||||
goog.require('ol.expr.Parser');
|
||||
goog.require('ol.expr.TokenType');
|
||||
Reference in New Issue
Block a user