import { Command } from "commander"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { registerNodesLocationCommands } from "./register.location.js"; const mocks = vi.hoisted(() => ({ resolveCliNodeId: vi.fn(async () => "node-1"), callNodesGatewayCli: vi.fn(async () => ({ payload: { lat: 48.2, lon: 16.3 } })), })); vi.mock("./cli-utils.js", () => ({ runNodesCommand: async (_label: string, action: () => Promise) => action(), })); vi.mock("./rpc.js", async () => { const actual = await vi.importActual("./rpc.js"); return { ...actual, resolveCliNodeId: mocks.resolveCliNodeId, callNodesGatewayCli: mocks.callNodesGatewayCli, }; }); vi.mock("../../gateway/call.js", () => ({ randomIdempotencyKey: () => "location-test-key", })); vi.mock("../../runtime.js", () => ({ defaultRuntime: { writeJson: vi.fn(), log: vi.fn(), }, })); function createNodesCommand(): Command { const nodes = new Command("nodes"); registerNodesLocationCommands(nodes); return nodes.exitOverride().configureOutput({ writeErr: () => {}, writeOut: () => {} }); } describe("nodes location get validation", () => { beforeEach(() => { vi.clearAllMocks(); }); it("rejects unsupported accuracy values before resolving or invoking a node", async () => { const nodes = createNodesCommand(); await expect( nodes.parseAsync([ "node", "nodes", "location", "get", "--node", "node-1", "--accuracy", "approximate", ]), ).rejects.toThrow("invalid --accuracy (use coarse|balanced|precise)"); expect(mocks.resolveCliNodeId).not.toHaveBeenCalled(); expect(mocks.callNodesGatewayCli).not.toHaveBeenCalled(); }); it("normalizes and forwards supported accuracy values", async () => { const nodes = createNodesCommand(); await nodes.parseAsync([ "node", "nodes", "location", "get", "--node", "node-1", "--accuracy", "PRECISE", ]); expect(mocks.callNodesGatewayCli).toHaveBeenCalledWith( "node.invoke", expect.anything(), expect.objectContaining({ params: expect.objectContaining({ desiredAccuracy: "precise" }), }), ); }); it.each(["", " \t "])( "rejects explicit blank --location-timeout %j before resolving or invoking a node", async (locationTimeout) => { const nodes = createNodesCommand(); await expect( nodes.parseAsync([ "node", "nodes", "location", "get", "--node", "node-1", "--location-timeout", locationTimeout, ]), ).rejects.toThrow("--location-timeout must be a positive integer"); expect(mocks.resolveCliNodeId).not.toHaveBeenCalled(); expect(mocks.callNodesGatewayCli).not.toHaveBeenCalled(); }, ); });