@beezwax/fmbond
Version:
A bridge for sending/receiving data between FileMaker and the web viewer
894 lines (832 loc) • 27.3 kB
JavaScript
const rewire = require("rewire");
const jsdom = require("jsdom");
/* Setup */
const PROMISE_UUID = "4q5bt4y8-339c-44d3-96aj-50ee623oc6az";
const WEB_VIEWER = "wv";
const RELAY_SCRIPT = "FMBondRelay";
const createFMResponse = function (
promiseUUID = "",
scriptResult = "",
webViewerName = "wv",
code = "0",
message = "OK"
) {
return {
response: {
promiseUUID,
scriptResult,
webViewerName,
},
messages: [
{
code,
message,
},
],
};
};
// Because of the quirk with FMBond hoisting itself to the window level,
// we need to define the window scope before importing FMBond.
let FMBondForWindow, FMBond;
beforeAll(() => {
const { JSDOM } = jsdom;
const { window } = new JSDOM("<!DOCTYPE html>");
global.window = window;
global.document = window.document;
// First 'require' FMBond
FMBondForWindow = require("../FMBond");
// Second 'rewire' FMBond
FMBond = rewire("../FMBond");
fmbondWindow = FMBond.__set__("window", jest.fn());
});
afterAll(() => {
fmbondWindow();
});
/*
* ~~~~~~~~~~~~~~~~~~ TESTS ~~~~~~~~~~~~~~~~~~
*/
describe("FMBond call parameters", () => {
test("new keyword throws error", () => {
expect.assertions(1);
const formattedFMError = FMBond.__get__("formattedFMError");
const { NO_NEW_KEYWORD } = FMBond.__get__("FMBOND_ERROR_CODE");
const expectedError = formattedFMError(
NO_NEW_KEYWORD,
"Use of the new keyword is prohibited with FMBond"
);
expect(() => new FMBond()).toThrow(expectedError);
});
test("no parameters should return undefined", () => {
expect.assertions(1);
expect(FMBond()).not.toBeDefined();
});
test("non-string should return undefined", () => {
expect.assertions(1);
expect(FMBond({ test: "test" })).not.toBeDefined();
});
test("no-length string should return undefined", () => {
expect.assertions(1);
expect(FMBond("")).not.toBeDefined();
});
/* This test simulates a situation where the response from FileMaker is given to a web viewer
that does contain FMBond, however was not the original web viewer the call to FileMaker
came from. We purposefully throw here so that our FileMaker script knows that it failed. */
test("FMBond called with object with non-existent response.promiseUUID throws error", () => {
expect.assertions(1);
const formattedFMError = FMBond.__get__("formattedFMError");
const { INVALID_PARAMETER } = FMBond.__get__("FMBOND_ERROR_CODE");
const param = JSON.stringify(createFMResponse("non-existent-uuid-123"));
const expectedError = formattedFMError(
INVALID_PARAMETER,
"FMBond was called with an invalid a promiseUUID"
);
expect(() => FMBond(param)).toThrow(expectedError);
});
test("valid FMResponse should perform handleCallFromRelayScript", () => {
// setup
const spy = jest.fn();
const resetHandleCallFromRelayScript = FMBond.__set__(
"handleCallFromRelayScript",
spy
);
const resetCreateUUID = FMBond.__set__("createUUID", () => PROMISE_UUID);
const resetPerformScriptSafely = FMBond.__set__("performScriptSafely", () =>
Promise.resolve()
);
const responseObj = createFMResponse(PROMISE_UUID);
const responseStr = JSON.stringify(responseObj);
// test
expect.assertions(2);
FMBond.PerformScript("a");
FMBond(responseStr);
expect(spy).toHaveBeenCalledWith(responseObj);
expect(spy).toHaveBeenCalledTimes(1);
// cleanup
resetHandleCallFromRelayScript();
resetCreateUUID();
resetPerformScriptSafely();
});
test("valid FM Request should perform handleJSCallFromFM", () => {
// setup
const spy = jest.fn();
const resetHandleJSCallFromFM = FMBond.__set__("handleJSCallFromFM", spy);
const validJSRequestParams = [
["a"],
["a", 1, 2, 3],
["() => 'hey'"],
["(a,b) => a*b", 5, 10],
];
// test
expect.assertions(validJSRequestParams.length + 1);
validJSRequestParams.forEach((req) => {
const [jsFunc, ...rest] = req;
FMBond(jsFunc, ...rest);
expect(spy).toHaveBeenLastCalledWith(jsFunc, rest);
});
expect(spy).toHaveBeenCalledTimes(validJSRequestParams.length);
// cleanup
resetHandleJSCallFromFM();
});
});
describe("PerformScript", () => {
let resetCreateUUID, resetPerformScriptSafely;
beforeAll(() => {
resetCreateUUID = FMBond.__set__("createUUID", () => PROMISE_UUID);
resetPerformScriptSafely = FMBond.__set__("performScriptSafely", () =>
Promise.resolve()
);
});
afterAll(() => {
resetCreateUUID();
resetPerformScriptSafely();
});
beforeEach(() => {
FMBond.__get__("promiseMap").clear();
FMBond.SetWebViewerName("");
});
test("should return js-formatted script results as resolved promises", () => {
// setup
const promiseMap = FMBond.__get__("promiseMap");
const scriptResultTests = [
{
fromFM: "",
expectedPromiseResult: "",
toBe: "toBe",
},
{
fromFM: "1",
expectedPromiseResult: 1,
toBe: "toBe",
},
{
fromFM: "1.2",
expectedPromiseResult: 1.2,
toBe: "toBe",
},
{
fromFM: "test",
expectedPromiseResult: "test",
toBe: "toMatch",
},
{
fromFM: '[100,"200","abc"]',
expectedPromiseResult: [100, "200", "abc"],
toBe: "toMatchObject",
},
{
fromFM: '{"a": "b", "c":[1,2,3], "d": { "e": 1000, "f": ["g", "h"] }}',
expectedPromiseResult: {
a: "b",
c: [1, 2, 3],
d: { e: 1000, f: ["g", "h"] },
},
toBe: "toMatchObject",
},
];
// test
expect.assertions(scriptResultTests.length * 4);
scriptResultTests.forEach(async (test, idx) => {
const { fromFM, expectedPromiseResult, toBe } = test;
const responseStr = JSON.stringify(
createFMResponse(PROMISE_UUID, fromFM, WEB_VIEWER)
);
expect(FMBond.GetWebViewerName()).toMatch(idx === 0 ? "" : WEB_VIEWER);
expect(promiseMap.get(PROMISE_UUID)).not.toBeDefined();
const deferredPromise = FMBond.PerformScript("a");
expect(promiseMap.get(PROMISE_UUID)).toBeDefined();
FMBond(responseStr);
await deferredPromise;
expect(deferredPromise).resolves[toBe](expectedPromiseResult);
});
});
test("invalid script name should throw", async () => {
// setup
const { INVALID_PARAMETER } = FMBond.__get__("FMBOND_ERROR_CODE");
const formattedFMError = FMBond.__get__("formattedFMError");
const expectedResult = formattedFMError(
INVALID_PARAMETER,
"The script name parameter must be a valid string"
);
const invalidScriptNames = ["", { test: "hey" }, undefined, null];
// test
expect.assertions(invalidScriptNames.length);
invalidScriptNames.forEach((scriptName) => {
expect(() => FMBond.PerformScript(scriptName)).toThrow(expectedResult);
});
});
test("missing relay script name should throw", async () => {
// setup
const { INVALID_PARAMETER } = FMBond.__get__("FMBOND_ERROR_CODE");
const formattedFMError = FMBond.__get__("formattedFMError");
const expectedResult = formattedFMError(
INVALID_PARAMETER,
"The script name parameter must be a valid string"
);
const invalidScriptNames = ["", { test: "hey" }, undefined, null];
// test
expect.assertions(invalidScriptNames.length);
invalidScriptNames.forEach((scriptName) => {
expect(() => FMBond.PerformScript(scriptName)).toThrow(expectedResult);
});
});
describe("Options are handled correctly", () => {
test("timeouts throw", async () => {
// setup
const { TIMEOUT_HIT } = FMBond.__get__("FMBOND_ERROR_CODE");
const formattedFMError = FMBond.__get__("formattedFMError");
const expectedResult = formattedFMError(
TIMEOUT_HIT,
"Failed to resolve promise within 10ms."
);
// test
expect.assertions(1);
return expect(
FMBond.PerformScript("a", "", { timeout: 10 })
).rejects.toThrow(expectedResult);
});
test("ignore result option should resolve, even with timeout", () => {
expect.assertions(1);
return expect(
FMBond.PerformScript("a", "", { ignoreResult: true, timeout: 1 })
).resolves.not.toBeDefined();
});
test("valid callTypes", async () => {
// setup
validCallTypes = [
null,
"null",
undefined,
"undefined",
"",
0,
"0",
"continue",
1,
"1",
"halt",
2,
"2",
"exit",
3,
"3",
"resume",
4,
"4",
"pause",
5,
"5",
"interrupt",
];
// test - since there are two methods of sending callType, we test for all valid types * 2
expect.assertions(validCallTypes.length * 2);
const tests = validCallTypes.map(async (callType, idx) => {
const uuid1 = `uuid1-${idx}`;
const uuid2 = `uuid2-${idx}`;
let secondCall = false;
FMBond.__set__("createUUID", () => {
secondCall = !secondCall;
return secondCall ? uuid2 : uuid1;
});
// two methods of sending callType
const promise1 = FMBond.PerformScript("a", "", callType);
const promise2 = FMBond.PerformScript("a", "", { callType });
FMBond(JSON.stringify(createFMResponse(uuid1)));
FMBond(JSON.stringify(createFMResponse(uuid2)));
return Promise.all([
expect(promise1).resolves.toMatch(""),
expect(promise2).resolves.toMatch(""),
]);
});
const allRun = await Promise.all(tests);
// cleanup
FMBond.__set__("createUUID", () => PROMISE_UUID);
return allRun;
});
test("invalid callTypes", async () => {
// setup
const invalidCallTypes = [
"invalidString",
"999",
999,
{ callType: "invalid" },
{ callType: "999" },
{ callType: 999 },
{ callType: { callType: "invalid" } },
];
const { INVALID_PARAMETER } = FMBond.__get__("FMBOND_ERROR_CODE");
const formattedFMError = FMBond.__get__("formattedFMError");
const expectedResult = (myString) =>
formattedFMError(
INVALID_PARAMETER,
`${myString} is not a valid call type. Please use options 0 - 5`
);
// tests
expect.assertions(invalidCallTypes.length);
invalidCallTypes.forEach((callType) => {
let expectedCallType =
typeof callType === "object" ? callType.callType : callType;
const expected = expectedResult(`${expectedCallType}`.toLowerCase());
expect(() => FMBond.PerformScript("a", "", callType)).toThrow(expected);
});
});
});
});
describe("RegisterScript", () => {
test("invalid parameters", () => {
// setup
const { INVALID_PARAMETER } = FMBond.__get__("FMBOND_ERROR_CODE");
const formattedFMError = FMBond.__get__("formattedFMError");
const expectedError = formattedFMError(
INVALID_PARAMETER,
"Invalid plugin parameters: { exec, scriptName } are required plugin options."
);
const invalidParams = [
"",
"test",
{},
{ exec: "", scriptName: "test" },
{ exec: "test", scriptName: "" },
undefined,
null,
];
// test
expect.assertions(invalidParams.length);
invalidParams.forEach((param) => {
expect(() => FMBond.RegisterScript(param)).toThrow(expectedError);
});
});
test("registering a method that already exists should throw", () => {
// setup
const { INVALID_PARAMETER } = FMBond.__get__("FMBOND_ERROR_CODE");
const formattedFMError = FMBond.__get__("formattedFMError");
const expectedError = formattedFMError(
INVALID_PARAMETER,
"Unable to register PerformScript as this method already exists. Please use a different name."
);
// test
expect.assertions(1);
expect(() =>
FMBond.RegisterScript({ exec: "PerformScript", scriptName: "test" })
).toThrow(expectedError);
});
test("registering works normally", () => {
// setup
FMBond.SetWebViewerName("wv");
const spy = jest.fn(() => Promise.resolve());
const fileMakerParams = {
promiseUUID: PROMISE_UUID,
mode: "PERFORM_SCRIPT",
options: {
callType: "interrupt",
ignoreResult: false,
webViewerName: "wv",
},
script: {
name: "My FileMaker Script",
parameter: "my parameter",
},
};
const resetPerformScriptSafely = FMBond.__set__("performScriptSafely", spy);
const resetCreateUUID = FMBond.__set__("createUUID", () => PROMISE_UUID);
// test
expect.assertions(7);
expect(FMBond.Run).not.toBeDefined();
expect(
FMBond.RegisterScript({
exec: "Run",
scriptName: "My FileMaker Script",
throwIf: (res) => res === "NoCanDo!",
})
).toBe(FMBond);
expect(FMBond.Run).toBeDefined();
// test good result
const goodResult = FMBond.Run("my parameter", "interrupt");
expect(spy).toHaveBeenCalledWith(RELAY_SCRIPT, fileMakerParams, "5");
FMBond(JSON.stringify(createFMResponse(PROMISE_UUID, "YesWeCan!")));
expect(goodResult).resolves.toMatch("YesWeCan!");
// test result that throws
const thrownResult = FMBond.Run("my parameter", "interrupt");
expect(spy).toHaveBeenCalledWith(RELAY_SCRIPT, fileMakerParams, "5");
FMBond(JSON.stringify(createFMResponse(PROMISE_UUID, "NoCanDo!")));
expect(thrownResult).rejects.toMatch("NoCanDo!");
// cleanup
resetCreateUUID();
resetPerformScriptSafely();
FMBond.SetWebViewerName("");
});
});
describe("handleJSCallFromFM", () => {
test("valid parameters", async () => {
// setup
FMBond.SetRelayScriptName("r");
const performScriptSafelySpy = jest.fn();
const resetPerformScriptSafely = FMBond.__set__(
"performScriptSafely",
performScriptSafelySpy
);
// a valid parameter is a correctly-defined js function
const validJSRequestParams = [
{
request: ["Math.max", 1, 10],
expectedResult: 10,
},
{
request: ["(a) => a", '{ "object": "test" }'],
expectedResult: { object: "test" },
},
{
request: ["Math.min", 1, 10],
expectedResult: 1,
},
{
request: ["() => 'hey'"],
expectedResult: "hey",
},
{
request: ["(a,b) => { return `${a}_${b}`; }", "my", "milkshake"],
expectedResult: "my_milkshake",
},
{
request: [
"function(callback, param) { return callback(param); }",
"ƒ(param) => { return param.toUpperCase() }",
"milkshake",
],
expectedResult: "MILKSHAKE",
},
];
// test
expect.assertions(validJSRequestParams.length * 2);
validJSRequestParams.forEach((req) => {
const { request, expectedResult } = req;
const [jsFunc, ...rest] = request;
const result = FMBond(jsFunc, ...rest);
const param = {
mode: "RETURN_JAVASCRIPT_RESULT",
result: {
messages: [
{
code: "0",
message: "OK",
},
],
response: {
result: expectedResult,
},
},
};
expect(performScriptSafelySpy).toHaveBeenLastCalledWith("r", param, "5");
expect(result).not.toBeDefined();
});
// cleanup
FMBond.SetRelayScriptName("");
resetPerformScriptSafely();
});
test("invalid parameters", async () => {
// setup
FMBond.SetRelayScriptName("r");
const performScriptSafelySpy = jest.fn();
const resetPerformScriptSafely = FMBond.__set__(
"performScriptSafely",
performScriptSafelySpy
);
// an invalid parameter is any incorrectly-defined js function
const invalidJSRequestParams = [
["a"],
["a(", 1, 2, 3],
["( => 'hey'"],
["function(a,b) => a*b", 5, 10],
["function(a,b)", 5, 10],
["function(a,b) { return `${a}_${b}`", 5, 10],
["fuction(a,b) { return `${a}_${b}` }", 5, 10],
["Math.idonotexist", 5, 10],
];
// test
expect.assertions(invalidJSRequestParams.length);
invalidJSRequestParams.forEach((req) => {
const [jsFunc, ...rest] = req;
FMBond(jsFunc, ...rest);
const param = {
mode: "RETURN_JAVASCRIPT_RESULT",
result: {
messages: [
{
code: "-3",
message: `The function '${jsFunc}' either (a) is missing from the global scope, or (b) is not a valid function definition`,
},
],
response: {},
},
};
expect(performScriptSafelySpy).toHaveBeenLastCalledWith("r", param, "5");
});
// cleanup
FMBond.SetRelayScriptName("");
resetPerformScriptSafely();
});
test("function throws are handled", async () => {
// setup
FMBond.SetRelayScriptName("r");
const performScriptSafelySpy = jest.fn();
const resetPerformScriptSafely = FMBond.__set__(
"performScriptSafely",
performScriptSafelySpy
);
let expectedError;
try {
JSON.parse("{");
} catch (e) {
expectedError = e.toString();
}
const param = {
mode: "RETURN_JAVASCRIPT_RESULT",
result: {
messages: [
{
code: "-5",
message: expectedError,
},
],
response: {},
},
};
// test
expect.assertions(1);
FMBond("JSON.parse", "{");
expect(performScriptSafelySpy).toHaveBeenLastCalledWith("r", param, "5");
// cleanup
FMBond.SetRelayScriptName("");
resetPerformScriptSafely();
});
test("Node.js server returns result", async () => {
// setup
const performScriptSafelySpy = jest.fn();
const resetPerformScriptSafely = FMBond.__set__(
"performScriptSafely",
performScriptSafelySpy
);
// undefine the window
const oldWindow = FMBond.__get__("window");
FMBond.__set__("window", undefined);
// test
expect.assertions(3);
const expectedResult1 = {
messages: [{ code: "0", message: "OK" }],
response: { result: 10 },
};
const expectedResult2 = {
messages: [
{
code: "-5",
message: "SyntaxError: Unexpected end of JSON input",
},
],
response: {},
};
const result1 = FMBond("(a) => a + 9", "1");
expect(result1).toEqual(expectedResult1);
const result2 = FMBond("JSON.parse", "{");
expect(result2).toEqual(expectedResult2);
expect(performScriptSafelySpy).not.toHaveBeenCalled();
// cleanup
FMBond.__set__("window", oldWindow);
resetPerformScriptSafely();
});
});
describe("Getters & Setters", () => {
beforeEach(() => {
FMBond.SetRelayScriptName("");
FMBond.SetWebViewerName("");
FMBond.SetWebViewerConfig({});
});
afterAll(() => {
FMBond.SetRelayScriptName(RELAY_SCRIPT);
FMBond.SetWebViewerName(WEB_VIEWER);
FMBond.SetWebViewerConfig({});
});
test("web viewer name", () => {
expect.assertions(3);
expect(FMBond.GetWebViewerName()).toMatch("");
expect(FMBond.SetWebViewerName("test")).toEqual(FMBond);
expect(FMBond.GetWebViewerName()).toMatch("test");
});
test("relay script name", () => {
expect.assertions(3);
// Defaults to RELAY_SCRIPT when not set
expect(FMBond.GetRelayScriptName()).toMatch(RELAY_SCRIPT);
expect(FMBond.SetRelayScriptName("test")).toEqual(FMBond);
expect(FMBond.GetRelayScriptName()).toMatch("test");
});
test("web viewer config", () => {
expect.assertions(3);
const expectedConfig = {
my: "config",
};
expect(FMBond.GetWebViewerConfig()).toMatchObject({});
expect(FMBond.SetWebViewerConfig(expectedConfig)).toEqual(FMBond);
expect(FMBond.GetWebViewerConfig()).toMatchObject({
my: "config",
});
});
test("SetWebViewerNameFromFM when name is already set", () => {
// setup
FMBond.SetWebViewerName("wvNameWhenAlreadySet");
// test - when name is already set
expect.assertions(2);
return FMBond.SetWebViewerNameFromFM().then((res) => {
expect(res).toMatch("");
expect(FMBond.GetWebViewerName()).toMatch("wvNameWhenAlreadySet");
});
});
test("SetWebViewerNameFromFM when name not set", () => {
// setup
const performScriptSafelySpy = jest.fn(() => Promise.resolve());
const resetPerformScriptSafely = FMBond.__set__(
"performScriptSafely",
performScriptSafelySpy
);
const resetCreateUUID = FMBond.__set__("createUUID", () => PROMISE_UUID);
const fmReponse = JSON.stringify(
createFMResponse(PROMISE_UUID, "", "testWVname")
);
FMBond.SetRelayScriptName("testRelayScriptName");
// test
expect.assertions(5);
expect(FMBond.GetWebViewerName()).toMatch("");
const promise = FMBond.SetWebViewerNameFromFM();
FMBond(fmReponse);
return promise.then((res) => {
expect(res).toMatch("");
expect(FMBond.GetWebViewerName()).toMatch("testWVname");
expect(performScriptSafelySpy).toHaveBeenCalledTimes(1);
expect(performScriptSafelySpy).toHaveBeenCalledWith(
"testRelayScriptName",
{
mode: "PERFORM_SCRIPT",
options: { ignoreResult: false, webViewerName: "" },
promiseUUID: PROMISE_UUID,
script: {
name: "testRelayScriptName",
parameter: { mode: "GET_WEB_VIEWER_NAME" },
},
},
"0"
);
// cleanup
resetPerformScriptSafely();
resetCreateUUID();
});
});
test("Sync Config", () => {
// setup
const config = {
my: "config",
};
const fmReponse = Promise.resolve(config);
// PS = PerformScript
const PSspy = jest.fn(() => Promise.resolve(fmReponse));
const resetPS = FMBond.__set__("FMBond.PerformScript", PSspy);
FMBond.SetWebViewerName("wvName");
FMBond.SetRelayScriptName("rName");
// test
expect.assertions(5);
expect(FMBond.GetWebViewerName()).toMatch("wvName");
expect(FMBond.GetWebViewerConfig()).toMatchObject({});
return FMBond.SyncConfig().then((res) => {
const expectedConfig = {
my: "config",
};
expect(res).toEqual(expectedConfig);
expect(FMBond.GetWebViewerConfig()).toMatchObject(expectedConfig);
expect(PSspy).toHaveBeenCalledWith("rName", {
mode: "GET_CONFIG",
options: { webViewerName: "wvName" },
});
// cleanup
resetPS();
});
});
});
describe("Private utility methods work as intended", () => {
describe("performScriptSafely", () => {
test("works regularly", () => {
// setup
const FileMaker = function () {};
FileMaker.PerformScript = jest.fn();
FileMaker.PerformScriptWithOption = jest.fn();
const resetFileMaker = FMBond.__set__("FileMaker", FileMaker);
const performScriptSafely = FMBond.__get__("performScriptSafely");
// test
expect.assertions(3);
expect(performScriptSafely("a", "b")).resolves.not.toBeDefined();
expect(FileMaker.PerformScript).not.toHaveBeenCalled();
expect(FileMaker.PerformScriptWithOption).toHaveBeenCalledWith(
"a",
"b",
"0"
);
// cleanup
resetFileMaker();
});
test("Throws when FileMaker object is not available within 1000ms", async () => {
// setup
jest.useFakeTimers();
const performScriptSafely = FMBond.__get__("performScriptSafely");
const formattedFMError = FMBond.__get__("formattedFMError");
const { FM_NOT_FOUND } = FMBond.__get__("FMBOND_ERROR_CODE");
const expectedError = formattedFMError(
FM_NOT_FOUND,
"FileMaker object not found"
);
// test
expect.assertions(1);
const promise = performScriptSafely("a", "b");
jest.advanceTimersByTime(1110);
jest.useRealTimers();
return expect(promise).rejects.toThrow(expectedError);
});
test("Safely waits for FileMaker to become available within 1000ms", async () => {
// setup
let runSetInterval;
const setIntervalSpy = jest.fn((callback) => {
runSetInterval = jest.fn(() => callback());
});
const resetSetInterval = FMBond.__set__("setInterval", setIntervalSpy);
const FileMaker = function () {};
FileMaker.PerformScriptWithOption = jest.fn();
const performScriptSafely = FMBond.__get__("performScriptSafely");
// test
expect.assertions(6);
expect(FMBond.FileMaker).not.toBeDefined();
const pendingPromise = performScriptSafely("a", "b");
// simulate the passing of 50 milliseconds
for (let i = 0; i < 50; i++) {
runSetInterval();
}
expect(runSetInterval).toHaveBeenCalledTimes(50);
expect(FileMaker.PerformScriptWithOption).not.toHaveBeenCalled();
// simulate FileMaker being available in the global scope
const resetFileMaker = FMBond.__set__("FileMaker", FileMaker);
// simulate the passing of 1 more millisecond
runSetInterval();
expect(FileMaker.PerformScriptWithOption).toHaveBeenCalledTimes(1);
expect(FileMaker.PerformScriptWithOption).toHaveBeenCalledWith(
"a",
"b",
"0"
);
await pendingPromise;
expect(pendingPromise).resolves.not.toBeDefined();
resetSetInterval();
resetFileMaker();
});
});
test("formattedFMError", () => {
// setup
const expected = new Error(
JSON.stringify({
messages: [
{
code: "1",
message: "test message",
},
],
response: { test: "TEST" },
})
);
const formattedFMError = FMBond.__get__("formattedFMError");
const received = formattedFMError("1", "test message", { test: "TEST" });
// test
expect.assertions(1);
expect(received.message).toMatch(expected.message);
});
test("createUUID", () => {
expect.assertions(1);
const createUUID = FMBond.__get__("createUUID");
expect(createUUID()).toMatch(
/[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}/
);
});
test("tryParse / tryStringify", () => {
expect.assertions(6);
const tryStringify = FMBond.__get__("tryStringify");
const tryParse = FMBond.__get__("tryParse");
const testStr = '{"abc":123}';
const testObj = { abc: 123 };
expect(tryParse(testStr)).toMatchObject(testObj);
expect(tryParse(testObj)).toMatchObject(testObj);
expect(tryStringify(testObj)).toBe(testStr);
expect(tryStringify(testStr)).toBe(testStr);
expect(tryStringify(1)).toBe("1");
expect(tryStringify([1, 2, 3])).toBe("[1,2,3]");
});
});
describe("Scopes", () => {
test("Window & Global scopes have FMBond defined", () => {
expect.assertions(4);
expect(global.window).toHaveProperty("FMBond");
expect(global.window.FMBond).toBe(FMBondForWindow);
expect(global).toHaveProperty("FMBond");
expect(global.FMBond).toBe(FMBondForWindow);
});
});