From 4f69cee86b635ff680c77e1216863aa4092912d5 Mon Sep 17 00:00:00 2001 From: Andrew Nesbitt Date: Wed, 23 Sep 2026 17:12:16 +0100 Subject: [PATCH] Return Composer resolution as JSON and detect CLI versions --- composer_test.go | 59 +++++++++++++++++++++++++++++++++++++++ definitions/composer.yaml | 6 +++- 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 composer_test.go diff --git a/composer_test.go b/composer_test.go new file mode 100644 index 0000000..63871c2 --- /dev/null +++ b/composer_test.go @@ -0,0 +1,59 @@ +package managers + +import ( + "context" + "os" + "path/filepath" + "runtime" + "testing" +) + +func TestComposerResolve(t *testing.T) { + runner := NewMockRunner() + detector := NewDetector(NewTranslator(), runner) + detector.Register(embeddedDef(t, "composer")) + mgr, err := detector.Detect(t.TempDir(), DetectOptions{Manager: "composer"}) + if err != nil { + t.Fatal(err) + } + if _, err := mgr.Resolve(context.Background()); err != nil { + t.Fatal(err) + } + want := []string{"composer", "show", "--tree", "--format=json"} + if len(runner.Captured) != 1 || !slicesEqual(runner.Captured[0], want) { + t.Errorf("commands = %v, want [%v]", runner.Captured, want) + } +} + +func TestComposerDetectVersion(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("requires a POSIX shell") + } + def := embeddedDef(t, "composer") + def.Binary = filepath.Join(t.TempDir(), "composer") + script := "#!/bin/sh\n[ \"$#\" = 1 ] && [ \"$1\" = --version ] || exit 1\nprintf '%s\\n' \"$COMPOSER_TEST_OUTPUT\"\n" + if err := os.WriteFile(def.Binary, []byte(script), 0o755); err != nil { + t.Fatal(err) + } + detector := NewDetector(NewTranslator(), NewMockRunner()) + tests := []struct { + output string + want string + }{ + {"Composer version 2.10.3 2026-08-27 13:34:23", "2.10.3"}, + {"Composer version 2.10.0-RC2 2026-05-20 11:00:00", "2.10.0-RC2"}, + {"Composer version 2.11.999-dev+source", "2.11.999-dev+source"}, + } + for _, tt := range tests { + t.Run(tt.want, func(t *testing.T) { + t.Setenv("COMPOSER_TEST_OUTPUT", tt.output) + version, err := detector.DetectVersion(def) + if err != nil { + t.Fatal(err) + } + if version != tt.want { + t.Errorf("version = %q, want %q", version, tt.want) + } + }) + } +} diff --git a/definitions/composer.yaml b/definitions/composer.yaml index 342b5ab..0dcc99b 100644 --- a/definitions/composer.yaml +++ b/definitions/composer.yaml @@ -16,6 +16,10 @@ detection: - composer.json priority: 10 +version_detection: + command: [--version] + pattern: '^Composer version (\S+)' + commands: init: base: [init, -n] @@ -92,7 +96,7 @@ commands: resolve: base: [show] - default_flags: [--tree] + default_flags: [--tree, --format=json] exit_codes: 0: success 1: error