From b0cc7367394c705bba6743b099daff8f1cf8b0a9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Sep 2026 03:55:03 +0000 Subject: [PATCH] [jsweep] Clean upload_workitem_attachment.cjs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../setup/js/upload_workitem_attachment.cjs | 7 +++ .../js/upload_workitem_attachment.test.cjs | 59 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 actions/setup/js/upload_workitem_attachment.test.cjs diff --git a/actions/setup/js/upload_workitem_attachment.cjs b/actions/setup/js/upload_workitem_attachment.cjs index aee035502b3..5933f6824ab 100644 --- a/actions/setup/js/upload_workitem_attachment.cjs +++ b/actions/setup/js/upload_workitem_attachment.cjs @@ -1,6 +1,13 @@ // @ts-check const { createAzureDevOpsWorkItemHandler } = require("./azure_devops_work_items.cjs"); + +/** + * Creates the Azure DevOps work item attachment upload handler. + * @param {Object} [config] - Handler configuration + * @returns {Promise} Message handler + */ async function main(config = {}) { return createAzureDevOpsWorkItemHandler("ado_upload_workitem_attachment", config); } + module.exports = { main }; diff --git a/actions/setup/js/upload_workitem_attachment.test.cjs b/actions/setup/js/upload_workitem_attachment.test.cjs new file mode 100644 index 00000000000..74e1f8d123f --- /dev/null +++ b/actions/setup/js/upload_workitem_attachment.test.cjs @@ -0,0 +1,59 @@ +// @ts-check +import { describe, it, expect, beforeEach, afterEach } from "vitest"; +import { createRequire } from "module"; + +const req = createRequire(import.meta.url); + +describe("upload_workitem_attachment", () => { + let originalCore; + let originalFetch; + + beforeEach(() => { + originalCore = global.core; + originalFetch = global.fetch; + global.core = /** @type {any} */ { info: () => {}, warning: () => {}, error: () => {}, debug: () => {}, setFailed: () => {} }; + global.fetch = /** @type {any} */ () => { + throw new Error("fetch should not be called in staged mode"); + }; + }); + + afterEach(() => { + global.core = originalCore; + global.fetch = originalFetch; + }); + + it("exports main as a function", () => { + const { main } = req("./upload_workitem_attachment.cjs"); + expect(typeof main).toBe("function"); + }); + + it("returns a handler function", async () => { + const { main } = req("./upload_workitem_attachment.cjs"); + const handler = await main({ staged: true }); + expect(typeof handler).toBe("function"); + }); + + it("accepts being called without config", async () => { + const { main } = req("./upload_workitem_attachment.cjs"); + const handler = await main(); + expect(typeof handler).toBe("function"); + }); + + it("logs a staged preview without touching the network", async () => { + const infos = []; + global.core = /** @type {any} */ { ...global.core, info: msg => infos.push(msg) }; + const { main } = req("./upload_workitem_attachment.cjs"); + const handler = await main({ staged: true }); + await handler({ work_item_id: 7, file_path: "a/b.txt" }, {}); + expect(infos.join(" ")).toContain("Would attach a file to Azure DevOps work item 7"); + }); + + it("does not leak the file path in staged output", async () => { + const infos = []; + global.core = /** @type {any} */ { ...global.core, info: msg => infos.push(msg) }; + const { main } = req("./upload_workitem_attachment.cjs"); + const handler = await main({ staged: true }); + await handler({ work_item_id: 7, file_path: "secret/file.pdf" }, {}); + expect(infos.join(" ")).not.toContain("secret/file.pdf"); + }); +});