返回 DeepSeek-Reasonix
slash_resolution_test.go
根目录 / internal / control / slash_resolution_test.go
1 package control
2
3 import (
4 "testing"
5
6 "reasonix/internal/command"
7 "reasonix/internal/skill"
8 )
9
10 func TestResolvedBuiltinDocsSlashNameMatchesRuntimeOwner(t *testing.T) {
11 tests := []struct {
12 name string
13 commands []command.Command
14 skills []skill.Skill
15 owner SlashCommandOwner
16 builtin string
17 }{
18 {name: "unoccupied", owner: SlashOwnerBuiltin, builtin: DocsSlashName},
19 {
20 name: "visible custom command",
21 commands: []command.Command{{Name: DocsSlashName}},
22 owner: SlashOwnerCustom,
23 builtin: ReasonixDocsSlashName,
24 },
25 {
26 name: "hidden plugin command alias",
27 commands: []command.Command{{Name: DocsSlashName, Plugin: "manuals", Hidden: true}},
28 owner: SlashOwnerCustom,
29 builtin: ReasonixDocsSlashName,
30 },
31 {
32 name: "visible project skill",
33 skills: []skill.Skill{{Name: DocsSlashName}},
34 owner: SlashOwnerSkill,
35 builtin: ReasonixDocsSlashName,
36 },
37 {
38 name: "compatible plugin skill alias",
39 skills: []skill.Skill{{Name: DocsSlashName, Plugin: "manuals"}},
40 owner: SlashOwnerSkill,
41 builtin: ReasonixDocsSlashName,
42 },
43 {
44 name: "ambiguous plugin skill aliases",
45 skills: []skill.Skill{
46 {Name: DocsSlashName, Plugin: "manuals"},
47 {Name: DocsSlashName, Plugin: "handbook"},
48 },
49 owner: SlashOwnerBuiltin,
50 builtin: DocsSlashName,
51 },
52 }
53
54 for _, tt := range tests {
55 t.Run(tt.name, func(t *testing.T) {
56 if got := ResolveSlashCommandOwner(DocsSlashName, tt.commands, tt.skills); got != tt.owner {
57 t.Fatalf("owner = %v, want %v", got, tt.owner)
58 }
59 if got := ResolvedBuiltinSlashName(DocsSlashName, tt.commands, tt.skills); got != tt.builtin {
60 t.Fatalf("built-in name = %q, want %q", got, tt.builtin)
61 }
62 if got := IsBuiltinDocsSlash(DocsSlashName, tt.commands, tt.skills); got != (tt.owner == SlashOwnerBuiltin) {
63 t.Fatalf("short built-in = %v, owner=%v", got, tt.owner)
64 }
65 if !IsBuiltinDocsSlash(ReasonixDocsSlashName, tt.commands, tt.skills) {
66 t.Fatal("preferred qualified Reasonix docs name should resolve to the built-in when unoccupied")
67 }
68 })
69 }
70 }
71
72 func TestQualifiedBuiltinDocsSlashPreservesExistingQualifiedCommands(t *testing.T) {
73 commands := []command.Command{
74 {Name: DocsSlashName},
75 {Name: ReasonixDocsSlashName},
76 {Name: "reasonix:builtin:docs"},
77 }
78 want := "reasonix:builtin:docs:2"
79 if got := ResolvedBuiltinSlashName(DocsSlashName, commands, nil); got != want {
80 t.Fatalf("resolved built-in name = %q, want %q", got, want)
81 }
82 for _, existing := range []string{DocsSlashName, ReasonixDocsSlashName, "reasonix:builtin:docs"} {
83 if IsBuiltinDocsSlash(existing, commands, nil) {
84 t.Fatalf("existing command %q was displaced by the built-in", existing)
85 }
86 }
87 if !IsBuiltinDocsSlash(want, commands, nil) {
88 t.Fatalf("generated fallback %q does not resolve to the built-in", want)
89 }
90 }
91
91 lines GO