import test from "node:test"; import assert from "node:assert/strict"; import { sendJsonRequest } from "../src/http.js"; import { runCli } from "./helpers.js"; const baseConfig = { baseUrl: "https://example.atlassian.net", jiraBaseUrl: "https://example.atlassian.net", confluenceBaseUrl: "https://example.atlassian.net", email: "dev@example.com", apiToken: "secret-token", }; const baseEnv = { ATLASSIAN_BASE_URL: "https://example.atlassian.net", ATLASSIAN_EMAIL: "dev@example.com", ATLASSIAN_API_TOKEN: "secret-token", }; test("health probes Jira and Confluence independently", async () => { const calls: string[] = []; const result = await runCli({ args: ["health"], env: baseEnv, fetchImpl: async (input) => { const url = typeof input === "string" ? input : input.toString(); calls.push(url); if (url.endsWith("/rest/api/3/myself")) { return new Response(JSON.stringify({ accountId: "1" }), { status: 200, headers: { "content-type": "application/json" }, }); } return new Response(JSON.stringify({ message: "Forbidden" }), { status: 403, statusText: "Forbidden", headers: { "content-type": "application/json" }, }); }, }); assert.deepEqual(calls, [ "https://example.atlassian.net/rest/api/3/myself", "https://example.atlassian.net/wiki/api/v2/spaces?limit=1", ]); assert.deepEqual(JSON.parse(result.stdout), { ok: false, data: { baseUrl: "https://example.atlassian.net", jiraBaseUrl: "https://example.atlassian.net", confluenceBaseUrl: "https://example.atlassian.net", products: { jira: { ok: true, status: 200, }, confluence: { ok: false, status: 403, message: "Confluence health check failed: 403 Forbidden - verify product permissions for this account", }, }, }, }); }); test("sendJsonRequest maps 401, 403, 404, and 429 to actionable messages", async () => { const cases = [ { status: 401, statusText: "Unauthorized", expected: /401 Unauthorized - check ATLASSIAN_EMAIL and ATLASSIAN_API_TOKEN/, }, { status: 403, statusText: "Forbidden", expected: /403 Forbidden - verify product permissions for this account/, }, { status: 404, statusText: "Not Found", expected: /404 Not Found - verify the resource identifier or API path/, }, { status: 429, statusText: "Too Many Requests", expected: /429 Too Many Requests - retry later or reduce request rate/, }, ] as const; for (const entry of cases) { await assert.rejects( sendJsonRequest({ config: baseConfig, url: "https://example.atlassian.net/rest/api/3/issue/ENG-1", method: "GET", errorPrefix: "Jira request failed", fetchImpl: async () => new Response(JSON.stringify({ message: entry.statusText }), { status: entry.status, statusText: entry.statusText, headers: { "content-type": "application/json" }, }), }), entry.expected, ); } }); test("sendJsonRequest reports malformed JSON responses clearly", async () => { await assert.rejects( sendJsonRequest({ config: baseConfig, url: "https://example.atlassian.net/rest/api/3/issue/ENG-1", method: "GET", errorPrefix: "Jira request failed", fetchImpl: async () => new Response("{", { status: 200, headers: { "content-type": "application/json" }, }), }), /Malformed JSON response from Atlassian API/, ); });