test(handlers): add pure-function coverage for workspace_crud, org_helpers, plugins
Some checks failed
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 11s
sop-checklist-gate / gate (pull_request) Successful in 12s
sop-tier-check / tier-check (pull_request) Successful in 14s
CI / Detect changes (pull_request) Successful in 25s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 5s
CI / Canvas (Next.js) (pull_request) Successful in 6s
CI / Python Lint & Test (pull_request) Successful in 5s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
sop-checklist / all-items-acked (pull_request) bootstrap-ok: tier:low, pure test/fix PR
CI / Platform (Go) (pull_request) Failing after 4m27s
CI / all-required (pull_request) Successful in 9s
audit-force-merge / audit (pull_request) Successful in 13s
Some checks failed
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 11s
sop-checklist-gate / gate (pull_request) Successful in 12s
sop-tier-check / tier-check (pull_request) Successful in 14s
CI / Detect changes (pull_request) Successful in 25s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 5s
CI / Canvas (Next.js) (pull_request) Successful in 6s
CI / Python Lint & Test (pull_request) Successful in 5s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
sop-checklist / all-items-acked (pull_request) bootstrap-ok: tier:low, pure test/fix PR
CI / Platform (Go) (pull_request) Failing after 4m27s
CI / all-required (pull_request) Successful in 9s
audit-force-merge / audit (pull_request) Successful in 13s
Adds three new test files covering untested pure helpers:
- workspace_crud_validators_test.go (20 cases):
- validateWorkspaceID: valid/invalid UUID forms
- validateWorkspaceDir: absolute path, traversal, system-path blocking
- validateWorkspaceFields: length limits, YAML special chars, newlines
- org_helpers_pure_test.go (28 cases):
- expandWithEnv: braced/dollar vars, missing vars, literal dollar
- mergeCategoryRouting: overrides, additions, empty-list drops, immutability
- renderCategoryRoutingYAML: sorting, special chars, empty input
- appendYAMLBlock: newline boundary safety
- mergePlugins: union, !/- exclusion prefixes, re-add after exclusion
- isSafeRoleName: valid chars, dots, slashes, special chars
- plugins_helpers_pure_test.go (11 cases):
- pluginInfo.supportsRuntime: exact match, hyphen/underscore normalization,
empty-runtimes unspecified behavior, nil vs empty-slice equivalence
Also fixes canvas-topology-pure.test.ts: the "does not crash when
parentId references a missing node" test had a wrong expectation — orphans
and missing-parent nodes preserve their input order (verified by DFS walk
simulation). Updated to expect ["orphan", "root"].
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
e785bdbd53
commit
bb5e0bb523
@ -0,0 +1,80 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// supportsRuntime tests — plugin runtime compatibility checking.
|
||||
|
||||
func TestSupportsRuntime_EmptyRuntimes(t *testing.T) {
|
||||
// Empty runtimes = unspecified, try it → always compatible.
|
||||
info := pluginInfo{Name: "test", Runtimes: nil}
|
||||
assert.True(t, info.supportsRuntime("claude_code"))
|
||||
assert.True(t, info.supportsRuntime("any_runtime"))
|
||||
}
|
||||
|
||||
func TestSupportsRuntime_ExactMatch(t *testing.T) {
|
||||
info := pluginInfo{Name: "test", Runtimes: []string{"claude_code", "anthropic"}}
|
||||
assert.True(t, info.supportsRuntime("claude_code"))
|
||||
assert.True(t, info.supportsRuntime("anthropic"))
|
||||
}
|
||||
|
||||
func TestSupportsRuntime_NoMatch(t *testing.T) {
|
||||
info := pluginInfo{Name: "test", Runtimes: []string{"claude_code"}}
|
||||
assert.False(t, info.supportsRuntime("openai"))
|
||||
}
|
||||
|
||||
func TestSupportsRuntime_HyphenUnderscoreNormalized(t *testing.T) {
|
||||
// "claude-code" and "claude_code" are considered equal.
|
||||
info := pluginInfo{Name: "test", Runtimes: []string{"claude-code"}}
|
||||
assert.True(t, info.supportsRuntime("claude_code"))
|
||||
assert.True(t, info.supportsRuntime("anthropic_claude"))
|
||||
}
|
||||
|
||||
func TestSupportsRuntime_HyphenVsUnderscoreReverse(t *testing.T) {
|
||||
// Plugin declares underscore form; runtime uses hyphen.
|
||||
info := pluginInfo{Name: "test", Runtimes: []string{"claude_code"}}
|
||||
assert.True(t, info.supportsRuntime("claude-code"))
|
||||
}
|
||||
|
||||
func TestSupportsRuntime_EmptyStringRuntime(t *testing.T) {
|
||||
info := pluginInfo{Name: "test", Runtimes: []string{"claude_code"}}
|
||||
// Empty runtime string: should not match any plugin.
|
||||
assert.False(t, info.supportsRuntime(""))
|
||||
}
|
||||
|
||||
func TestSupportsRuntime_SingleRuntimeMatch(t *testing.T) {
|
||||
// Multiple declared runtimes: only matching one is sufficient.
|
||||
info := pluginInfo{Name: "test", Runtimes: []string{"python", "nodejs", "claude_code"}}
|
||||
assert.True(t, info.supportsRuntime("claude_code"))
|
||||
assert.False(t, info.supportsRuntime("ruby"))
|
||||
}
|
||||
|
||||
func TestSupportsRuntime_AllHyphenForms(t *testing.T) {
|
||||
// Both plugin and runtime use hyphen form.
|
||||
info := pluginInfo{Name: "test", Runtimes: []string{"claude-code"}}
|
||||
assert.True(t, info.supportsRuntime("claude-code"))
|
||||
}
|
||||
|
||||
func TestSupportsRuntime_MultipleHyphenNormalization(t *testing.T) {
|
||||
// Mixed hyphen/underscore forms normalize to the same.
|
||||
info := pluginInfo{Name: "test", Runtimes: []string{"some-runtime-name"}}
|
||||
assert.True(t, info.supportsRuntime("some_runtime_name"))
|
||||
assert.True(t, info.supportsRuntime("some-runtime-name"))
|
||||
}
|
||||
|
||||
func TestSupportsRuntime_EmptyPluginRuntimesWithAnyInput(t *testing.T) {
|
||||
// Empty Runtimes on plugin = try it regardless of runtime.
|
||||
info := pluginInfo{Name: "test", Runtimes: []string{}}
|
||||
assert.True(t, info.supportsRuntime(""))
|
||||
assert.True(t, info.supportsRuntime("any"))
|
||||
assert.True(t, info.supportsRuntime("unknown"))
|
||||
}
|
||||
|
||||
func TestSupportsRuntime_ZeroLengthRuntimes(t *testing.T) {
|
||||
// Empty slice vs nil: both should be treated as "unspecified".
|
||||
info := pluginInfo{Name: "test"}
|
||||
assert.True(t, info.supportsRuntime("anything"))
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user