Skip to content

Pure-logic unit tests (PR 2 of 2)#27

Merged
AbsolutOD merged 5 commits into
mainfrom
feature/tests-pure-logic
May 7, 2026
Merged

Pure-logic unit tests (PR 2 of 2)#27
AbsolutOD merged 5 commits into
mainfrom
feature/tests-pure-logic

Conversation

@AbsolutOD

Copy link
Copy Markdown
Owner

Summary

Implements PR 2 of the cleanup-and-tests design (docs/superpowers/specs/2026-05-05-cleanup-and-tests-design.md). All test files use stdlib testing only, table-driven where the function has multiple distinct cases. No production code changes.

Builds on the cleaner shape from PR 1 (#26).

Commits (in order)

  1. test: cover internal/app path builders and initTestGetAppPath and TestGetAppParamPath lock down the /OrgName/Env/AppName/[param] convention and edge cases (empty fields, leading slashes in inputs, slash-containing param names). TestUpdateWithInput pins the comma-list regexp.MustCompile(", *").Split rule. TestCreateEspFile asserts which fields cross from Config to espFile and which don't.
  2. test: cover cmd path/name helpersTestEspName (the spec name; tests formatParamName) pins the actual rule: HasPrefix → unchanged, else OrgPrefix + "_" + ToUpper(n). Hyphens are preserved, not converted to underscores — this surfaces a behavior the design doc described differently; the test pins what the code actually does. TestGetParamPath covers the slash-prefix vs. short-name routing in cmd/get.go. TestGetPathRelative covers the empty-args branch of getPath in cmd/list.go. Adds withOrgPrefix / withAppConfig helpers to swap the package-level globals in and out per test.
  3. test: cover internal/ssm utils and errorsTestSelectType and TestConvertToEspParam (including Secure: true flip on SecureString). One test per checkSSM*Error function plus the dispatcher; each covers typed-error pass-through, the smithy.APIError fallback, and the nil no-match path. TestCheckSSMByPathError pins the asymmetry that this function has no smithy.APIError fallback — generic API errors return nil, unlike its siblings.
  4. test: cover internal/client.New unsupported-backend pathTestNewUnsupportedBackend confirms a non-"ssm" backend returns (nil, error) with the offending backend named in the message. The "ssm" happy path is intentionally not covered (would require AWS credentials or a DI seam — explicitly deferred per the spec's Non-Goals).
  5. chore: refresh CLAUDE.md testing notes — replaces the stale "these four files are empty stubs" paragraph (all four are now populated) with the actual test conventions used in this PR.

Behavior pinned by the new tests (worth a second look)

  • formatParamName does not convert hyphens to underscores; only ToUpper. The spec asked for "hyphens to underscores" but the code preserves hyphens — TestEspName/hyphenated_input... makes this explicit.
  • getPath (cmd/list.go) returns the positional arg verbatim for any non-empty input; only the empty-args branch routes through GetAppPath(). TestGetPathEnvVarName already documented this; TestGetPathRelative adds the empty-args side.
  • checkSSMByPathError has no smithy.APIError fallback. A generic API error from a GetParametersByPath call would return nil from this mapper, which is then handled by mapErr's raw-error fallback — so callers still see the failure. Worth knowing if the dispatch in checkSSMError ever wires GetMany to use it.

Spec deviations

  • The design doc's commit 5 was conditional ("delete unused stub test files (only if the audit during PR 2 finds any)"). All four stubs are populated by commits 1–4, so nothing to delete. The slot is repurposed for the CLAUDE.md docs refresh.

Test Plan

  • go build ./... clean
  • go vet ./... clean
  • go test ./... — every package now reports ok (was several [no test files])
  • No production code modified — git log shows test/docs commits only

AbsolutOD added 5 commits May 6, 2026 18:16
Add table-driven tests for the pure logic in internal/app:

- config_test.go: TestGetAppPath and TestGetAppParamPath cover
  the /OrgName/Env/AppName/[param] convention plus edge cases
  (empty fields, leading slashes in inputs, slash-containing
  param names).
- init_test.go: TestUpdateWithInput pins the comma-list parsing
  rule for Envs (regexp ", *" splits correctly with zero, one,
  or multiple trailing spaces). TestCreateEspFile asserts
  field-by-field that createEspFile copies the espFile-shaped
  fields and ignores Config-only fields like IsEspProject,
  Env, Path, Filename.

Stdlib testing only; no testify.
Fill the empty stubs and extend the existing list test to cover
the pure helpers in the cmd package.

- cmd/put_test.go (was an empty stub): TestEspName pins
  formatParamName's actual rule. Already-prefixed inputs pass
  through (HasPrefix, not exact match — so "ACMEISH" with prefix
  "ACME" is unchanged); other inputs become OrgPrefix + "_" +
  ToUpper(n). Hyphens are preserved as-is, not converted to
  underscores; the test makes that explicit.
- cmd/get_test.go (was an empty stub): TestGetParamPath pins
  the leading-"/" → literal path / short-name → GetAppParamPath
  rule.
- cmd/list_test.go: TestGetPathRelative covers the empty-args
  branch (getPath returns esp.GetAppPath() — the project's
  base path).

Helpers withOrgPrefix and withAppConfig save/restore the
package-level esp global so each test runs in isolation.
Two new test files (no production code change):

- internal/ssm/utils_test.go:
  - TestSelectType — true → SecureString, false → String.
  - TestConvertToEspParam — table covers SecureString (Secure
    flips to true), plain String, StringList (Secure stays
    false — only SecureString flips it), and nil-pointer
    fields rendering as zero values via aws.ToString /
    aws.ToTime.

- internal/ssm/errors_test.go:
  - One test per checkSSM*Error function, table-driven against
    each typed AWS error the function maps. Each table also
    covers a generic smithy.APIError fallthrough case and a
    plain non-API error to assert the no-match-returns-nil
    path.
  - TestCheckSSMByPathError pins the asymmetry that this
    function lacks the smithy.APIError fallback that the
    others have, so a generic API error returns nil.
  - TestCheckSSMError exercises the dispatcher: each known
    action routes to its mapper; unknown actions (e.g.
    GetMany — no case) fall through to checkBaseSSMErrors.

Stdlib testing only.
Fill the empty cmd/client/client_test.go stub with
TestNewUnsupportedBackend: passing a Backend value other than
"ssm" must return a non-nil error, a nil *EspClient, and an
error message that names the offending backend.

A comment in the test file explains why the "ssm" happy path
is intentionally not covered here: it would require AWS
credentials (LoadDefaultConfig) or a dependency-injection
seam, both deferred per the cleanup-and-tests design's
Non-Goals.
The previous note said the four files that had been empty stubs
(cmd/get_test.go, cmd/put_test.go, internal/app/config_test.go,
internal/client/client_test.go) were stubs to satisfy the test
runner. They are all populated now, so replace that paragraph
with the actual test conventions: stdlib testing only, table-
driven for multi-case functions, AWS-side-effect functions
intentionally unit-test-free, and the cmd-package global swap
helpers (withOrgPrefix, withAppConfig).

This replaces the conditional "delete unused stub files" commit
the design doc carved out — the audit found no stubs left to
delete, so the slot is repurposed for the docs refresh.
@AbsolutOD AbsolutOD merged commit 2ff0698 into main May 7, 2026
@AbsolutOD AbsolutOD deleted the feature/tests-pure-logic branch May 7, 2026 01:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant