Skip to content

feat(detector): implement FNM detection with mocked tests#1

Merged
dipto0321 merged 1 commit into
mainfrom
feat/detector/implement-fnm
Jun 29, 2026
Merged

feat(detector): implement FNM detection with mocked tests#1
dipto0321 merged 1 commit into
mainfrom
feat/detector/implement-fnm

Conversation

@dipto0321

@dipto0321 dipto0321 commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Summary

Replaces the FNM stub in internal/detector/fnm.go with a real implementation of the detection surface of the Manager interface. Mutation methods (Install, Uninstall, Use, SetDefault, GlobalNpmPrefix) now return a new ErrFNMNotImplemented sentinel rather than a silent zero value.

What's implemented

Method Strategy
Detect() platform.LookupManagerBinary("fnm") != "" — zero subprocesses
Version() fnm --version, parses leading "fnm " token
ListInstalled() fnm list, strips "* " default marker, drops "system" line, returns sorted-asc []semver.Version
Mutation methods Return ErrFNMNotImplemented sentinel

What's tested

internal/detector/fnm_test.go — 21 tests covering:

  • parseFNMVersion: standard output, bare version, trailing whitespace, empty
  • parseFNMInstalled: happy path, unparseable lines skipped, empty input, system-only
  • FNM.Version(): success, RunShell error wrapping, parse error on blank
  • FNM.ListInstalled(): success, RunShell error wrapping
  • FNM.MutationMethods: each returns ErrFNMNotImplemented (errors.Is-verified)
  • FNM.Detect() does not invoke runShell (cheap-probe contract)
  • Stub swaps/restore via withStubShell helper

Live verification

Against the local /opt/homebrew/bin/fnm 1.39.0:

- fnm: version="1.39.0" err=<nil>
  installed=[24.15.0 25.9.0] err=<nil>

The "* system" line in fnm list output is correctly excluded.

Test-stub pattern (for future managers)

fnm.go declares a package-level runShell = platform.RunShell var. Tests use withStubShell(t, ...) to swap it for the duration of the test (auto-restored via t.Cleanup). Future manager implementations (nvm, volta, asdf, mise, n, nodenv, nvm-windows) should follow the same pattern for consistency.

Out of scope (tracked separately)

  • FNM mutation commands (Install, Uninstall, Use, SetDefault, GlobalNpmPrefix) — will land in their own commit when the upgrade command (Phase 4) needs to call them
  • Other manager implementations — next PRs per plan §16

Test plan

  • go build ./...
  • go vet ./...
  • go test -race ./internal/detector/... (21/21 pass)
  • CI green (golangci-lint + commitlint + matrix builds)

Replace the FNM stub with a real implementation of the detection
surface of the Manager interface:

- Detect()       — cheap PATH probe via platform.LookupManagerBinary
- Version()      — wraps `fnm --version`, parses leading "fnm " token
- ListInstalled()— wraps `fnm list`, skips the "system" line and the
                   "*" default marker, returns a non-nil sorted-asc
                   []semver.Version

Mutation methods (Install, Uninstall, Use, SetDefault,
GlobalNpmPrefix) now return the new ErrFNMNotImplemented sentinel
instead of a silent zero value, so callers can use errors.Is to
distinguish "not yet implemented" from "succeeded".

Tests use a package-level runShell var (signature-compatible with
platform.RunShell) that is swapped per-test via withStubShell. The
test-stub pattern intentionally matches what was already established
in detector_test.go for future manager files (nvm, volta, asdf,
mise, n, nodenv, nvm-windows) to follow.

Verified against the local /opt/homebrew/bin/fnm 1.39.0: detected,
version "1.39.0" parsed, installed versions [24.15.0 25.9.0]
returned sorted asc with the "system" line correctly excluded.
@dipto0321 dipto0321 force-pushed the feat/detector/implement-fnm branch from badb145 to 077baae Compare June 29, 2026 06:48
@cocogitto-bot

cocogitto-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown

✔️ 077baae - Conventional commits check succeeded.

@dipto0321 dipto0321 merged commit 90f8257 into main Jun 29, 2026
10 checks passed
@dipto0321 dipto0321 deleted the feat/detector/implement-fnm branch June 29, 2026 06:50
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