This example can be used to test functions in Google Apps Script code.
It uses the Node.js VM module to create an ad hoc script,
which consists of the function's code to be tested as well as an invocation of the function to be evaluated.
The result of the script is returned by execute
and can be asserted afterwards.
If the function uses global objects (e.g. DriveApp
, SpreadsheetApp
or GmailApp
), stub implementations can be provided as context for the script execution.
import chai from "chai";
import fs from "fs";
import vm from "vm";
const expect = chai.expect;
const code = fs.readFileSync("./backend/code.js", "utf8");
function execute(functionName, args = [], ctx = {}) {
// "myFunction", ["test", true, 123] -> "arg0,arg1,arg2"
let argsExpr = "";
// "myFunction", ["test", true, 123] -> {arg0: "test", arg1: true, arg2: 123}
const context = Object.assign({}, ctx);
for (let i = 0; i < args.length; i++) {
argsExpr += (i != 0 ? "," : "") + "arg" + i;
context["arg" + i] = args[i];
}
// "myFunction", ["test", true, 123] -> myFunction(arg0,arg1,arg2);
return new vm.Script(`${code}\n${functionName}(${argsExpr});`).runInNewContext(context);
}
describe("code", () => {
it("should parse and sort list", () => {
const genres = execute("parseAndSort", ["z,y,x"]);
expect(genres).to.have.lengthOf(3);
expect(genres[0]).to.equal("x");
expect(genres[1]).to.equal("y");
expect(genres[2]).to.equal("z");
});
it("should throw an error, if desired file does not exist", () => {
const DriveApp = stubDriveAppWithoutFiles();
expect(() => execute("getFile", [], { DriveApp })).to.throw();
});
});
function stubDriveAppWithoutFiles() {
const files = {
hasNext: () => false
};
return {
getRootFolder: () => {
return {
getFilesByName: () => {
return files;
}
};
}
};
}