From 652f523f5ba7b88d2aa365e488b5024f7bea0fd6 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 14 Oct 2025 17:34:26 +0200 Subject: [PATCH] test: improve Git ls-remote parsing tests with uppercase SHA and negative cases Enhanced test coverage to match production code regex pattern and prevent false positives by adding comprehensive edge case testing. **Changes:** 1. **Updated regex pattern to match production code**: - Changed from `/([0-9a-f]{40})\s*\t/` to `/\b([0-9a-fA-F]{40})(?=\s*\t)/` - Now handles both uppercase and lowercase hex characters (A-F and a-f) - Uses word boundary `\b` for more precise matching - Uses lookahead `(?=\s*\t)` instead of capturing whitespace 2. **Added uppercase SHA test**: - Tests extraction of uppercase commit SHA (196D3DF7...) - Normalizes to lowercase using `strtolower()` for comparison - Reflects Git's case-insensitive SHA handling 3. **Added negative test cases**: - Tests output with no commit SHA present (error messages only) - Tests output with tab but invalid SHA format - Ensures `null` is returned to prevent false positives **Test Coverage:** - 8 total tests (up from 5) - Covers all positive cases (lowercase, uppercase, warnings, whitespace) - Covers negative cases (missing SHA, invalid format) - Regex pattern now exactly matches production code in ApplicationDeploymentJob.php:1908 Co-Authored-By: Claude --- tests/Unit/GitLsRemoteParsingTest.php | 38 +++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/tests/Unit/GitLsRemoteParsingTest.php b/tests/Unit/GitLsRemoteParsingTest.php index f4fd2e881..fce51a210 100644 --- a/tests/Unit/GitLsRemoteParsingTest.php +++ b/tests/Unit/GitLsRemoteParsingTest.php @@ -5,7 +5,7 @@ it('extracts commit SHA from git ls-remote output without warnings', function () { $output = "196d3df7665359a8c8fa3329a6bcde0267e550bf\trefs/heads/master"; - preg_match('/([0-9a-f]{40})\s*\t/', $output, $matches); + preg_match('/\b([0-9a-fA-F]{40})(?=\s*\t)/', $output, $matches); $commit = $matches[1] ?? null; expect($commit)->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf'); @@ -14,7 +14,7 @@ it('extracts commit SHA from git ls-remote output with redirect warning on separate line', function () { $output = "warning: redirecting to https://tangled.org/@tangled.org/core/\n196d3df7665359a8c8fa3329a6bcde0267e550bf\trefs/heads/master"; - preg_match('/([0-9a-f]{40})\s*\t/', $output, $matches); + preg_match('/\b([0-9a-fA-F]{40})(?=\s*\t)/', $output, $matches); $commit = $matches[1] ?? null; expect($commit)->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf'); @@ -24,7 +24,7 @@ // This is the actual format from tangled.sh - warning and result on same line, no newline $output = "warning: redirecting to https://tangled.org/@tangled.org/core/196d3df7665359a8c8fa3329a6bcde0267e550bf\trefs/heads/master"; - preg_match('/([0-9a-f]{40})\s*\t/', $output, $matches); + preg_match('/\b([0-9a-fA-F]{40})(?=\s*\t)/', $output, $matches); $commit = $matches[1] ?? null; expect($commit)->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf'); @@ -33,7 +33,7 @@ it('extracts commit SHA from git ls-remote output with multiple warning lines', function () { $output = "warning: redirecting to https://example.org/repo/\ninfo: some other message\n196d3df7665359a8c8fa3329a6bcde0267e550bf\trefs/heads/main"; - preg_match('/([0-9a-f]{40})\s*\t/', $output, $matches); + preg_match('/\b([0-9a-fA-F]{40})(?=\s*\t)/', $output, $matches); $commit = $matches[1] ?? null; expect($commit)->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf'); @@ -42,8 +42,36 @@ it('handles git ls-remote output with extra whitespace', function () { $output = " 196d3df7665359a8c8fa3329a6bcde0267e550bf \trefs/heads/master"; - preg_match('/([0-9a-f]{40})\s*\t/', $output, $matches); + preg_match('/\b([0-9a-fA-F]{40})(?=\s*\t)/', $output, $matches); $commit = $matches[1] ?? null; expect($commit)->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf'); }); + +it('extracts commit SHA with uppercase letters and normalizes to lowercase', function () { + $output = "196D3DF7665359A8C8FA3329A6BCDE0267E550BF\trefs/heads/master"; + + preg_match('/\b([0-9a-fA-F]{40})(?=\s*\t)/', $output, $matches); + $commit = $matches[1] ?? null; + + // Git SHAs are case-insensitive, so we normalize to lowercase for comparison + expect(strtolower($commit))->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf'); +}); + +it('returns null when no commit SHA is present in output', function () { + $output = "warning: redirecting to https://example.org/repo/\nError: repository not found"; + + preg_match('/\b([0-9a-fA-F]{40})(?=\s*\t)/', $output, $matches); + $commit = $matches[1] ?? null; + + expect($commit)->toBeNull(); +}); + +it('returns null when output has tab but no valid SHA', function () { + $output = "invalid-sha-format\trefs/heads/master"; + + preg_match('/\b([0-9a-fA-F]{40})(?=\s*\t)/', $output, $matches); + $commit = $matches[1] ?? null; + + expect($commit)->toBeNull(); +});