/* Copyright 2020 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { loadScript } from "../../src/display/display_utils.js"; const sandboxBundleSrc = "../../build/generic/build/pdf.sandbox.js"; describe("Scripting", function () { let sandbox, send_queue, test_id, ref; function getId() { const id = `${ref++}R`; return id; } function myeval(code) { const key = (test_id++).toString(); return sandbox.eval(code, key).then(() => { const result = send_queue.get(key).result; send_queue.delete(key); return result; }); } beforeAll(function (done) { test_id = 0; ref = 1; send_queue = new Map(); window.dispatchEvent = event => { if (event.detail.command) { send_queue.set(event.detail.command, event.detail); } else if (send_queue.has(event.detail.id)) { const prev = send_queue.get(event.detail.id); Object.assign(prev, event.detail); } else { send_queue.set(event.detail.id, event.detail); } }; const promise = loadScript(sandboxBundleSrc).then(() => { return window.pdfjsSandbox.QuickJSSandbox(); }); sandbox = { createSandbox(data) { promise.then(sbx => sbx.create(data)); }, dispatchEventInSandbox(data) { return promise.then(sbx => sbx.dispatchEvent(data)); }, nukeSandbox() { promise.then(sbx => sbx.nukeSandbox()); }, eval(code, key) { return promise.then(sbx => sbx.evalForTesting(code, key)); }, }; done(); }); afterAll(function () { sandbox.nukeSandbox(); sandbox = null; send_queue = null; }); describe("Sandbox", function () { it("should send a value, execute an action and get back a new value", function (done) { function compute(n) { let s = 0; for (let i = 0; i < n; i++) { s += i; } return s; } const number = 123; const expected = ((number - 1) * number) / 2; const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { Keystroke: [ `${compute.toString()}event.value = compute(parseInt(event.value));`, ], }, type: "text", }, ], }, calculationOrder: [], appInfo: { language: "en-US", platform: "Linux x86_64" }, dispatchEventName: "_dispatchMe", }; sandbox.createSandbox(data); sandbox .dispatchEventInSandbox({ id: refId, value: `${number}`, name: "Keystroke", willCommit: true, }) .then(() => { expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, valueAsString: expected, }); done(); }) .catch(done.fail); }); }); describe("Util", function () { beforeAll(function (done) { sandbox.createSandbox({ appInfo: { language: "en-US", platform: "Linux x86_64" }, objects: {}, calculationOrder: [], dispatchEventName: "_dispatchMe", }); done(); }); describe("printd", function () { it("should print a date according to a format", function (done) { const date = `new Date("Sun Apr 15 2007 03:14:15")`; Promise.all([ myeval(`util.printd(0, ${date})`).then(value => { expect(value).toEqual("D:20070415031415"); }), myeval(`util.printd(1, ${date})`).then(value => { expect(value).toEqual("2007.04.15 03:14:15"); }), myeval(`util.printd(2, ${date})`).then(value => { expect(value).toEqual("4/15/07 3:14:15 am"); }), myeval(`util.printd("mmmm mmm mm m", ${date})`).then(value => { expect(value).toEqual("April Apr 04 4"); }), myeval(`util.printd("dddd ddd dd d", ${date})`).then(value => { expect(value).toEqual("Sunday Sun 15 15"); }), ]).then(() => done()); }); }); describe("scand", function () { it("should parse a date according to a format", function (done) { const date = new Date("Sun Apr 15 2007 03:14:15"); Promise.all([ myeval(`util.scand(0, "D:20070415031415").toString()`).then(value => { expect(new Date(value)).toEqual(date); }), myeval(`util.scand(1, "2007.04.15 03:14:15").toString()`).then( value => { expect(new Date(value)).toEqual(date); } ), myeval(`util.scand(2, "4/15/07 3:14:15 am").toString()`).then( value => { expect(new Date(value)).toEqual(date); } ), ]).then(() => done()); }); }); describe("printf", function () { it("should print some data according to a format", function (done) { Promise.all([ myeval( `util.printf("Integer numbers: %d, %d,...", 1.234, 56.789)` ).then(value => { expect(value).toEqual("Integer numbers: 1, 56,..."); }), myeval(`util.printf("Hex numbers: %x, %x,...", 1234, 56789)`).then( value => { expect(value).toEqual("Hex numbers: 4D2, DDD5,..."); } ), myeval( `util.printf("Hex numbers with 0x: %#x, %#x,...", 1234, 56789)` ).then(value => { expect(value).toEqual("Hex numbers with 0x: 0x4D2, 0xDDD5,..."); }), myeval(`util.printf("Decimal number: %,0+.3f", 1234567.89123)`).then( value => { expect(value).toEqual("Decimal number: +1,234,567.891"); } ), myeval(`util.printf("Decimal number: %,0+8.3f", 1.234567)`).then( value => { expect(value).toEqual("Decimal number: + 1.235"); } ), ]).then(() => done()); }); it("should print a string with no argument", function (done) { myeval(`util.printf("hello world")`) .then(value => { expect(value).toEqual("hello world"); }) .then(() => done()); }); it("print a string with a percent", function (done) { myeval(`util.printf("%%s")`) .then(value => { expect(value).toEqual("%%s"); }) .then(() => done()); }); }); describe("printx", function () { it("should print some data according to a format", function (done) { myeval(`util.printx("9 (999) 999-9999", "aaa14159697489zzz")`) .then(value => { expect(value).toEqual("1 (415) 969-7489"); }) .then(() => done()); }); }); }); describe("Events", function () { it("should trigger an event and modify the source", function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { test: [`event.source.value = "123";`], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; sandbox.createSandbox(data); sandbox .dispatchEventInSandbox({ id: refId, value: "", name: "test", willCommit: true, }) .then(() => { expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "123", }); done(); }) .catch(done.fail); }); it("should trigger a Keystroke event and invalidate it", function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { Keystroke: [`event.rc = false;`], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; sandbox.createSandbox(data); sandbox .dispatchEventInSandbox({ id: refId, value: "hell", name: "Keystroke", willCommit: false, change: "o", selStart: 4, selEnd: 4, }) .then(() => { expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "hell", selRange: [4, 4], }); done(); }) .catch(done.fail); }); it("should trigger a Keystroke event and change it", function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { Keystroke: [`event.change = "a";`], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; sandbox.createSandbox(data); sandbox .dispatchEventInSandbox({ id: refId, value: "hell", name: "Keystroke", willCommit: false, change: "o", selStart: 4, selEnd: 4, }) .then(() => { expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "hella", }); done(); }) .catch(done.fail); }); it("should trigger an invalid commit Keystroke event", function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { test: [`event.rc = false;`], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; sandbox.createSandbox(data); sandbox .dispatchEventInSandbox({ id: refId, value: "", name: "test", willCommit: true, }) .then(() => { expect(send_queue.has(refId)).toEqual(false); done(); }) .catch(done.fail); }); it("should trigger a valid commit Keystroke event", function (done) { const refId1 = getId(); const refId2 = getId(); const data = { objects: { field1: [ { id: refId1, value: "", actions: { Validate: [`event.value = "world";`], }, type: "text", }, ], field2: [ { id: refId2, value: "", actions: { Calculate: [`event.value = "hello";`], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [refId2], dispatchEventName: "_dispatchMe", }; sandbox.createSandbox(data); sandbox .dispatchEventInSandbox({ id: refId1, value: "hello", name: "Keystroke", willCommit: true, }) .then(() => { expect(send_queue.has(refId1)).toEqual(true); expect(send_queue.get(refId1)).toEqual({ id: refId1, value: "world", valueAsString: "world", }); done(); }) .catch(done.fail); }); }); describe("Color", function () { beforeAll(function (done) { sandbox.createSandbox({ appInfo: { language: "en-US", platform: "Linux x86_64" }, objects: {}, calculationOrder: [], dispatchEventName: "_dispatchMe", }); done(); }); function round(color) { return [ color[0], ...color.slice(1).map(x => Math.round(x * 1000) / 1000), ]; } it("should convert RGB color for different color spaces", function (done) { Promise.all([ myeval(`color.convert(["RGB", 0.1, 0.2, 0.3], "T")`).then(value => { expect(round(value)).toEqual(["T"]); }), myeval(`color.convert(["RGB", 0.1, 0.2, 0.3], "G")`).then(value => { expect(round(value)).toEqual(["G", 0.181]); }), myeval(`color.convert(["RGB", 0.1, 0.2, 0.3], "RGB")`).then(value => { expect(round(value)).toEqual(["RGB", 0.1, 0.2, 0.3]); }), myeval(`color.convert(["RGB", 0.1, 0.2, 0.3], "CMYK")`).then(value => { expect(round(value)).toEqual(["CMYK", 0.9, 0.8, 0.7, 0.7]); }), ]).then(() => done()); }); it("should convert CMYK color for different color spaces", function (done) { Promise.all([ myeval(`color.convert(["CMYK", 0.1, 0.2, 0.3, 0.4], "T")`).then( value => { expect(round(value)).toEqual(["T"]); } ), myeval(`color.convert(["CMYK", 0.1, 0.2, 0.3, 0.4], "G")`).then( value => { expect(round(value)).toEqual(["G", 0.371]); } ), myeval(`color.convert(["CMYK", 0.1, 0.2, 0.3, 0.4], "RGB")`).then( value => { expect(round(value)).toEqual(["RGB", 0.5, 0.3, 0.4]); } ), myeval(`color.convert(["CMYK", 0.1, 0.2, 0.3, 0.4], "CMYK")`).then( value => { expect(round(value)).toEqual(["CMYK", 0.1, 0.2, 0.3, 0.4]); } ), ]).then(() => done()); }); it("should convert Gray color for different color spaces", function (done) { Promise.all([ myeval(`color.convert(["G", 0.1], "T")`).then(value => { expect(round(value)).toEqual(["T"]); }), myeval(`color.convert(["G", 0.1], "G")`).then(value => { expect(round(value)).toEqual(["G", 0.1]); }), myeval(`color.convert(["G", 0.1], "RGB")`).then(value => { expect(round(value)).toEqual(["RGB", 0.1, 0.1, 0.1]); }), myeval(`color.convert(["G", 0.1], "CMYK")`).then(value => { expect(round(value)).toEqual(["CMYK", 0, 0, 0, 0.9]); }), ]).then(() => done()); }); it("should convert Transparent color for different color spaces", function (done) { Promise.all([ myeval(`color.convert(["T"], "T")`).then(value => { expect(round(value)).toEqual(["T"]); }), myeval(`color.convert(["T"], "G")`).then(value => { expect(round(value)).toEqual(["G", 0]); }), myeval(`color.convert(["T"], "RGB")`).then(value => { expect(round(value)).toEqual(["RGB", 0, 0, 0]); }), myeval(`color.convert(["T"], "CMYK")`).then(value => { expect(round(value)).toEqual(["CMYK", 0, 0, 0, 1]); }), ]).then(() => done()); }); }); describe("App", function () { beforeAll(function (done) { sandbox.createSandbox({ appInfo: { language: "en-US", platform: "Linux x86_64" }, objects: {}, calculationOrder: [], dispatchEventName: "_dispatchMe", }); done(); }); it("should test language", function (done) { Promise.all([ myeval(`app.language`).then(value => { expect(value).toEqual("ENU"); }), myeval(`app.language = "hello"`).then(value => { expect(value).toEqual("app.language is read-only"); }), ]).then(() => done()); }); it("should test platform", function (done) { Promise.all([ myeval(`app.platform`).then(value => { expect(value).toEqual("UNIX"); }), myeval(`app.platform = "hello"`).then(value => { expect(value).toEqual("app.platform is read-only"); }), ]).then(() => done()); }); }); describe("AForm", function () { beforeAll(function (done) { sandbox.createSandbox({ appInfo: { language: "en-US", platform: "Linux x86_64" }, objects: {}, calculationOrder: [], dispatchEventName: "_dispatchMe", }); done(); }); describe("AFExtractNums", function () { it("should extract numbers", function (done) { Promise.all([ myeval(`AFExtractNums("123 456 789")`).then(value => { expect(value).toEqual(["123", "456", "789"]); }), myeval(`AFExtractNums("123.456")`).then(value => { expect(value).toEqual(["123", "456"]); }), myeval(`AFExtractNums("123")`).then(value => { expect(value).toEqual(["123"]); }), myeval(`AFExtractNums(".123")`).then(value => { expect(value).toEqual(["0", "123"]); }), myeval(`AFExtractNums(",123")`).then(value => { expect(value).toEqual(["0", "123"]); }), ]).then(() => done()); }); }); describe("AFMakeNumber", function () { it("should convert string to number", function (done) { Promise.all([ myeval(`AFMakeNumber("123.456")`).then(value => { expect(value).toEqual(123.456); }), myeval(`AFMakeNumber(123.456)`).then(value => { expect(value).toEqual(123.456); }), myeval(`AFMakeNumber("-123.456")`).then(value => { expect(value).toEqual(-123.456); }), myeval(`AFMakeNumber("-123,456")`).then(value => { expect(value).toEqual(-123.456); }), myeval(`AFMakeNumber("not a number")`).then(value => { expect(value).toEqual(null); }), ]).then(() => done()); }); }); describe("AFMakeArrayFromList", function () { it("should split a string into an array of strings", async function (done) { const value = await myeval( `AFMakeArrayFromList("aaaa, bbbbbbb,cc,ddd, e")` ); expect(value).toEqual(["aaaa", " bbbbbbb", "cc", "ddd", "e"]); done(); }); }); describe("AFNumber_format", function () { it("should format a number", async function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { test1: [ `AFNumber_Format(2, 0, 0, 0, "€", false);` + `event.source.value = event.value;`, ], test2: [ `AFNumber_Format(1, 3, 0, 0, "$", true);` + `event.source.value = event.value;`, ], test3: [ `AFNumber_Format(2, 0, 1, 0, "€", false);` + `event.source.value = event.value;`, ], test4: [ `AFNumber_Format(2, 0, 2, 0, "€", false);` + `event.source.value = event.value;`, ], test5: [ `AFNumber_Format(2, 0, 3, 0, "€", false);` + `event.source.value = event.value;`, ], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; try { sandbox.createSandbox(data); await sandbox.dispatchEventInSandbox({ id: refId, value: "123456.789", name: "test1", }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "123,456.79€", }); send_queue.delete(refId); await sandbox.dispatchEventInSandbox({ id: refId, value: "223456.789", name: "test2", }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "$223456,8", }); send_queue.delete(refId); await sandbox.dispatchEventInSandbox({ id: refId, value: "-323456.789", name: "test3", }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "323,456.79€", textColor: ["RGB", 1, 0, 0], }); send_queue.delete(refId); await sandbox.dispatchEventInSandbox({ id: refId, value: "-423456.789", name: "test4", }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "(423,456.79€)", }); send_queue.delete(refId); await sandbox.dispatchEventInSandbox({ id: refId, value: "-52345.678", name: "test5", }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "(52,345.68€)", textColor: ["RGB", 1, 0, 0], }); done(); } catch (_) { done.fail(); } }); }); describe("AFNumber_Keystroke", function () { it("should validate a number on a keystroke event", async function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { Validate: [ `AFNumber_Keystroke(null, 0, null, null, null, null);`, ], }, type: "text", name: "MyField", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; try { sandbox.createSandbox(data); await sandbox.dispatchEventInSandbox({ id: refId, value: "123456.789", name: "Keystroke", willCommit: true, }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "123456.789", valueAsString: "123456.789", }); done(); } catch (_) { done.fail(); } }); it("should not validate a number on a keystroke event", async function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { Validate: [ `AFNumber_Keystroke(null, 0, null, null, null, null);`, ], }, type: "text", name: "MyField", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; try { sandbox.createSandbox(data); await sandbox.dispatchEventInSandbox({ id: refId, value: "123s456.789", name: "Keystroke", willCommit: true, }); expect(send_queue.has("alert")).toEqual(true); expect(send_queue.get("alert")).toEqual({ command: "alert", value: "Invalid number in [ MyField ]", }); done(); } catch (_) { done.fail(); } }); }); describe("AFPercent_Format", function () { it("should format a percentage", async function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { test1: [ `AFPercent_Format(2, 1, false);` + `event.source.value = event.value;`, ], test2: [ `AFPercent_Format(2, 1, true);` + `event.source.value = event.value;`, ], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; try { sandbox.createSandbox(data); await sandbox.dispatchEventInSandbox({ id: refId, value: "0.456789", name: "test1", }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "45.68%", }); send_queue.delete(refId); await sandbox.dispatchEventInSandbox({ id: refId, value: "0.456789", name: "test2", }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "%45.68", }); done(); } catch (_) { done.fail(); } }); }); describe("AFDate_Format", function () { it("should format a date", async function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { test1: [`AFDate_Format(0);event.source.value = event.value;`], test2: [ `AFDate_Format(12);event.source.value = event.value;`, ], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; try { sandbox.createSandbox(data); await sandbox.dispatchEventInSandbox({ id: refId, value: "Sun Apr 15 2007 03:14:15", name: "test1", }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "4/15", }); send_queue.delete(refId); await sandbox.dispatchEventInSandbox({ id: refId, value: "Sun Apr 15 2007 03:14:15", name: "test2", }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "4/15/07 3:14 am", }); done(); } catch (_) { done.fail(); } }); }); describe("AFRange_Validate", function () { it("should validate a number in range [a, b]", async function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { Validate: [`AFRange_Validate(true, 123, true, 456);`], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; try { sandbox.createSandbox(data); await sandbox.dispatchEventInSandbox({ id: refId, value: "321", name: "Keystroke", willCommit: true, }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "321", valueAsString: "321", }); done(); } catch (_) { done.fail(); } }); it("should invalidate a number out of range [a, b]", async function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { Validate: [`AFRange_Validate(true, 123, true, 456);`], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; try { sandbox.createSandbox(data); await sandbox.dispatchEventInSandbox({ id: refId, value: "12", name: "Keystroke", willCommit: true, }); expect(send_queue.has("alert")).toEqual(true); expect(send_queue.get("alert")).toEqual({ command: "alert", value: "12 is not between 123 and 456", }); done(); } catch (_) { done.fail(); } }); }); describe("ASSimple_Calculate", function () { it("should compute the sum of several fields", async function (done) { const refIds = [0, 1, 2, 3].map(_ => getId()); const data = { objects: { field1: [ { id: refIds[0], value: "", actions: {}, type: "text", }, ], field2: [ { id: refIds[1], value: "", actions: {}, type: "text", }, ], field3: [ { id: refIds[2], value: "", actions: {}, type: "text", }, ], field4: [ { id: refIds[3], value: "", actions: { Calculate: [ `AFSimple_Calculate("SUM", ["field1", "field2", "field3"]);`, ], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [refIds[3]], dispatchEventName: "_dispatchMe", }; try { sandbox.createSandbox(data); await sandbox.dispatchEventInSandbox({ id: refIds[0], value: "1", name: "Keystroke", willCommit: true, }); expect(send_queue.has(refIds[3])).toEqual(true); expect(send_queue.get(refIds[3])).toEqual({ id: refIds[3], value: 1, valueAsString: 1, }); await sandbox.dispatchEventInSandbox({ id: refIds[1], value: "2", name: "Keystroke", willCommit: true, }); expect(send_queue.has(refIds[3])).toEqual(true); expect(send_queue.get(refIds[3])).toEqual({ id: refIds[3], value: 3, valueAsString: 3, }); await sandbox.dispatchEventInSandbox({ id: refIds[2], value: "3", name: "Keystroke", willCommit: true, }); expect(send_queue.has(refIds[3])).toEqual(true); expect(send_queue.get(refIds[3])).toEqual({ id: refIds[3], value: 6, valueAsString: 6, }); done(); } catch (_) { done.fail(); } }); }); describe("AFSpecial_KeystrokeEx", function () { it("should validate a phone number on a keystroke event", async function (done) { const refId = getId(); const data = { objects: { field: [ { id: refId, value: "", actions: { Keystroke: [`AFSpecial_KeystrokeEx("9AXO");`], }, type: "text", }, ], }, appInfo: { language: "en-US", platform: "Linux x86_64" }, calculationOrder: [], dispatchEventName: "_dispatchMe", }; try { sandbox.createSandbox(data); await sandbox.dispatchEventInSandbox({ id: refId, value: "", change: "3", name: "Keystroke", willCommit: false, selStart: 0, selEnd: 0, }); expect(send_queue.has(refId)).toEqual(false); await sandbox.dispatchEventInSandbox({ id: refId, value: "3", change: "F", name: "Keystroke", willCommit: false, selStart: 1, selEnd: 1, }); expect(send_queue.has(refId)).toEqual(false); await sandbox.dispatchEventInSandbox({ id: refId, value: "3F", change: "?", name: "Keystroke", willCommit: false, selStart: 2, selEnd: 2, }); expect(send_queue.has(refId)).toEqual(false); await sandbox.dispatchEventInSandbox({ id: refId, value: "3F?", change: "@", name: "Keystroke", willCommit: false, selStart: 3, selEnd: 3, }); expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, value: "3F?", selRange: [3, 3], }); done(); } catch (_) { done.fail(); } }); }); describe("eMailValidate", function () { it("should validate an e-mail address", function (done) { Promise.all([ myeval(`eMailValidate(123)`).then(value => { expect(value).toEqual(false); }), myeval(`eMailValidate("foo@bar.com")`).then(value => { expect(value).toEqual(true); }), myeval(`eMailValidate("foo bar")`).then(value => { expect(value).toEqual(false); }), ]).then(() => done()); }); }); }); });