This repository has been archived on 2026-10-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
maestro/web/src/fastForward.test.ts
T
Miguel Palhas e12baa23c6
ci / flake (push) Successful in 10m50s
ci / web (push) Successful in 1m6s
ci / rust (push) Successful in 5m17s
fix(maestro): fast-forward spawn prefers the focused session's project
N picked the globally freshest project by git-mtime, ignoring the session
the operator was actually on. Plain n's spawn form already seeds from the
focused session (spawnSimilarProjectSeed); fast-forward now matches that,
falling back to recency only when nothing is focused.
2026-09-02 17:36:11 +01:00

120 lines
4.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
buildFastForwardRequest,
fastForwardSeed,
resolveFastForward,
} from "./fastForward.js";
import type { Project, SpawnPreset } from "./types.js";
const presets: SpawnPreset[] = [
{ id: "custom", label: "Custom…", command: "" },
{ id: "claude", label: "Claude", command: "claude" },
];
function project(overrides: Partial<Project>): Project {
return {
path: "/repos/p",
name: "p",
last_activity: new Date().toISOString(),
...overrides,
};
}
describe("resolveFastForward (#67)", () => {
it("resolves every default from the most recent project", () => {
const projects = [
project({ path: "/repos/old", name: "old", last_activity: "2020-01-01T00:00:00Z" }),
project({
path: "/repos/fresh",
name: "fresh",
base_repo: "/repos/fresh",
last_command: "aider",
}),
];
const res = resolveFastForward(projects, presets, "amber-falcon");
expect(res.project?.path).toBe("/repos/fresh");
expect(res.command).toBe("aider");
expect(res.name).toBe("amber-falcon");
const req = buildFastForwardRequest(res)!;
expect(req.cwd).toBe("/repos/fresh");
expect(req.command).toBe("aider");
expect(req.metadata).toEqual({ name: "amber-falcon" });
expect(req.worktree).toEqual({
base_repo: "/repos/fresh",
branch: "amber-falcon",
create_branch: true,
});
});
it("prefers the focused session's project over the freshest one", () => {
const projects = [
project({ path: "/repos/fresh", name: "fresh", last_command: "claude" }),
project({
path: "/repos/current",
name: "current",
last_activity: "2020-01-01T00:00:00Z",
last_command: "zsh",
}),
];
const res = resolveFastForward(projects, presets, "n", "/repos/current");
expect(res.project?.path).toBe("/repos/current");
expect(res.command).toBe("zsh");
});
it("falls back to the freshest project when the focused cwd is unknown", () => {
const projects = [
project({ path: "/repos/old", name: "old", last_activity: "2020-01-01T00:00:00Z" }),
project({ path: "/repos/fresh", name: "fresh" }),
];
const res = resolveFastForward(projects, presets, "n", "/repos/gone");
expect(res.project?.path).toBe("/repos/fresh");
});
it("falls back to the first non-custom preset when there is no last command", () => {
const res = resolveFastForward([project({ last_command: undefined })], presets, "n");
expect(res.command).toBe("claude");
});
it("treats an empty last command as no command", () => {
const res = resolveFastForward([project({ last_command: "" })], [presets[0]], "n");
expect(res.command).toBeUndefined();
expect(buildFastForwardRequest(res)).toBeNull();
});
it("resolves nothing when no projects are known yet", () => {
const res = resolveFastForward([], presets, "n");
expect(res.project).toBeUndefined();
expect(buildFastForwardRequest(res)).toBeNull();
});
it("downgrades to a draft when the generated name is missing", () => {
const res = resolveFastForward([project({ last_command: "claude" })], presets);
expect(res.name).toBeUndefined();
expect(buildFastForwardRequest(res)).toBeNull();
});
it("seeds the fallback draft with whatever did resolve", () => {
const res = resolveFastForward(
[project({ path: "/repos/p", base_repo: "/repos/p", last_command: "aider" })],
presets,
);
expect(fastForwardSeed(res)).toEqual({
cwd: "/repos/p",
command: "aider",
name: "",
worktreeEnabled: true,
worktreeBranch: undefined,
});
});
it("leaves the worktree default alone when not even a project resolved", () => {
// Not `false`: the form defaults the toggle on and a false would stick,
// so the fallback draft would disagree with a normally-opened draft and
// with the TUI's fast path.
const seed = fastForwardSeed(resolveFastForward([], presets));
expect(seed.worktreeEnabled).toBeUndefined();
expect(seed.cwd).toBe("");
});
});