




















@@ -157,9 +157,11 @@ describe("mantis Slack desktop smoke runtime", () => {
157157158158it("leases Convex Slack credentials for gateway setup and maps them into the VM env", async () => {
159159const commands: { args: readonly string[]; command: string; env?: NodeJS.ProcessEnv }[] = [];
160+const events: string[] = [];
160161const fetchMock = vi.fn(async (input: RequestInfo | URL, init?: RequestInit) => {
161162const url = describeFetchInput(input);
162163if (url.endsWith("/acquire")) {
164+events.push("acquire");
163165return new Response(
164166JSON.stringify({
165167credentialId: "cred-slack",
@@ -177,6 +179,7 @@ describe("mantis Slack desktop smoke runtime", () => {
177179);
178180}
179181if (url.endsWith("/release") || url.endsWith("/heartbeat")) {
182+events.push(url.endsWith("/release") ? "release" : "heartbeat");
180183return new Response(JSON.stringify({ status: "ok" }), { status: 200 });
181184}
182185throw new Error(`unexpected fetch: ${url} ${describeFetchBody(init?.body)}`);
@@ -186,6 +189,7 @@ describe("mantis Slack desktop smoke runtime", () => {
186189const runner = vi.fn(
187190async (command: string, args: readonly string[], options: { env?: NodeJS.ProcessEnv }) => {
188191commands.push({ command, args, env: options.env });
192+events.push(`${command}:${args[0]}`);
189193if (command === "/tmp/crabbox" && args[0] === "warmup") {
190194return { stdout: "ready lease cbx_c0ffee\n", stderr: "" };
191195}
@@ -244,6 +248,17 @@ describe("mantis Slack desktop smoke runtime", () => {
244248});
245249246250expect(result.status).toBe("pass");
251+expect(events).toEqual(
252+expect.arrayContaining([
253+"/tmp/crabbox:warmup",
254+"/tmp/crabbox:inspect",
255+"acquire",
256+"/tmp/crabbox:run",
257+"release",
258+]),
259+);
260+expect(events.indexOf("acquire")).toBeGreaterThan(events.indexOf("/tmp/crabbox:inspect"));
261+expect(events.indexOf("acquire")).toBeLessThan(events.indexOf("/tmp/crabbox:run"));
247262const runCommand = commands.find(
248263(entry) => entry.command === "/tmp/crabbox" && entry.args[0] === "run",
249264);
@@ -274,6 +289,59 @@ describe("mantis Slack desktop smoke runtime", () => {
274289expect(summary.slackUrl).toBe("https://app.slack.com/client/TLEASED/CLEASED");
275290});
276291292+it("stops a created no-keep lease when the remote Slack QA run fails", async () => {
293+const commands: { args: readonly string[]; command: string }[] = [];
294+const runner = vi.fn(async (command: string, args: readonly string[]) => {
295+commands.push({ command, args });
296+if (command === "/tmp/crabbox" && args[0] === "warmup") {
297+return { stdout: "ready lease cbx_fade123\n", stderr: "" };
298+}
299+if (command === "/tmp/crabbox" && args[0] === "inspect") {
300+return {
301+stdout: `${JSON.stringify({
302+ host: "203.0.113.10",
303+ id: "cbx_fade123",
304+ provider: "hetzner",
305+ sshKey: "/tmp/key",
306+ sshPort: "2222",
307+ sshUser: "crabbox",
308+ })}\n`,
309+stderr: "",
310+};
311+}
312+if (command === "/tmp/crabbox" && args[0] === "run") {
313+throw new Error("remote Slack QA failed");
314+}
315+if (command === "rsync") {
316+const outputDir = args.at(-1);
317+await fs.mkdir(outputDir as string, { recursive: true });
318+if (!String(outputDir).endsWith("slack-qa/")) {
319+await fs.writeFile(path.join(outputDir as string, "slack-desktop-smoke.png"), "png");
320+await fs.writeFile(path.join(outputDir as string, "remote-metadata.json"), "{}\n");
321+}
322+}
323+return { stdout: "", stderr: "" };
324+});
325+326+const result = await runMantisSlackDesktopSmoke({
327+commandRunner: runner,
328+crabboxBin: "/tmp/crabbox",
329+keepLease: false,
330+outputDir: ".artifacts/qa-e2e/mantis/slack-desktop-created-fail",
331+ repoRoot,
332+});
333+334+expect(result.status).toBe("fail");
335+expect(commands).toEqual(
336+expect.arrayContaining([
337+expect.objectContaining({
338+args: ["stop", "--provider", "hetzner", "cbx_fade123"],
339+command: "/tmp/crabbox",
340+}),
341+]),
342+);
343+});
344+277345it("passes gateway setup when Crabbox returns non-zero after remote metadata proves success", async () => {
278346const runner = vi.fn(async (command: string, args: readonly string[]) => {
279347if (command === "/tmp/crabbox" && args[0] === "warmup") {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。