@airtasker/form-schema-compiler
Version:
a form schema compiler
185 lines (176 loc) • 6.46 kB
JavaScript
;
var _const = require("../const");
var _evaluate = require("./evaluate");
var _evaluate2 = _interopRequireDefault(_evaluate);
var _parsers = require("../parsers");
var _Environment = require("./Environment");
var _Environment2 = _interopRequireDefault(_Environment);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
var evaluateWithStringExpression = function evaluateWithStringExpression(str, env) {
var ast = (0, _parsers.parseExpressionString)(str);
return (0, _evaluate2["default"])(ast, env);
};
describe("interpreter evaluate()", function () {
var env;
beforeEach(function () {
env = new _Environment2["default"]();
});
[{
title: "should support binary expression",
given: "1 + 1",
expect: 2
}, {
title: "should support complicate equation",
given: "1 + 2 * 3 - +(4 + 5) * (2 / 2) - -2",
expect: 0
}, {
title: "should support complicate expression",
given: "(true and true or (false or true)) is (false or true) is (false or false)",
expect: false
}, {
title: "should support + unary expression",
given: "-1",
expect: -1
}, {
title: "should support - unary expression",
given: "1",
expect: 1
}, {
title: "should support not unary expression",
given: "not true",
expect: false
}, {
title: "should support string",
given: '"hello"',
expect: "hello"
}, {
title: "should support numeric",
given: "1",
expect: 1
}, {
title: "should support boolean",
given: "true",
expect: true
}, {
title: "should support null",
given: "null",
expect: null
}, {
title: "should support regex",
given: '"a" match /A/i',
expect: true
}].forEach(function (data) {
it(data.title, function () {
expect(evaluateWithStringExpression(data.given, env)).toEqual(data.expect);
});
});
it("should support assign", function () {
expect(evaluateWithStringExpression("a = 1", env)).toBe(1);
expect(env.get("a")).toBe(1);
});
it("should support identity", function () {
env.get = jest.fn().mockReturnValue("bar");
expect(evaluateWithStringExpression("foo", env)).toBe("bar");
expect(env.get).toHaveBeenCalledWith("foo");
});
it("should support components", function () {
env.evaluateComponents = jest.fn().mockReturnValue("returnValue");
expect((0, _evaluate2["default"])({
type: _const.TYPES.Components,
components: [],
a: 1,
b: 2
}, env)).toBe("returnValue");
expect(env.evaluateComponents).toHaveBeenCalledWith({
components: [],
a: 1,
b: 2
});
});
it("should support function call", function () {
env.get = jest.fn().mockReturnValueOnce(function (str) {
return str;
}).mockReturnValueOnce("world");
expect(evaluateWithStringExpression('whatAmISay("world")', env)).toBe("world");
expect(env.get).toHaveBeenCalled();
});
it("should support Object", function () {
expect(evaluateWithStringExpression("{}", env)).toEqual({});
env.set("c", "d");
expect(evaluateWithStringExpression('{"a": 1, "b": {}, c: 1 + 2, "e": "hello"}', env)).toEqual({
a: 1,
b: {},
d: 3,
e: "hello"
});
});
it("should support Array", function () {
expect(evaluateWithStringExpression("[]", env)).toEqual([]);
env.set("b", "c");
expect(evaluateWithStringExpression('["a", b, 3, {}, 1 + 1]', env)).toEqual(["a", "c", 3, {}, 2]);
});
it("should support MemberObject", function () {
env.set("a", [0]);
expect(evaluateWithStringExpression("a[0]", env)).toBe(0);
env.set("a", {
a: 1
});
expect(evaluateWithStringExpression("a['a']", env)).toBe(1);
});
it("should support TemplateLiteral", function () {
env.set("world", "world");
env.set("foo", function () {
return "bar";
});
expect(evaluateWithStringExpression("`hello {world}, {`foo`}{foo()}`", env)).toBe("hello world, foobar");
});
it("should support program", function () {
env.set("foobar", jest.fn());
env.set("hello", jest.fn());
expect(evaluateWithStringExpression('foobar(); hello({"a":3}); 1+3', env)).toBe(4);
expect(env.get("foobar")).toHaveBeenCalled();
expect(env.get("hello")).toHaveBeenCalledWith({
a: 3
});
});
describe("if statement", function () {
it("should support if consequent", function () {
env.set("test", jest.fn().mockReturnValue(true));
env.set("consequent", jest.fn().mockReturnValue('foobar'));
env.set("alternate", jest.fn());
expect(evaluateWithStringExpression('if test() then consequent() else alternate()', env)).toBe('foobar');
expect(env.get("test")).toHaveBeenCalled();
expect(env.get("consequent")).toHaveBeenCalled();
expect(env.get("alternate")).not.toHaveBeenCalled();
});
it("should support if alternate", function () {
env.set("test", jest.fn().mockReturnValue(false));
env.set("consequent", jest.fn());
env.set("alternate", jest.fn().mockReturnValue('foobar'));
expect(evaluateWithStringExpression('if test() then consequent() else alternate()', env)).toBe('foobar');
expect(env.get("test")).toHaveBeenCalled();
expect(env.get("consequent")).not.toHaveBeenCalled();
expect(env.get("alternate")).toHaveBeenCalled();
});
it("should support chained if", function () {
env.set("test", jest.fn().mockReturnValue(false));
env.set("test2", jest.fn().mockReturnValue(false));
env.set("consequent", jest.fn());
env.set("alternate", jest.fn().mockReturnValue('foobar'));
expect(evaluateWithStringExpression('if test() then consequent() else if test2() else alternate()', env)).toBe('foobar');
expect(env.get("test")).toHaveBeenCalled();
expect(env.get("test2")).toHaveBeenCalled();
expect(env.get("consequent")).not.toHaveBeenCalled();
expect(env.get("alternate")).toHaveBeenCalled();
});
it("should support if with blocks", function () {
env.set("test", jest.fn().mockReturnValue(true));
env.set("call1", jest.fn());
env.set("call2", jest.fn());
expect(evaluateWithStringExpression('if test() then {call1(); call2();\n 123+110}', env)).toBe(233);
expect(env.get("test")).toHaveBeenCalled();
expect(env.get("call1")).toHaveBeenCalled();
expect(env.get("call2")).toHaveBeenCalled();
});
});
});