Skip to content

Commit cfd5407

Browse files
committed
Drive the named-profile merge test through resolveProfile
1 parent f037fac commit cfd5407

1 file changed

Lines changed: 24 additions & 36 deletions

File tree

src/profiles.test.ts

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ function makeTmp(): string {
1616
);
1717
}
1818

19+
async function writeJson(path: string, value: unknown): Promise<void> {
20+
await writeFile(path, JSON.stringify(value));
21+
}
22+
1923
test("profilesDir returns ~/.corbits/profiles", () => {
2024
const result = profilesDir("/home/user");
2125
expect(result).toBe("/home/user/.corbits/profiles");
@@ -35,7 +39,7 @@ test("loadProfile parses valid profile", async () => {
3539
const dir = makeTmp();
3640
await mkdir(dir, { recursive: true });
3741
const path = join(dir, "profile.json");
38-
await writeFile(path, JSON.stringify({ model: "claude-opus-4-8" }));
42+
await writeJson(path, { model: "claude-opus-4-8" });
3943
const result = await loadProfile(path);
4044
expect(result).toEqual({ model: "claude-opus-4-8" });
4145
});
@@ -44,10 +48,9 @@ test("loadProfile parses systemPromptExtensions", async () => {
4448
const dir = makeTmp();
4549
await mkdir(dir, { recursive: true });
4650
const path = join(dir, "profile.json");
47-
await writeFile(
48-
path,
49-
JSON.stringify({ systemPromptExtensions: ["no-destructive-migrations"] }),
50-
);
51+
await writeJson(path, {
52+
systemPromptExtensions: ["no-destructive-migrations"],
53+
});
5154
const result = await loadProfile(path);
5255
expect(result).toEqual({
5356
systemPromptExtensions: ["no-destructive-migrations"],
@@ -58,15 +61,15 @@ test("loadProfile rejects unknown keys", async () => {
5861
const dir = makeTmp();
5962
await mkdir(dir, { recursive: true });
6063
const path = join(dir, "profile.json");
61-
await writeFile(path, JSON.stringify({ model: "x", unknownKey: true }));
64+
await writeJson(path, { model: "x", unknownKey: true });
6265
await expect(loadProfile(path)).rejects.toThrow(/unknownKey must be removed/);
6366
});
6467

6568
test("loadProfile rejects non-array systemPromptExtensions", async () => {
6669
const dir = makeTmp();
6770
await mkdir(dir, { recursive: true });
6871
const path = join(dir, "profile.json");
69-
await writeFile(path, JSON.stringify({ systemPromptExtensions: "bad" }));
72+
await writeJson(path, { systemPromptExtensions: "bad" });
7073
await expect(loadProfile(path)).rejects.toThrow(/systemPromptExtensions/);
7174
});
7275

@@ -101,10 +104,7 @@ test("resolveProfile loads a valid named profile", async () => {
101104
await mkdir(cwd, { recursive: true });
102105
const namedDir = join(home, ".corbits", "profiles");
103106
await mkdir(namedDir, { recursive: true });
104-
await writeFile(
105-
join(namedDir, "work.json"),
106-
JSON.stringify({ model: "named-model" }),
107-
);
107+
await writeJson(join(namedDir, "work.json"), { model: "named-model" });
108108
const result = await resolveProfile(cwd, "work", home);
109109
expect(result.model).toBe("named-model");
110110
expect(result.profile).toBe("work");
@@ -114,13 +114,10 @@ test("resolveProfile applies project profile fields", async () => {
114114
const cwd = makeTmp();
115115
const dir = join(cwd, ".corbits");
116116
await mkdir(dir, { recursive: true });
117-
await writeFile(
118-
join(dir, "profile.json"),
119-
JSON.stringify({
120-
model: "claude-sonnet",
121-
systemPromptExtensions: ["ext1"],
122-
}),
123-
);
117+
await writeJson(join(dir, "profile.json"), {
118+
model: "claude-sonnet",
119+
systemPromptExtensions: ["ext1"],
120+
});
124121
const result = await resolveProfile(cwd);
125122
expect(result.model).toBe("claude-sonnet");
126123
expect(result.systemPromptExtensions).toEqual(["ext1"]);
@@ -132,10 +129,7 @@ test("resolveProfile throws when a named profile key points at a missing file",
132129
const dir = join(cwd, ".corbits");
133130
await mkdir(dir, { recursive: true });
134131
const name = "no-such-named-profile";
135-
await writeFile(
136-
join(dir, "profile.json"),
137-
JSON.stringify({ profile: name }),
138-
);
132+
await writeJson(join(dir, "profile.json"), { profile: name });
139133
const missingPath = join(profilesDir(home), `${name}.json`);
140134
await expect(resolveProfile(cwd, undefined, home)).rejects.toThrow(
141135
missingPath,
@@ -147,25 +141,19 @@ test("resolveProfile: project profile fields override named profile fields", asy
147141
const cwd = makeTmp();
148142
const namedDir = join(home, ".corbits", "profiles");
149143
await mkdir(namedDir, { recursive: true });
150-
await writeFile(
144+
await writeJson(
151145
join(namedDir, "work.json"),
152-
JSON.stringify({ model: "base-model", systemPromptExtensions: ["ext1"] }),
146+
{ model: "base-model", systemPromptExtensions: ["ext1"] },
153147
);
154148
const localDir = join(cwd, ".corbits");
155149
await mkdir(localDir, { recursive: true });
156-
await writeFile(
150+
await writeJson(
157151
join(localDir, "profile.json"),
158-
JSON.stringify({ profile: "work", model: "override-model" }),
152+
{ profile: "work", model: "override-model" },
159153
);
160154

161-
// We can't easily inject profilesDir home in resolveProfile without additional plumbing,
162-
// so test the merge logic directly via the exported functions.
163-
// Project profile model should win over named profile model.
164-
const projectProfile = await loadProfile(join(localDir, "profile.json"));
165-
const namedProfile = await loadProfile(join(namedDir, "work.json"));
166-
const merged = { ...namedProfile };
167-
if (projectProfile?.model !== undefined) merged.model = projectProfile.model;
168-
expect(merged.model).toBe("override-model");
169-
// systemPromptExtensions not in project profile so named profile value survives
170-
expect(merged.systemPromptExtensions).toEqual(["ext1"]);
155+
const result = await resolveProfile(cwd, undefined, home);
156+
expect(result.model).toBe("override-model");
157+
expect(result.systemPromptExtensions).toEqual(["ext1"]);
158+
expect(result.profile).toBe("work");
171159
});

0 commit comments

Comments
 (0)