|
7 | 7 | "path/filepath" |
8 | 8 | "testing" |
9 | 9 |
|
| 10 | + "github.com/databricks/cli/internal/testutil" |
10 | 11 | "github.com/databricks/cli/libs/cmdio" |
| 12 | + "github.com/databricks/cli/libs/dbr" |
11 | 13 | "github.com/databricks/cli/libs/telemetry" |
12 | 14 | "github.com/databricks/cli/libs/telemetry/protos" |
13 | 15 | "github.com/stretchr/testify/assert" |
@@ -132,3 +134,72 @@ func TestRecommendSkillsInstallInteractiveDecline(t *testing.T) { |
132 | 134 | // The prompt is logged when shown, so a declined prompt still counts. |
133 | 135 | assert.Equal(t, []protos.AitoolsHintKind{protos.AitoolsHintKindAppsInitPrompt}, hintKinds(t, ctx)) |
134 | 136 | } |
| 137 | + |
| 138 | +func TestMaybeVersionCheckTip(t *testing.T) { |
| 139 | + noPlugins := func(context.Context) []string { return nil } |
| 140 | + recordedCodexPlugin := func(context.Context) []string { return []string{"codex_0.2.6"} } |
| 141 | + |
| 142 | + for _, tc := range []struct { |
| 143 | + name string |
| 144 | + agentEnv []string |
| 145 | + agentDirs []string |
| 146 | + globalSkills bool |
| 147 | + claudePlugin bool |
| 148 | + projectSkills bool |
| 149 | + agentSkills bool |
| 150 | + fromSubdir bool |
| 151 | + onDBR bool |
| 152 | + installedPlugins func(context.Context) []string |
| 153 | + wantTip bool |
| 154 | + }{ |
| 155 | + {name: "agent without tooling", agentDirs: []string{".codex"}, installedPlugins: noPlugins, wantTip: true}, |
| 156 | + {name: "no agent detected", installedPlugins: noPlugins}, |
| 157 | + {name: "plugin in agent manifest", agentDirs: []string{".claude"}, claudePlugin: true, installedPlugins: noPlugins}, |
| 158 | + {name: "plugin recorded in install state", agentDirs: []string{".codex"}, installedPlugins: recordedCodexPlugin}, |
| 159 | + {name: "global skills", agentDirs: []string{".kiro"}, globalSkills: true, installedPlugins: noPlugins}, |
| 160 | + {name: "project skills", agentDirs: []string{".kiro"}, projectSkills: true, installedPlugins: noPlugins}, |
| 161 | + {name: "project skills at the repository root, run from a subdirectory", agentDirs: []string{".kiro"}, projectSkills: true, fromSubdir: true, installedPlugins: noPlugins}, |
| 162 | + {name: "skills only in the agent's own skills dir", agentDirs: []string{".cursor"}, agentSkills: true, installedPlugins: noPlugins}, |
| 163 | + {name: "databricks runtime", agentDirs: []string{".codex"}, onDBR: true, installedPlugins: noPlugins}, |
| 164 | + {name: "claude code caller is left to MaybeHint", agentEnv: []string{"CLAUDECODE", "1"}, agentDirs: []string{".claude"}, installedPlugins: noPlugins}, |
| 165 | + } { |
| 166 | + t.Run(tc.name, func(t *testing.T) { |
| 167 | + home := t.TempDir() |
| 168 | + testutil.SetAgentEnv(t, append([]string{"HOME", home, "USERPROFILE", home}, tc.agentEnv...)...) |
| 169 | + project := t.TempDir() |
| 170 | + if tc.fromSubdir { |
| 171 | + // The walk up to the repository root stops at the nearest .git. |
| 172 | + require.NoError(t, os.Mkdir(filepath.Join(project, ".git"), 0o755)) |
| 173 | + subdir := filepath.Join(project, "src") |
| 174 | + require.NoError(t, os.Mkdir(subdir, 0o755)) |
| 175 | + t.Chdir(subdir) |
| 176 | + } else { |
| 177 | + t.Chdir(project) |
| 178 | + } |
| 179 | + for _, dir := range tc.agentDirs { |
| 180 | + require.NoError(t, os.MkdirAll(filepath.Join(home, dir), 0o755)) |
| 181 | + } |
| 182 | + if tc.claudePlugin { |
| 183 | + writePluginManifest(t, home, `{"plugins":{"databricks@claude-plugins-official":[{"version":"0.2.6"}]}}`) |
| 184 | + } |
| 185 | + if tc.globalSkills { |
| 186 | + require.NoError(t, os.MkdirAll(filepath.Join(home, CanonicalSkillsDir, "databricks"), 0o755)) |
| 187 | + } |
| 188 | + if tc.projectSkills { |
| 189 | + require.NoError(t, os.MkdirAll(filepath.Join(project, ".kiro", "skills", "databricks-apps"), 0o755)) |
| 190 | + } |
| 191 | + if tc.agentSkills { |
| 192 | + require.NoError(t, os.MkdirAll(filepath.Join(home, ".cursor", "skills", "databricks-apps"), 0o755)) |
| 193 | + } |
| 194 | + |
| 195 | + ctx, stderr := cmdio.NewTestContextWithStderr(t.Context()) |
| 196 | + ctx = dbr.MockRuntime(ctx, dbr.Environment{IsDbr: tc.onDBR}) |
| 197 | + MaybeVersionCheckTip(ctx, tc.installedPlugins) |
| 198 | + if tc.wantTip { |
| 199 | + assert.Equal(t, skillsTipText+"\n", stderr.String()) |
| 200 | + } else { |
| 201 | + assert.Empty(t, stderr.String()) |
| 202 | + } |
| 203 | + }) |
| 204 | + } |
| 205 | +} |
0 commit comments