Files
ConvertX/tests/helpers/printVersions.test.ts
T

115 lines
4.4 KiB
TypeScript

import { test, expect, mock, spyOn, afterEach } from "bun:test";
import { exec } from "node:child_process";
import { readFile } from "node:fs";
// mocks have to be defined before importing the module under test,
// otherwise the real modules will be loaded first and the mocks won't take effect.
mock.module("node:child_process", () => ({
// The mock checks the environment variable MOCK_EXEC_ERROR at call-time so
// individual tests can trigger error paths by setting that env before
// importing the module under test.
exec: mock((cmd: string, cb: (error: Error | null, stdout: string) => void) => {
const shouldError = (process.env.MOCK_EXEC_ERROR || "")
.split(",")
.some((p) => p && cmd.includes(p));
if (shouldError) {
cb(new Error(`${cmd} not found`), "");
} else {
cb(null, `${cmd} v1.0.0\n`);
}
}),
}));
mock.module("node:fs", () => ({
readFile: mock(
(path: string, encoding: string, cb: (error: Error | null, data: string) => void) => {
cb(null, 'PRETTY_NAME="Ubuntu 22.04 LTS"\n');
},
),
}));
mock.module("../../package.json", () => ({
version: "1.0.0-test",
}));
// We import the module in each test after the spies and the desired NODE_ENV were set
// so that the top level execution is under control of each test
let consoleLogSpy: ReturnType<typeof spyOn>;
let consoleErrorSpy: ReturnType<typeof spyOn>;
afterEach(() => {
consoleLogSpy.mockRestore();
consoleErrorSpy.mockRestore();
delete process.env.NODE_ENV;
delete process.env.MOCK_EXEC_ERROR;
});
test("prints only the version and terminates itself immediately when NODE_ENV is not production", async () => {
consoleLogSpy = spyOn(console, "log");
consoleErrorSpy = spyOn(console, "error");
// import the module after the spies were set so that the initial console.log within the module
// gets recognized by the spy
await import("../../src/helpers/printVersions?test=" + Math.random());
// empty the queue to make sure all callbacks have been processed
await new Promise((resolve) => setImmediate(resolve));
expect(consoleLogSpy).toHaveBeenCalledWith("ConvertX v1.0.0-test");
expect(consoleLogSpy).toHaveBeenCalledTimes(1);
expect(readFile).not.toHaveBeenCalled();
});
test("prints system information and tool versions in production mode", async () => {
process.env.NODE_ENV = "production";
consoleLogSpy = spyOn(console, "log");
consoleErrorSpy = spyOn(console, "error");
// import module under test after setting NODE_ENV and activating the spies
await import("../../src/helpers/printVersions?test=" + Math.random());
await new Promise((resolve) => setImmediate(resolve));
expect(consoleLogSpy).toHaveBeenCalledWith("ConvertX v1.0.0-test");
expect(consoleLogSpy).toHaveBeenCalledWith("Ubuntu 22.04 LTS");
expect(readFile).toHaveBeenCalledTimes(1);
expect(exec).toHaveBeenCalledTimes(17); // Corresponds exactly to the number of exec calls in the source code
});
test("logs error paths when tools are missing", async () => {
process.env.NODE_ENV = "production";
// Trigger a few error paths
process.env.MOCK_EXEC_ERROR = "pandoc,resvg,bun";
consoleLogSpy = spyOn(console, "log");
consoleErrorSpy = spyOn(console, "error");
await import("../../src/helpers/printVersions?test=" + Math.random());
await new Promise((resolve) => setImmediate(resolve));
expect(consoleErrorSpy).toHaveBeenCalled();
expect(consoleErrorSpy).toHaveBeenCalledWith("Pandoc is not installed.");
expect(consoleErrorSpy).toHaveBeenCalledWith("resvg is not installed");
expect(consoleErrorSpy).toHaveBeenCalledWith("Bun is not installed. wait what");
});
test("processes output parsing correctly and logs no errors in the success case", async () => {
process.env.NODE_ENV = "production";
consoleLogSpy = spyOn(console, "log");
consoleErrorSpy = spyOn(console, "error");
// import module under test after setting NODE_ENV and activating the spies
await import("../../src/helpers/printVersions?test=" + Math.random());
await new Promise((resolve) => setImmediate(resolve));
// testing some specific outputs
expect(consoleLogSpy).toHaveBeenCalledWith("pandoc -v v1.0.0");
expect(consoleLogSpy).toHaveBeenCalledWith("ffmpeg -version v1.0.0");
expect(consoleLogSpy).toHaveBeenCalledWith("resvg v1.0.0");
expect(consoleLogSpy).toHaveBeenCalledWith("Bun v1.0.0");
// make sure that error paths have not been triggered
expect(consoleErrorSpy).not.toHaveBeenCalled();
});