



























@@ -119,6 +119,7 @@ describe("mantis Slack desktop smoke runtime", () => {
119119)?.args;
120120expect(runArgs).not.toContain("--no-sync");
121121const remoteScript = runArgs?.at(-1);
122+expect(remoteScript).toContain("hydrate_mode='source'");
122123expect(remoteScript).toContain("${BROWSER:-}");
123124expect(remoteScript).toContain("${CHROME_BIN:-}");
124125expect(remoteScript).toContain("PNPM_STORE_DIR");
@@ -146,15 +147,83 @@ describe("mantis Slack desktop smoke runtime", () => {
146147await expect(fs.readFile(result.videoPath ?? "", "utf8")).resolves.toBe("mp4");
147148const summary = JSON.parse(await fs.readFile(result.summaryPath, "utf8")) as {
148149crabbox: { id: string; vncCommand: string };
150+hydrateMode: string;
149151status: string;
152+timings: { phases: { name: string; status: string }[]; totalMs: number };
150153};
151154expect(summary).toMatchObject({
152155crabbox: {
153156id: "cbx_abc123",
154157vncCommand: "/tmp/crabbox vnc --provider hetzner --id cbx_abc123 --open",
155158},
159+hydrateMode: "source",
156160status: "pass",
157161});
162+expect(summary.timings.totalMs).toBeGreaterThanOrEqual(0);
163+expect(summary.timings.phases.map((phase) => phase.name)).toEqual(
164+expect.arrayContaining([
165+"crabbox.warmup",
166+"crabbox.inspect",
167+"credentials.prepare",
168+"crabbox.remote_run",
169+"artifacts.copy",
170+]),
171+);
172+});
173+174+it("supports prehydrated remote workspaces without installing or building inside the VM", async () => {
175+const commands: { args: readonly string[]; command: string }[] = [];
176+const runner = vi.fn(async (command: string, args: readonly string[]) => {
177+commands.push({ command, args });
178+if (command === "/tmp/crabbox" && args[0] === "inspect") {
179+return {
180+stdout: `${JSON.stringify({
181+ host: "203.0.113.10",
182+ id: "cbx_warm",
183+ provider: "hetzner",
184+ sshKey: "/tmp/key",
185+ sshPort: "2222",
186+ sshUser: "crabbox",
187+ })}\n`,
188+stderr: "",
189+};
190+}
191+if (command === "rsync") {
192+const outputDir = args.at(-1);
193+await fs.mkdir(outputDir as string, { recursive: true });
194+if (!String(outputDir).endsWith("slack-qa/")) {
195+await fs.writeFile(path.join(outputDir as string, "slack-desktop-smoke.png"), "png");
196+await fs.writeFile(
197+path.join(outputDir as string, "remote-metadata.json"),
198+`${JSON.stringify({ hydrateMode: "prehydrated", qaExitCode: 0 })}\n`,
199+);
200+}
201+}
202+return { stdout: "", stderr: "" };
203+});
204+205+const result = await runMantisSlackDesktopSmoke({
206+commandRunner: runner,
207+crabboxBin: "/tmp/crabbox",
208+hydrateMode: "prehydrated",
209+leaseId: "cbx_warm",
210+outputDir: ".artifacts/qa-e2e/mantis/slack-desktop-prehydrated",
211+ repoRoot,
212+});
213+214+expect(result.status).toBe("pass");
215+const remoteScript = commands
216+.find((entry) => entry.command === "/tmp/crabbox" && entry.args[0] === "run")
217+?.args.at(-1);
218+expect(remoteScript).toContain("hydrate_mode='prehydrated'");
219+expect(remoteScript).toContain("hydrate-mode=prehydrated requires node_modules");
220+expect(remoteScript).toContain("hydrate-mode=prehydrated requires a built dist/ directory");
221+const summary = JSON.parse(await fs.readFile(result.summaryPath, "utf8")) as {
222+hydrateMode: string;
223+timings: { phases: { name: string; status: string }[] };
224+};
225+expect(summary.hydrateMode).toBe("prehydrated");
226+expect(summary.timings.phases.map((phase) => phase.name)).not.toContain("crabbox.warmup");
158227});
159228160229it("leases Convex Slack credentials for gateway setup and maps them into the VM env", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。