Files
oneuptime/CLI/Tests/ConfigCommands.test.ts
Nawaz Dhandala d25a97fe17 Refactor components for improved readability and consistency
- Added missing newlines at the end of files in MarkdownContent.tsx and RootCauseCard.tsx
- Reformatted shadowColor and color properties in NotesSection.tsx, SegmentedControl.tsx, MainTabNavigator.tsx, HomeScreen.tsx for better readability
- Enhanced code formatting in SectionHeader.tsx and OnCallStackNavigator.tsx for consistency
- Improved readability of getEntityId function in useAllProjectOnCallPolicies.ts
- Refactored conditional rendering in AlertDetailScreen.tsx, AlertEpisodeDetailScreen.tsx, IncidentDetailScreen.tsx, and IncidentEpisodeDetailScreen.tsx for better clarity
2026-02-15 11:47:32 +00:00

258 lines
7.3 KiB
TypeScript

import { Command } from "commander";
import { registerConfigCommands } from "../Commands/ConfigCommands";
import * as ConfigManager from "../Core/ConfigManager";
import * as fs from "fs";
import * as path from "path";
import * as os from "os";
const CONFIG_DIR: string = path.join(os.homedir(), ".oneuptime");
const CONFIG_FILE: string = path.join(CONFIG_DIR, "config.json");
describe("ConfigCommands", () => {
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);
});
afterEach(() => {
consoleLogSpy.mockRestore();
jest.restoreAllMocks();
});
function createProgram(): Command {
const program: Command = new Command();
program.exitOverride(); // Prevent commander from calling process.exit
program.configureOutput({
writeOut: () => {},
writeErr: () => {},
});
registerConfigCommands(program);
return program;
}
describe("login command", () => {
it("should create a context and set it as current", async () => {
const program: Command = createProgram();
await program.parseAsync([
"node",
"test",
"login",
"my-api-key",
"https://example.com",
]);
const ctx: ReturnType<typeof ConfigManager.getCurrentContext> =
ConfigManager.getCurrentContext();
expect(ctx).not.toBeNull();
expect(ctx!.name).toBe("default");
expect(ctx!.apiUrl).toBe("https://example.com");
expect(ctx!.apiKey).toBe("my-api-key");
});
it("should use custom context name", async () => {
const program: Command = createProgram();
await program.parseAsync([
"node",
"test",
"login",
"key123",
"https://prod.com",
"--context-name",
"production",
]);
const ctx: ReturnType<typeof ConfigManager.getCurrentContext> =
ConfigManager.getCurrentContext();
expect(ctx!.name).toBe("production");
});
it("should handle login errors gracefully", async () => {
// Mock addContext to throw
const addCtxSpy: jest.SpyInstance = jest
.spyOn(ConfigManager, "addContext")
.mockImplementation(() => {
throw new Error("Permission denied");
});
const program: Command = createProgram();
await program.parseAsync([
"node",
"test",
"login",
"key123",
"https://example.com",
]);
expect(exitSpy).toHaveBeenCalledWith(1);
addCtxSpy.mockRestore();
});
it("should strip trailing slashes from URL", async () => {
const program: Command = createProgram();
await program.parseAsync([
"node",
"test",
"login",
"key123",
"https://example.com///",
]);
const ctx: ReturnType<typeof ConfigManager.getCurrentContext> =
ConfigManager.getCurrentContext();
expect(ctx!.apiUrl).toBe("https://example.com");
});
});
describe("context list command", () => {
it("should show message when no contexts exist", async () => {
const program: Command = createProgram();
await program.parseAsync(["node", "test", "context", "list"]);
expect(consoleLogSpy).toHaveBeenCalled();
});
it("should list contexts with current marker", async () => {
ConfigManager.addContext({
name: "a",
apiUrl: "https://a.com",
apiKey: "k1",
});
ConfigManager.addContext({
name: "b",
apiUrl: "https://b.com",
apiKey: "k2",
});
const program: Command = createProgram();
await program.parseAsync(["node", "test", "context", "list"]);
expect(consoleLogSpy).toHaveBeenCalled();
});
});
describe("context use command", () => {
it("should switch to the specified context", async () => {
ConfigManager.addContext({
name: "a",
apiUrl: "https://a.com",
apiKey: "k1",
});
ConfigManager.addContext({
name: "b",
apiUrl: "https://b.com",
apiKey: "k2",
});
const program: Command = createProgram();
await program.parseAsync(["node", "test", "context", "use", "b"]);
const current: ReturnType<typeof ConfigManager.getCurrentContext> =
ConfigManager.getCurrentContext();
expect(current!.name).toBe("b");
});
it("should handle non-existent context", async () => {
const program: Command = createProgram();
await program.parseAsync(["node", "test", "context", "use", "nope"]);
expect(exitSpy).toHaveBeenCalledWith(1);
});
});
describe("context current command", () => {
it("should show current context info", async () => {
ConfigManager.addContext({
name: "myctx",
apiUrl: "https://myctx.com",
apiKey: "abcdefghijklm",
});
const program: Command = createProgram();
await program.parseAsync(["node", "test", "context", "current"]);
// Check that masked key is shown
expect(consoleLogSpy).toHaveBeenCalledWith("Context: myctx");
expect(consoleLogSpy).toHaveBeenCalledWith("URL: https://myctx.com");
// Key should be masked: abcd****jklm
expect(consoleLogSpy).toHaveBeenCalledWith(
expect.stringContaining("****"),
);
});
it("should show message when no current context", async () => {
const program: Command = createProgram();
await program.parseAsync(["node", "test", "context", "current"]);
expect(consoleLogSpy).toHaveBeenCalled();
});
it("should mask short API keys", async () => {
ConfigManager.addContext({
name: "short",
apiUrl: "https://s.com",
apiKey: "abc",
});
const program: Command = createProgram();
await program.parseAsync(["node", "test", "context", "current"]);
expect(consoleLogSpy).toHaveBeenCalledWith("API Key: ****");
});
});
describe("context delete command", () => {
it("should delete a context", async () => {
ConfigManager.addContext({
name: "todelete",
apiUrl: "https://del.com",
apiKey: "k1",
});
const program: Command = createProgram();
await program.parseAsync([
"node",
"test",
"context",
"delete",
"todelete",
]);
const contexts: ReturnType<typeof ConfigManager.listContexts> =
ConfigManager.listContexts();
expect(contexts).toHaveLength(0);
});
it("should handle deletion of non-existent context", async () => {
const program: Command = createProgram();
await program.parseAsync([
"node",
"test",
"context",
"delete",
"nonexistent",
]);
expect(exitSpy).toHaveBeenCalledWith(1);
});
});
});