|
| 1 | +import { createServer, type Server, type ServerResponse } from "node:http"; |
| 2 | +import type { AddressInfo } from "node:net"; |
| 3 | +import { apiClientManager } from "@trigger.dev/core/v3"; |
| 4 | +import { afterEach, beforeEach, describe, expect, it } from "vitest"; |
| 5 | +import * as envvars from "./envvars.js"; |
| 6 | + |
| 7 | +type ReceivedRequest = { |
| 8 | + method: string; |
| 9 | + url: string; |
| 10 | +}; |
| 11 | + |
| 12 | +describe("envvars.update outside a task context (GH #4264)", () => { |
| 13 | + let server: Server; |
| 14 | + let baseUrl: string; |
| 15 | + let requests: ReceivedRequest[]; |
| 16 | + |
| 17 | + beforeEach(async () => { |
| 18 | + requests = []; |
| 19 | + server = createServer((request, response) => { |
| 20 | + requests.push({ method: request.method ?? "", url: request.url ?? "" }); |
| 21 | + response.writeHead(200, { "content-type": "application/json" }); |
| 22 | + response.end(JSON.stringify({ success: true })); |
| 23 | + }); |
| 24 | + await new Promise<void>((resolve) => { |
| 25 | + server.listen(0, "127.0.0.1", () => { |
| 26 | + baseUrl = `http://127.0.0.1:${(server.address() as AddressInfo).port}`; |
| 27 | + resolve(); |
| 28 | + }); |
| 29 | + }); |
| 30 | + }); |
| 31 | + |
| 32 | + afterEach(async () => { |
| 33 | + await new Promise<void>((resolve) => server.close(() => resolve())); |
| 34 | + }); |
| 35 | + |
| 36 | + it("resolves the name argument instead of throwing ReferenceError", async () => { |
| 37 | + const key = "tr_prod_0123456789abcdefghijklmn"; |
| 38 | + |
| 39 | + // Outside a task context, taskContext.ctx is undefined. Before the fix this |
| 40 | + // path evaluated `$name = name!`, but the implementation signature has no |
| 41 | + // `name` parameter, so it threw `ReferenceError: name is not defined`. |
| 42 | + await apiClientManager.runWithConfig({ baseURL: baseUrl, accessToken: key }, async () => { |
| 43 | + try { |
| 44 | + await envvars.update("proj_ref", "prod", "MY_SECRET", { value: "abc" }); |
| 45 | + } catch (err) { |
| 46 | + // Response-shape concerns are irrelevant here; only assert the |
| 47 | + // argument-resolution crash is gone. |
| 48 | + expect((err as Error).message).not.toContain("name is not defined"); |
| 49 | + } |
| 50 | + }); |
| 51 | + |
| 52 | + const updateRequest = requests.find((request) => request.url.includes("MY_SECRET")); |
| 53 | + expect(updateRequest).toBeDefined(); |
| 54 | + expect(updateRequest!.url).toContain("/projects/proj_ref/envvars/prod/MY_SECRET"); |
| 55 | + }); |
| 56 | + |
| 57 | + it("throws a clear error when the name is missing", async () => { |
| 58 | + const key = "tr_prod_0123456789abcdefghijklmn"; |
| 59 | + |
| 60 | + await apiClientManager.runWithConfig({ baseURL: baseUrl, accessToken: key }, async () => { |
| 61 | + await expect( |
| 62 | + // @ts-expect-error deliberately omitting the name argument |
| 63 | + envvars.update("proj_ref", "prod", { value: "abc" }) |
| 64 | + ).rejects.toThrow("name is required"); |
| 65 | + }); |
| 66 | + }); |
| 67 | +}); |
0 commit comments