Files
coder/coderd/templatebuilder/catalog_internal_test.go
Michael Suchacz 26e4429362 test: fold near-identical test bodies into tables across eight packages (#29463)
Folds groups of near-identical test bodies (same parent, same parallel
flag, differing only in inputs and expected values) into table-driven
tests in eight packages: `coderd/templatebuilder`, `scripts/develop`,
`agent/agentfiles`, `coderd/x/chatd/chatloop`,
`coderd/x/chatd/chatdebug`, `enterprise/aibridgeproxyd`, `cli`, and
`coderd/database/db2sdk`. One commit per package.

Every case keeps its previous subtest name, `t.Parallel()` placement is
unchanged, and the set of `=== RUN` names is identical except where
standalone `TestX_Y` funcs became `TestX/Y` subtests (chatloop: 9 funcs
into `TestExecuteLocalTools_BatchRuntime`; chatdebug: 15 funcs into two
tables). Members whose bodies differ in more than data stayed as they
were (listed per package in the commit messages). In `agent/agentfiles`
the four `TestFuzzyReplace_*` funcs were already tables, so the shared
request plumbing was hoisted into one helper instead of merging the
funcs and losing their per-rule docs. Net -1035 lines across 9 test
files; runtime is unchanged (all sub-100ms unit tests).

| Package | Diff | Funcs removed | Subtests | RUN lines |
|---|---|---|---|---|
| coderd/templatebuilder | +237 / -291 | 0 | 31 -> 31 | 33 -> 33 |
| scripts/develop | +194 / -246 | 0 | 27 -> 27 | 28 -> 28 |
| agent/agentfiles | +117 / -260 | 0 | unchanged | 58 -> 58 |
| coderd/x/chatd/chatloop | +224 / -306 | 9 | 3 -> 12 | 14 -> 15 |
| coderd/x/chatd/chatdebug | +251 / -537 | 13 | 0 -> 15 | 42 -> 44 |
| enterprise/aibridgeproxyd | +287 / -419 | 0 | 31 -> 31 | 32 -> 32 |
| cli | +143 / -326 | 0 | 15 -> 15 | 16 -> 16 |
| coderd/database/db2sdk | +130 / -233 | 0 | 9 -> 9 | 10 -> 10 |

## Validation

- Per package: `go test -count=1 -tags=testsmallbatch -parallel=8
./<pkg>/ -run <regex> -v` before and after, with the `=== RUN` name sets
diffed
- `go test -race -count=2 -shuffle=on` on each converted test: pass
- `golangci-lint run ./<pkg>/...` with a fresh cache: 0 issues in all
eight packages
- Repository pre-commit hook (including lint/go) passed on every commit

Part of the test-suite speedup series (see #29457); independent of the
other PRs.

## Remote validation

Remote run on a dogfood workspace (separate compute), chat
https://dogfood.cdr.dev/agents/5bbe73d0-866a-4841-9cc3-c5e5b4d97e44,
tested head `d7c55d6b0e8` against base `9d973372774`: all eight packages
pass on the head and under `-race -count=3 -shuffle=on`; package times
are sub-second on both sides (unchanged). `=== RUN` name sets: chatloop
15 to 16 lines with all nine `TestExecuteLocalTools_<X>` leaves
surviving as `TestExecuteLocalTools_BatchRuntime/<X>`; chatdebug 42 to
44; `aibridgeproxyd` `TestNew` 32 to 32, byte-identical sorted list. One
correction to the text above: seven chatdebug leaves are renamed, not
preserved verbatim (`TestRecordingTransport_*UnknownLength*` became
`TestRecordingTransport_UnknownLengthClose/<name without
"UnknownLength">`), so `-run` filters keyed on those old names need
updating. Endorsed verdict: PASS.


> Xum (an AI agent) authored this PR on behalf of @ibetitsmike.
2026-09-17 19:26:18 +02:00

243 lines
5.7 KiB
Go

package templatebuilder
import (
"testing"
"testing/fstest"
"github.com/stretchr/testify/require"
)
func TestParseModulesFromFS(t *testing.T) {
t.Parallel()
t.Run("ValidManifest", func(t *testing.T) {
t.Parallel()
fsys := fstest.MapFS{
"modules/mymod/module.json": &fstest.MapFile{
Data: []byte(`{
"id": "mymod",
"display_name": "My Module",
"description": "A test module.",
"icon": "/icons/mymod.svg",
"category": "IDE",
"tags": ["ide"],
"compatible_os": ["linux"],
"conflicts_with": ["other"],
"pinned_version": "1.2.3",
"variables": [
{
"name": "agent_id",
"type": "string",
"description": "The Coder agent ID.",
"required": true,
"sensitive": false,
"computed": true
},
{
"name": "port",
"type": "number",
"description": "Port number.",
"default": 8080,
"required": false,
"sensitive": false,
"computed": false
},
{
"name": "enable_debug",
"type": "bool",
"description": "Enable debug mode.",
"required": false,
"sensitive": false,
"computed": false
},
{
"name": "api_key",
"type": "string",
"description": "Secret API key.",
"required": true,
"sensitive": true,
"computed": false
}
]
}`),
},
}
modules, err := parseModulesFromFS(fsys)
require.NoError(t, err)
require.Len(t, modules, 1)
m := modules[0]
require.Equal(t, "mymod", m.ID)
require.Equal(t, "My Module", m.DisplayName)
require.Equal(t, "A test module.", m.Description)
require.Equal(t, "/icons/mymod.svg", m.Icon)
require.Equal(t, "IDE", m.Category)
require.Equal(t, []string{"ide"}, m.Tags)
require.Equal(t, []string{"linux"}, m.CompatibleOS)
require.Equal(t, []string{"other"}, m.ConflictsWith)
require.Equal(t, "1.2.3", m.PinnedVersion)
require.Len(t, m.Variables, 4)
// Verify variable types parsed correctly.
require.Equal(t, "string", m.Variables[0].Type)
require.Equal(t, "number", m.Variables[1].Type)
require.Equal(t, "bool", m.Variables[2].Type)
// Verify computed and sensitive fields.
require.True(t, m.Variables[0].Computed)
require.True(t, m.Variables[3].Sensitive)
// Verify default pointer.
require.Nil(t, m.Variables[0].Default)
require.NotNil(t, m.Variables[1].Default)
require.JSONEq(t, "8080", string(m.Variables[1].Default))
})
t.Run("MultipleModules", func(t *testing.T) {
t.Parallel()
fsys := fstest.MapFS{
"modules/alpha/module.json": &fstest.MapFile{
Data: []byte(`{"id": "alpha", "pinned_version": "1.0.0"}`),
},
"modules/beta/module.json": &fstest.MapFile{
Data: []byte(`{"id": "beta", "pinned_version": "2.0.0"}`),
},
}
modules, err := parseModulesFromFS(fsys)
require.NoError(t, err)
require.Len(t, modules, 2)
ids := []string{modules[0].ID, modules[1].ID}
require.Contains(t, ids, "alpha")
require.Contains(t, ids, "beta")
})
t.Run("EmptyCatalog", func(t *testing.T) {
t.Parallel()
fsys := fstest.MapFS{
"modules/.keep": &fstest.MapFile{Data: []byte{}},
}
modules, err := parseModulesFromFS(fsys)
require.NoError(t, err)
require.Empty(t, modules)
})
rejects := []struct {
name string
fsys fstest.MapFS
wantErr string
}{
{
name: "RejectsDirWithoutManifest",
fsys: fstest.MapFS{
"modules/nomod/readme.txt": &fstest.MapFile{Data: []byte("hi")},
},
wantErr: "read nomod/module.json",
},
{
name: "RejectsEmptyID",
fsys: fstest.MapFS{
"modules/bad/module.json": &fstest.MapFile{
Data: []byte(`{"id": "", "pinned_version": "1.0.0"}`),
},
},
wantErr: "empty id",
},
{
name: "RejectsEmptyPinnedVersion",
fsys: fstest.MapFS{
"modules/bad/module.json": &fstest.MapFile{
Data: []byte(`{"id": "bad", "pinned_version": ""}`),
},
},
wantErr: "empty pinned_version",
},
{
name: "RejectsDuplicateID",
fsys: fstest.MapFS{
"modules/a/module.json": &fstest.MapFile{
Data: []byte(`{"id": "dupe", "pinned_version": "1.0.0"}`),
},
"modules/b/module.json": &fstest.MapFile{
Data: []byte(`{"id": "dupe", "pinned_version": "2.0.0"}`),
},
},
wantErr: "duplicate module id",
},
{
name: "RejectsUnknownVariableType",
fsys: fstest.MapFS{
"modules/bad/module.json": &fstest.MapFile{
Data: []byte(`{
"id": "bad",
"pinned_version": "1.0.0",
"variables": [{"name": "x", "type": "list"}]
}`),
},
},
wantErr: `unknown type "list"`,
},
{
name: "RejectsUnknownField",
fsys: fstest.MapFS{
"modules/bad/module.json": &fstest.MapFile{
Data: []byte(`{"id": "bad", "pinned_version": "1.0.0", "dispaly_name": "typo"}`),
},
},
wantErr: "decode",
},
{
name: "RejectsEmptyVariableName",
fsys: fstest.MapFS{
"modules/bad/module.json": &fstest.MapFile{
Data: []byte(`{
"id": "bad",
"pinned_version": "1.0.0",
"variables": [{"name": "", "type": "string"}]
}`),
},
},
wantErr: "empty name",
},
{
name: "RejectsDuplicateVariableName",
fsys: fstest.MapFS{
"modules/bad/module.json": &fstest.MapFile{
Data: []byte(`{
"id": "bad",
"pinned_version": "1.0.0",
"variables": [
{"name": "x", "type": "string"},
{"name": "x", "type": "number"}
]
}`),
},
},
wantErr: "duplicate variable name",
},
{
name: "RejectsInvalidJSON",
fsys: fstest.MapFS{
"modules/bad/module.json": &fstest.MapFile{
Data: []byte(`{not json`),
},
},
wantErr: "decode",
},
}
for _, tc := range rejects {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
_, err := parseModulesFromFS(tc.fsys)
require.ErrorContains(t, err, tc.wantErr)
})
}
}