feat(atlassian): implement milestone M3 - confluence and safety controls
This commit is contained in:
129
skills/atlassian/shared/scripts/tests/raw.test.ts
Normal file
129
skills/atlassian/shared/scripts/tests/raw.test.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { createTempWorkspace, jsonResponse, runCli } from "./helpers.js";
|
||||
|
||||
const baseEnv = {
|
||||
ATLASSIAN_BASE_URL: "https://example.atlassian.net",
|
||||
ATLASSIAN_EMAIL: "dev@example.com",
|
||||
ATLASSIAN_API_TOKEN: "secret-token",
|
||||
};
|
||||
|
||||
test("raw rejects DELETE requests", async () => {
|
||||
await assert.rejects(
|
||||
runCli({
|
||||
args: ["raw", "--product", "jira", "--method", "DELETE", "--path", "/rest/api/3/issue/ENG-1"],
|
||||
env: baseEnv,
|
||||
}),
|
||||
/raw only allows GET, POST, and PUT/,
|
||||
);
|
||||
});
|
||||
|
||||
test("raw rejects unsupported Jira and Confluence prefixes", async () => {
|
||||
await assert.rejects(
|
||||
runCli({
|
||||
args: ["raw", "--product", "jira", "--method", "GET", "--path", "/wiki/api/v2/pages"],
|
||||
env: baseEnv,
|
||||
}),
|
||||
/raw path is not allowed for jira/,
|
||||
);
|
||||
|
||||
await assert.rejects(
|
||||
runCli({
|
||||
args: ["raw", "--product", "confluence", "--method", "GET", "--path", "/rest/api/3/issue/ENG-1"],
|
||||
env: baseEnv,
|
||||
}),
|
||||
/raw path is not allowed for confluence/,
|
||||
);
|
||||
});
|
||||
|
||||
test("raw GET executes against the validated Jira endpoint", async () => {
|
||||
let call: { url: string; init: RequestInit | undefined } | undefined;
|
||||
|
||||
const result = await runCli({
|
||||
args: ["raw", "--product", "jira", "--method", "GET", "--path", "/rest/api/3/issue/ENG-1"],
|
||||
env: baseEnv,
|
||||
fetchImpl: async (input, init) => {
|
||||
call = { url: typeof input === "string" ? input : input.toString(), init };
|
||||
return jsonResponse({ id: "10001", key: "ENG-1" });
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(call, {
|
||||
url: "https://example.atlassian.net/rest/api/3/issue/ENG-1",
|
||||
init: {
|
||||
method: "GET",
|
||||
headers: [
|
||||
["Accept", "application/json"],
|
||||
["Authorization", `Basic ${Buffer.from("dev@example.com:secret-token").toString("base64")}`],
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(JSON.parse(result.stdout), {
|
||||
ok: true,
|
||||
data: {
|
||||
id: "10001",
|
||||
key: "ENG-1",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("raw POST dry-run reads only workspace-scoped body files", async () => {
|
||||
const workspace = createTempWorkspace();
|
||||
|
||||
try {
|
||||
workspace.write("payload.json", "{\"title\":\"Runbook\"}");
|
||||
|
||||
const result = await runCli({
|
||||
args: [
|
||||
"raw",
|
||||
"--product",
|
||||
"confluence",
|
||||
"--method",
|
||||
"POST",
|
||||
"--path",
|
||||
"/wiki/api/v2/pages",
|
||||
"--body-file",
|
||||
"payload.json",
|
||||
"--dry-run",
|
||||
],
|
||||
cwd: workspace.cwd,
|
||||
env: baseEnv,
|
||||
});
|
||||
|
||||
assert.deepEqual(JSON.parse(result.stdout), {
|
||||
ok: true,
|
||||
dryRun: true,
|
||||
data: {
|
||||
method: "POST",
|
||||
url: "https://example.atlassian.net/wiki/api/v2/pages",
|
||||
body: {
|
||||
title: "Runbook",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await assert.rejects(
|
||||
runCli({
|
||||
args: [
|
||||
"raw",
|
||||
"--product",
|
||||
"confluence",
|
||||
"--method",
|
||||
"POST",
|
||||
"--path",
|
||||
"/wiki/api/v2/pages",
|
||||
"--body-file",
|
||||
"../outside.json",
|
||||
"--dry-run",
|
||||
],
|
||||
cwd: workspace.cwd,
|
||||
env: baseEnv,
|
||||
}),
|
||||
/--body-file must stay within the active workspace/,
|
||||
);
|
||||
} finally {
|
||||
workspace.cleanup();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user