mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-05-27 01:31:35 +00:00
202 lines
7.7 KiB
TypeScript
202 lines
7.7 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { parseArgs } from "./main";
|
|
|
|
function mockProcessExit() {
|
|
const exitMock = vi.spyOn(process, "exit").mockImplementation(((code?: number) => {
|
|
throw new Error(`__EXIT__:${code ?? 0}`);
|
|
}) as any);
|
|
return exitMock;
|
|
}
|
|
|
|
describe("CLI parseArgs", () => {
|
|
const originalArgv = process.argv.slice();
|
|
|
|
afterEach(() => {
|
|
process.argv = originalArgv.slice();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it("exits 1 when --settings has no value", () => {
|
|
process.argv = ["node", "livesync-cli", "./databasePath", "--settings"];
|
|
const exitMock = mockProcessExit();
|
|
const stderr = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
|
|
expect(() => parseArgs()).toThrowError("__EXIT__:1");
|
|
expect(exitMock).toHaveBeenCalledWith(1);
|
|
expect(stderr).toHaveBeenCalledWith("Error: Missing value for --settings");
|
|
});
|
|
|
|
it("exits 1 when database-path is missing", () => {
|
|
process.argv = ["node", "livesync-cli", "sync"];
|
|
const exitMock = mockProcessExit();
|
|
const stderr = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
|
|
expect(() => parseArgs()).toThrowError("__EXIT__:1");
|
|
expect(exitMock).toHaveBeenCalledWith(1);
|
|
expect(stderr).toHaveBeenCalledWith("Error: database-path is required");
|
|
});
|
|
|
|
it("exits 1 for unknown command after database-path", () => {
|
|
process.argv = ["node", "livesync-cli", "./databasePath", "unknown-cmd"];
|
|
const exitMock = mockProcessExit();
|
|
const stderr = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
|
|
expect(() => parseArgs()).toThrowError("__EXIT__:1");
|
|
expect(exitMock).toHaveBeenCalledWith(1);
|
|
expect(stderr).toHaveBeenCalledWith("Error: Unknown command 'unknown-cmd'");
|
|
});
|
|
|
|
it("exits 0 and prints help for --help", () => {
|
|
process.argv = ["node", "livesync-cli", "--help"];
|
|
const exitMock = mockProcessExit();
|
|
const stdout = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
|
|
expect(() => parseArgs()).toThrowError("__EXIT__:0");
|
|
expect(exitMock).toHaveBeenCalledWith(0);
|
|
expect(stdout).toHaveBeenCalled();
|
|
const combined = stdout.mock.calls.flat().join("\n");
|
|
expect(combined).toContain("Usage:");
|
|
expect(combined).toContain("livesync-cli <database-path> [options] <command> [command-args]");
|
|
});
|
|
|
|
it("parses p2p-peers command and timeout", () => {
|
|
process.argv = ["node", "livesync-cli", "./databasePath", "p2p-peers", "5"];
|
|
const parsed = parseArgs();
|
|
|
|
expect(parsed.databasePath).toBe("./databasePath");
|
|
expect(parsed.command).toBe("p2p-peers");
|
|
expect(parsed.commandArgs).toEqual(["5"]);
|
|
});
|
|
|
|
it("parses p2p-sync command with peer and timeout", () => {
|
|
process.argv = ["node", "livesync-cli", "./databasePath", "p2p-sync", "peer-1", "12"];
|
|
const parsed = parseArgs();
|
|
|
|
expect(parsed.databasePath).toBe("./databasePath");
|
|
expect(parsed.command).toBe("p2p-sync");
|
|
expect(parsed.commandArgs).toEqual(["peer-1", "12"]);
|
|
});
|
|
|
|
it("parses p2p-host command", () => {
|
|
process.argv = ["node", "livesync-cli", "./databasePath", "p2p-host"];
|
|
const parsed = parseArgs();
|
|
|
|
expect(parsed.databasePath).toBe("./databasePath");
|
|
expect(parsed.command).toBe("p2p-host");
|
|
expect(parsed.commandArgs).toEqual([]);
|
|
});
|
|
|
|
it("parses remote-add command", () => {
|
|
process.argv = [
|
|
"node",
|
|
"livesync-cli",
|
|
"./databasePath",
|
|
"remote-add",
|
|
"my-remote",
|
|
"sls+https://user:pass@example.com/db",
|
|
];
|
|
const parsed = parseArgs();
|
|
|
|
expect(parsed.databasePath).toBe("./databasePath");
|
|
expect(parsed.command).toBe("remote-add");
|
|
expect(parsed.commandArgs).toEqual(["my-remote", "sls+https://user:pass@example.com/db"]);
|
|
});
|
|
|
|
it("parses remote-activate command", () => {
|
|
process.argv = ["node", "livesync-cli", "./databasePath", "remote-activate", "remote-abc"];
|
|
const parsed = parseArgs();
|
|
|
|
expect(parsed.databasePath).toBe("./databasePath");
|
|
expect(parsed.command).toBe("remote-activate");
|
|
expect(parsed.commandArgs).toEqual(["remote-abc"]);
|
|
});
|
|
|
|
it("parses remote-export command", () => {
|
|
process.argv = ["node", "livesync-cli", "./databasePath", "remote-export", "remote-abc"];
|
|
const parsed = parseArgs();
|
|
|
|
expect(parsed.databasePath).toBe("./databasePath");
|
|
expect(parsed.command).toBe("remote-export");
|
|
expect(parsed.commandArgs).toEqual(["remote-abc"]);
|
|
});
|
|
|
|
it("parses remote-set command", () => {
|
|
process.argv = [
|
|
"node",
|
|
"livesync-cli",
|
|
"./databasePath",
|
|
"remote-set",
|
|
"remote-abc",
|
|
"sls+p2p://room-1?passphrase=abc",
|
|
];
|
|
const parsed = parseArgs();
|
|
|
|
expect(parsed.databasePath).toBe("./databasePath");
|
|
expect(parsed.command).toBe("remote-set");
|
|
expect(parsed.commandArgs).toEqual(["remote-abc", "sls+p2p://room-1?passphrase=abc"]);
|
|
});
|
|
|
|
it("parses --interval flag with valid integer", () => {
|
|
process.argv = ["node", "livesync-cli", "./vault", "--interval", "30"];
|
|
const parsed = parseArgs();
|
|
expect(parsed.command).toBe("daemon");
|
|
expect(parsed.interval).toBe(30);
|
|
});
|
|
|
|
it("parses -i shorthand for --interval", () => {
|
|
process.argv = ["node", "livesync-cli", "./vault", "-i", "10"];
|
|
const parsed = parseArgs();
|
|
expect(parsed.interval).toBe(10);
|
|
});
|
|
|
|
it("exits 1 when --interval has no value", () => {
|
|
process.argv = ["node", "livesync-cli", "./vault", "--interval"];
|
|
const exitMock = mockProcessExit();
|
|
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
expect(() => parseArgs()).toThrowError("__EXIT__:1");
|
|
expect(exitMock).toHaveBeenCalledWith(1);
|
|
});
|
|
|
|
it("exits 1 when --interval is not a positive integer", () => {
|
|
process.argv = ["node", "livesync-cli", "./vault", "--interval", "0"];
|
|
const exitMock = mockProcessExit();
|
|
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
expect(() => parseArgs()).toThrowError("__EXIT__:1");
|
|
expect(exitMock).toHaveBeenCalledWith(1);
|
|
});
|
|
|
|
it("exits 1 when --interval is negative", () => {
|
|
process.argv = ["node", "livesync-cli", "./vault", "--interval", "-5"];
|
|
const exitMock = mockProcessExit();
|
|
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
expect(() => parseArgs()).toThrowError("__EXIT__:1");
|
|
});
|
|
|
|
it("exits 1 when --interval is not numeric", () => {
|
|
process.argv = ["node", "livesync-cli", "./vault", "--interval", "abc"];
|
|
const exitMock = mockProcessExit();
|
|
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
expect(() => parseArgs()).toThrowError("__EXIT__:1");
|
|
});
|
|
|
|
it("parses explicit daemon command", () => {
|
|
process.argv = ["node", "livesync-cli", "./vault", "daemon"];
|
|
const parsed = parseArgs();
|
|
expect(parsed.command).toBe("daemon");
|
|
expect(parsed.databasePath).toBe("./vault");
|
|
});
|
|
|
|
it("defaults to daemon when no command specified", () => {
|
|
process.argv = ["node", "livesync-cli", "./vault"];
|
|
const parsed = parseArgs();
|
|
expect(parsed.command).toBe("daemon");
|
|
});
|
|
|
|
it("parses explicit daemon command with --interval", () => {
|
|
process.argv = ["node", "livesync-cli", "./vault", "daemon", "--interval", "30"];
|
|
const parsed = parseArgs();
|
|
expect(parsed.command).toBe("daemon");
|
|
expect(parsed.interval).toBe(30);
|
|
});
|
|
});
|