diff options
| author | Adam Malczewski <[email protected]> | 2026-05-20 15:04:26 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-05-20 15:04:26 +0900 |
| commit | adc8bd185b54935e7a31aae04da3175b7989927a (patch) | |
| tree | 031fa53009a4708ce0cc15c0e3dcb2f2a73cf2d9 /packages/core/tests | |
| parent | 52af4ca33b1f83b8f863a6267d447944f55e729d (diff) | |
| download | dispatch-adc8bd185b54935e7a31aae04da3175b7989927a.tar.gz dispatch-adc8bd185b54935e7a31aae04da3175b7989927a.zip | |
feat: phase 3 — config, skills, model groups, task list, and sidebar UI
- Config system: TOML-based dispatch.toml with hot-reload via chokidar
- Model/key resolution: tag-based model selection, key fallback chains
- Skills system: directory loader with TOML frontmatter, agent mappings
- Task list tool: add/update/list/get operations with WebSocket events
- API routes: GET /config, /skills, /skills/:name, /models, /models/resolve
- Frontend: sidebar with model status, task list, config viewer, skills browser, permission log
- Sliding sidebar animation using CSS transitions (not Svelte transitions)
Diffstat (limited to 'packages/core/tests')
| -rw-r--r-- | packages/core/tests/config/loader.test.ts | 48 |
1 files changed, 25 insertions, 23 deletions
diff --git a/packages/core/tests/config/loader.test.ts b/packages/core/tests/config/loader.test.ts index 9a358fe..5c02326 100644 --- a/packages/core/tests/config/loader.test.ts +++ b/packages/core/tests/config/loader.test.ts @@ -14,25 +14,25 @@ afterEach(() => { rmSync(TMP, { recursive: true, force: true }); }); -function writeYaml(content: string): void { - writeFileSync(join(TMP, "dispatch.yaml"), content, "utf-8"); +function writeToml(content: string): void { + writeFileSync(join(TMP, "dispatch.toml"), content, "utf-8"); } describe("loadConfig", () => { - it("returns empty permissions when dispatch.yaml is missing", () => { + it("returns empty permissions when dispatch.toml is missing", () => { const config = loadConfig(TMP); expect(config.permissions).toEqual({}); }); it("parses simple string permissions", () => { - writeYaml(`permissions:\n read: allow\n edit: deny\n`); + writeToml(`[permissions]\nread = "allow"\nedit = "deny"\n`); const config = loadConfig(TMP); expect(config.permissions["read"]).toBe("allow"); expect(config.permissions["edit"]).toBe("deny"); }); it("parses nested pattern permissions", () => { - writeYaml(`permissions:\n bash:\n "npm test": allow\n "*": ask\n`); + writeToml(`[permissions.bash]\n"npm test" = "allow"\n"*" = "ask"\n`); const config = loadConfig(TMP); const bash = config.permissions["bash"] as Record<string, string>; expect(bash["npm test"]).toBe("allow"); @@ -40,29 +40,27 @@ describe("loadConfig", () => { }); it("ignores comment lines", () => { - writeYaml(`# this is a comment\npermissions:\n # another comment\n read: allow\n`); + writeToml(`# this is a comment\n[permissions]\n# another comment\nread = "allow"\n`); const config = loadConfig(TMP); expect(config.permissions["read"]).toBe("allow"); }); it("handles ~ expansion in nested keys", () => { - const home = homedir(); - writeYaml(`permissions:\n read:\n "~/projects/*": allow\n`); + writeToml(`[permissions.read]\n"~/projects/*" = "allow"\n`); const config = loadConfig(TMP); const read = config.permissions["read"] as Record<string, string>; - expect(read[`${home}/projects/*`]).toBe("allow"); + expect(read["~/projects/*"]).toBe("allow"); }); it("handles $HOME expansion in nested keys", () => { - const home = homedir(); - writeYaml(`permissions:\n read:\n "$HOME/docs/*": allow\n`); + writeToml(`[permissions.read]\n"$HOME/docs/*" = "allow"\n`); const config = loadConfig(TMP); const read = config.permissions["read"] as Record<string, string>; - expect(read[`${home}/docs/*`]).toBe("allow"); + expect(read["$HOME/docs/*"]).toBe("allow"); }); it("parses quoted keys", () => { - writeYaml(`permissions:\n bash:\n "git commit *": allow\n "rm *": deny\n`); + writeToml(`[permissions.bash]\n"git commit *" = "allow"\n"rm *" = "deny"\n`); const config = loadConfig(TMP); const bash = config.permissions["bash"] as Record<string, string>; expect(bash["git commit *"]).toBe("allow"); @@ -70,8 +68,8 @@ describe("loadConfig", () => { }); it("handles multiple permission groups", () => { - writeYaml( - `permissions:\n read: allow\n edit:\n "*": ask\n "src/**": allow\n bash:\n "npm test": allow\n "*": ask\n`, + writeToml( + `[permissions]\nread = "allow"\n\n[permissions.edit]\n"*" = "ask"\n"src/**" = "allow"\n\n[permissions.bash]\n"npm test" = "allow"\n"*" = "ask"\n`, ); const config = loadConfig(TMP); expect(config.permissions["read"]).toBe("allow"); @@ -83,28 +81,32 @@ describe("loadConfig", () => { expect(bash["*"]).toBe("ask"); }); - it("preserves # inside quoted string values", () => { - writeYaml(`permissions:\n bash:\n '"file#1"': allow\n`); + it("preserves # inside quoted string keys", () => { + writeToml(`[permissions.bash]\n"file#1" = "allow"\n`); const config = loadConfig(TMP); const bash = config.permissions["bash"] as Record<string, string>; - expect(bash['"file#1"']).toBe("allow"); + expect(bash["file#1"]).toBe("allow"); }); - it("strips inline comments on nested map keys (empty value after comment)", () => { - writeYaml(`permissions:\n bash: # scripts\n "*": allow\n`); + it("strips inline comments on table headers", () => { + writeToml(`[permissions.bash] # scripts\n"*" = "allow"\n`); const config = loadConfig(TMP); const bash = config.permissions["bash"] as Record<string, string>; expect(bash["*"]).toBe("allow"); }); it("expands ~ with platform path separator", () => { - const home = homedir(); // Simulate a path using the OS separator const pattern = `~${sep}projects${sep}*`; - writeYaml(`permissions:\n read:\n "${pattern}": allow\n`); + writeToml(`[permissions.read]\n"${pattern}" = "allow"\n`); const config = loadConfig(TMP); const read = config.permissions["read"] as Record<string, string>; - expect(read[`${home}${sep}projects${sep}*`]).toBe("allow"); + expect(read[pattern]).toBe("allow"); + }); + + it("throws on TOML parse errors", () => { + writeToml("this is not valid TOML [[["); + expect(() => loadConfig(TMP)).toThrow(); }); }); |
