mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
- Implement tests for ResourceCommands, ConfigCommands, UtilityCommands, and ErrorHandler. - Enhance test coverage for command registration and execution, including list, get, create, update, delete, and count operations. - Introduce tests for credential management and context handling in commands. - Add error handling tests to ensure graceful exits on API errors and invalid inputs. - Update jest configuration to exclude test files from coverage and adjust TypeScript settings.
192 lines
6.0 KiB
TypeScript
192 lines
6.0 KiB
TypeScript
import { Command } from "commander";
|
|
import { registerUtilityCommands } from "../Commands/UtilityCommands";
|
|
import { registerResourceCommands } from "../Commands/ResourceCommands";
|
|
import * as ConfigManager from "../Core/ConfigManager";
|
|
import * as fs from "fs";
|
|
import * as path from "path";
|
|
import * as os from "os";
|
|
|
|
const CONFIG_DIR = path.join(os.homedir(), ".oneuptime");
|
|
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
|
|
describe("UtilityCommands", () => {
|
|
let originalConfigContent: string | null = null;
|
|
let consoleLogSpy: jest.SpyInstance;
|
|
let exitSpy: jest.SpyInstance;
|
|
|
|
beforeAll(() => {
|
|
if (fs.existsSync(CONFIG_FILE)) {
|
|
originalConfigContent = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
}
|
|
});
|
|
|
|
afterAll(() => {
|
|
if (originalConfigContent) {
|
|
fs.writeFileSync(CONFIG_FILE, originalConfigContent, { mode: 0o600 });
|
|
} else if (fs.existsSync(CONFIG_FILE)) {
|
|
fs.unlinkSync(CONFIG_FILE);
|
|
}
|
|
});
|
|
|
|
beforeEach(() => {
|
|
if (fs.existsSync(CONFIG_FILE)) {
|
|
fs.unlinkSync(CONFIG_FILE);
|
|
}
|
|
consoleLogSpy = jest.spyOn(console, "log").mockImplementation(() => {});
|
|
jest.spyOn(console, "error").mockImplementation(() => {});
|
|
exitSpy = jest.spyOn(process, "exit").mockImplementation((() => {}) as any);
|
|
delete process.env["ONEUPTIME_API_KEY"];
|
|
delete process.env["ONEUPTIME_URL"];
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.restoreAllMocks();
|
|
delete process.env["ONEUPTIME_API_KEY"];
|
|
delete process.env["ONEUPTIME_URL"];
|
|
});
|
|
|
|
function createProgram(): Command {
|
|
const program = new Command();
|
|
program.exitOverride();
|
|
program.configureOutput({
|
|
writeOut: () => {},
|
|
writeErr: () => {},
|
|
});
|
|
program
|
|
.option("--api-key <key>", "API key")
|
|
.option("--url <url>", "URL")
|
|
.option("--context <name>", "Context");
|
|
registerUtilityCommands(program);
|
|
return program;
|
|
}
|
|
|
|
describe("version command", () => {
|
|
it("should print version", async () => {
|
|
const program = createProgram();
|
|
await program.parseAsync(["node", "test", "version"]);
|
|
expect(consoleLogSpy).toHaveBeenCalled();
|
|
// Should print a version string (either from package.json or fallback)
|
|
const versionArg = consoleLogSpy.mock.calls[0][0];
|
|
expect(typeof versionArg).toBe("string");
|
|
});
|
|
});
|
|
|
|
describe("whoami command", () => {
|
|
it("should show not authenticated when no credentials", async () => {
|
|
const program = createProgram();
|
|
await program.parseAsync(["node", "test", "whoami"]);
|
|
expect(consoleLogSpy).toHaveBeenCalled();
|
|
});
|
|
|
|
it("should show credentials from current context", async () => {
|
|
ConfigManager.addContext({
|
|
name: "test",
|
|
apiUrl: "https://test.com",
|
|
apiKey: "abcdefghijklm",
|
|
});
|
|
|
|
const program = createProgram();
|
|
await program.parseAsync(["node", "test", "whoami"]);
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalledWith("URL: https://test.com");
|
|
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
expect.stringContaining("****"),
|
|
);
|
|
expect(consoleLogSpy).toHaveBeenCalledWith("Context: test");
|
|
});
|
|
|
|
it("should mask short API keys", async () => {
|
|
ConfigManager.addContext({
|
|
name: "short",
|
|
apiUrl: "https://s.com",
|
|
apiKey: "abc",
|
|
});
|
|
|
|
const program = createProgram();
|
|
await program.parseAsync(["node", "test", "whoami"]);
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalledWith("API Key: ****");
|
|
});
|
|
|
|
it("should show credentials from env vars", async () => {
|
|
process.env["ONEUPTIME_API_KEY"] = "env-key-long-enough";
|
|
process.env["ONEUPTIME_URL"] = "https://env.com";
|
|
|
|
const program = createProgram();
|
|
await program.parseAsync(["node", "test", "whoami"]);
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalledWith("URL: https://env.com");
|
|
});
|
|
|
|
it("should handle whoami outer catch block", async () => {
|
|
// Mock getCurrentContext to throw an unexpected error
|
|
const spy = jest
|
|
.spyOn(ConfigManager, "getCurrentContext")
|
|
.mockImplementation(() => {
|
|
throw new Error("Unexpected crash");
|
|
});
|
|
|
|
const program = createProgram();
|
|
await program.parseAsync(["node", "test", "whoami"]);
|
|
|
|
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
spy.mockRestore();
|
|
});
|
|
|
|
it("should not show context line when no context exists", async () => {
|
|
process.env["ONEUPTIME_API_KEY"] = "env-key-long-enough";
|
|
process.env["ONEUPTIME_URL"] = "https://env.com";
|
|
|
|
const program = createProgram();
|
|
await program.parseAsync(["node", "test", "whoami"]);
|
|
|
|
// Should NOT have a "Context:" call since no context is set
|
|
const contextCalls = consoleLogSpy.mock.calls.filter(
|
|
(call: any[]) => typeof call[0] === "string" && call[0].startsWith("Context:"),
|
|
);
|
|
expect(contextCalls).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
describe("resources command", () => {
|
|
it("should list all resources", async () => {
|
|
// We need registerResourceCommands for discoverResources to work
|
|
// but discoverResources is imported directly, so it should work
|
|
const program = createProgram();
|
|
await program.parseAsync(["node", "test", "resources"]);
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalled();
|
|
// Should show total count
|
|
const lastCall =
|
|
consoleLogSpy.mock.calls[consoleLogSpy.mock.calls.length - 1][0];
|
|
expect(lastCall).toContain("Total:");
|
|
});
|
|
|
|
it("should filter by type", async () => {
|
|
const program = createProgram();
|
|
await program.parseAsync([
|
|
"node",
|
|
"test",
|
|
"resources",
|
|
"--type",
|
|
"database",
|
|
]);
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalled();
|
|
});
|
|
|
|
it("should show message when filter returns no results", async () => {
|
|
const program = createProgram();
|
|
await program.parseAsync([
|
|
"node",
|
|
"test",
|
|
"resources",
|
|
"--type",
|
|
"nonexistent",
|
|
]);
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|