test: extract mock fixtures - #28
Conversation
Refactor TestHelpers.php to use dedicated mock classes for better maintainability. - Extract inline anonymous classes to separate MockFilesystem and MockSSHService classes in fixtures/ - Add comprehensive docblocks with usage examples - Organize functions into logical sections with comments - Use match expressions for cleaner conditional logic - Improve defaults and type safety throughout
Extract Laravel Prompts wrappers from ConsoleInputTrait into dedicated PrompterService. - Add PrompterService with all prompt methods and spacing suppression - Update ConsoleInputTrait to delegate to injected PrompterService - Inject PrompterService into BaseCommand constructor - Add MockPrompter fixture for testing - Update all tests to use non-interactive options and mock prompter - Add unit tests for PrompterService ANSI suppression
WalkthroughInjects a new PrompterService into BaseCommand and console commands, refactors ConsoleInputTrait to delegate all prompt calls to the PrompterService, and adds test fixtures and helpers (MockPrompter, MockSSHService, MockFilesystem) plus unit/integration test updates to use the new prompter-based flow. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Command as Console Command
participant Trait as ConsoleInputTrait
participant Prompter as PrompterService
participant LP as Laravel Prompts
User->>Command: run
Command->>Trait: getOptionOrPrompt(name, option)
alt Option present (bool or non-null string)
Trait-->>Command: return option
else Option missing (null)
Trait->>Prompter: promptX(label, ...)
Prompter->>Prompter: emit spacing-suppression (ANSI)
Prompter->>LP: call promptX(...)
LP-->>Prompter: value
Prompter-->>Trait: value
Trait-->>Command: value
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
tests/Fixtures/MockFilesystem.php (1)
47-47: Initialize directories array conditionally for clearer intent.The ternary operator used here works correctly, but the logic could be clearer. Consider using an if-statement or adding a comment to explain why
.deployeris only added whenthrowOnMkdiris false.- $this->directories = $this->throwOnMkdir ? [] : ['.deployer']; + // Pre-populate default directory unless mkdir operations should fail + $this->directories = $this->throwOnMkdir ? [] : ['.deployer'];
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
app/Contracts/BaseCommand.php(2 hunks)app/Services/PrompterService.php(1 hunks)app/Traits/ConsoleInputTrait.php(11 hunks)tests/Fixtures/MockFilesystem.php(1 hunks)tests/Fixtures/MockPrompter.php(1 hunks)tests/Fixtures/MockSSHService.php(1 hunks)tests/Fixtures/TestConsoleCommand.php(2 hunks)tests/Integration/Console/Server/ServerAddCommandTest.php(16 hunks)tests/Integration/Console/Server/ServerDeleteCommandTest.php(2 hunks)tests/Integration/Console/Server/ServerListCommandTest.php(2 hunks)tests/TestHelpers.php(7 hunks)tests/Unit/Contracts/BaseCommandTest.php(4 hunks)tests/Unit/Services/PrompterServiceTest.php(1 hunks)tests/Unit/Traits/ConsoleInputTraitTest.php(2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.php
📄 CodeRabbit inference engine (.cursor/rules/00-main.mdc)
**/*.php: Eliminate single-use private methods by inlining them directly
Cache expensive computed values by initializing them in the constructor instead of recomputing
Prefer direct property access over method calls when appropriate to avoid call overhead
Organize code into comment-separated sections; prefer alphabetical ordering when it does not conflict with logical grouping
**/*.php: Adhere to PSR-12 for all PHP code
Declare strict_types and write code assuming strict typing
Prefer PHP 8.x language features where appropriate (union types, match, attributes, readonly)
Use import statements (use ...) instead of fully qualified class names in code
All methods must have explicit return types, and use proper generics in types (e.g., Collection<int, User>)
Use dependency injection instead of manually resolving or instantiating classes
Prefer Symfony component classes (e.g., Filesystem, Process) over native PHP functions for testability
All object creation must use $container->build(ClassName::class), except value objects, DTOs, and pure data structures
In production code, access the container via constructor injection (no service locator or global access)
Add DocBlock comments with minimalist descriptions, parameters, and return types for classes and functions
Use comments as visual separators with section headers/subheaders and avoid obvious or stale comments
Files:
app/Traits/ConsoleInputTrait.phptests/Unit/Contracts/BaseCommandTest.phptests/Unit/Traits/ConsoleInputTraitTest.phptests/Unit/Services/PrompterServiceTest.phptests/Fixtures/MockPrompter.phptests/Fixtures/MockFilesystem.phptests/Fixtures/TestConsoleCommand.phptests/Fixtures/MockSSHService.phptests/Integration/Console/Server/ServerListCommandTest.phptests/Integration/Console/Server/ServerAddCommandTest.phptests/Integration/Console/Server/ServerDeleteCommandTest.phpapp/Contracts/BaseCommand.phpapp/Services/PrompterService.phptests/TestHelpers.php
app/Traits/ConsoleInputTrait.php
📄 CodeRabbit inference engine (.cursor/rules/03-commands.mdc)
app/Traits/ConsoleInputTrait.php: Add new input-gathering methods to ConsoleInputTrait and implement them using Laravel Prompts; methods should operate via $this->input
ConsoleInputTrait wrappers (promptText, promptPassword, promptConfirm, promptSelect, promptMultiselect, promptSuggest, promptSearch, promptPause, promptSpin) should call Laravel Prompts and suppress extra spacing
Files:
app/Traits/ConsoleInputTrait.php
{tests/**,test/**,**/*@(Test|Spec).php}
📄 CodeRabbit inference engine (.cursor/rules/00-main.mdc)
Do not run or edit tests unless explicitly instructed
Files:
tests/Unit/Contracts/BaseCommandTest.phptests/Unit/Traits/ConsoleInputTraitTest.phptests/Unit/Services/PrompterServiceTest.phptests/Fixtures/MockPrompter.phptests/Fixtures/MockFilesystem.phptests/Fixtures/TestConsoleCommand.phptests/Fixtures/MockSSHService.phptests/Integration/Console/Server/ServerListCommandTest.phptests/Integration/Console/Server/ServerAddCommandTest.phptests/Integration/Console/Server/ServerDeleteCommandTest.phptests/TestHelpers.php
tests/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)
tests/**/*.php: In tests, it's allowed to instantiate the Container directly for isolation
Exclude tests from PHPStan static analysis
tests/**/*.php: Write Pest tests usingit()syntax
In unit tests, prefer manual instantiation with explicit mocks (e.g.,new ClassName(...)) over using the DI container
Use the DI container only in integration tests when verifying multiple services together or DI configuration
DI container conventions for production do not apply to tests
Apply the AAA pattern (Arrange, Act, Assert) in every test
For exception tests, combine phases with a// ACT & ASSERTcomment when the act triggers the assertion
Organize tests withdescribe()blocks and shared setup viabeforeEach(); extract helpers/traits for DRY tests
Keep test files under 1.8x the size of the source they test, without sacrificing readability
Focus tests on core business logic; avoid testing the framework itself
Use dataset-driven testing with->with([])for multiple scenarios
Eliminate overlap: avoid multiple tests covering the same functionality
Consolidate assertions using chained expectations (e.g.,expect($x)->toBe(1)->and($y)->toBe(2))
Mock only external dependencies; do not perform real I/O in unit tests
Avoid performance tests unless performance is the primary concern
Forbidden in tests:toBeInstanceOf(...),toBeArray(), genericnot->toBeNull(),expect(true)->toBeTrue(), andsleep(...)(use time mocking)
Prefer meaningful assertions on behavior and values (e.g., checking specific config values, validator outcomes, and configured mock interactions)
Unit tests: mock all external dependencies, test single units in isolation, complete in milliseconds
Integration tests: allow real file operations and external processes; cover CLI commands and full workflows
Do not run or gate tests on PHPStan compliance; ignore PHPStan issues in tests and avoid excessive phpdoc just for types
Files:
tests/Unit/Contracts/BaseCommandTest.phptests/Unit/Traits/ConsoleInputTraitTest.phptests/Unit/Services/PrompterServiceTest.phptests/Fixtures/MockPrompter.phptests/Fixtures/MockFilesystem.phptests/Fixtures/TestConsoleCommand.phptests/Fixtures/MockSSHService.phptests/Integration/Console/Server/ServerListCommandTest.phptests/Integration/Console/Server/ServerAddCommandTest.phptests/Integration/Console/Server/ServerDeleteCommandTest.phptests/TestHelpers.php
app/Contracts/BaseCommand.php
📄 CodeRabbit inference engine (.cursor/rules/03-commands.mdc)
Keep BaseCommand limited to shared initialization, configuration, and orchestration logic; do not implement individual I/O operations here
Files:
app/Contracts/BaseCommand.php
🧠 Learnings (3)
📚 Learning: 2025-10-04T12:08:48.838Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-04T12:08:48.838Z
Learning: Applies to app/Traits/ConsoleInputTrait.php : ConsoleInputTrait wrappers (promptText, promptPassword, promptConfirm, promptSelect, promptMultiselect, promptSuggest, promptSearch, promptPause, promptSpin) should call Laravel Prompts and suppress extra spacing
Applied to files:
app/Traits/ConsoleInputTrait.phptests/Unit/Traits/ConsoleInputTraitTest.phptests/Unit/Services/PrompterServiceTest.phpapp/Services/PrompterService.php
📚 Learning: 2025-10-04T12:08:48.838Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-04T12:08:48.838Z
Learning: Applies to app/Traits/ConsoleInputTrait.php : Add new input-gathering methods to ConsoleInputTrait and implement them using Laravel Prompts; methods should operate via $this->input
Applied to files:
app/Traits/ConsoleInputTrait.phpapp/Services/PrompterService.php
📚 Learning: 2025-10-04T12:08:48.838Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-04T12:08:48.838Z
Learning: Use laravel/prompts for all user interactions (text, password, confirm, select, multiselect, suggest, search, spin) rather than raw Symfony IO
Applied to files:
app/Traits/ConsoleInputTrait.phpapp/Services/PrompterService.php
🧬 Code graph analysis (13)
app/Traits/ConsoleInputTrait.php (2)
app/Services/PrompterService.php (9)
text(33-51)password(56-72)confirm(77-93)pause(98-103)select(110-128)multiselect(138-158)suggest(165-187)search(192-210)spin(221-229)tests/Fixtures/MockPrompter.php (9)
text(41-54)password(59-71)confirm(76-88)pause(93-100)select(107-120)multiselect(130-144)suggest(151-166)search(171-184)spin(195-201)
tests/Unit/Contracts/BaseCommandTest.php (5)
app/Services/PrompterService.php (1)
PrompterService(24-246)app/Contracts/BaseCommand.php (1)
__construct(36-45)tests/Fixtures/MockPrompter.php (1)
__construct(30-32)tests/Fixtures/TestConsoleCommand.php (1)
__construct(32-41)tests/TestHelpers.php (1)
mockPrompter(258-269)
tests/Unit/Traits/ConsoleInputTraitTest.php (1)
tests/Fixtures/TestConsoleCommand.php (2)
setTestMethod(46-50)execute(61-92)
tests/Unit/Services/PrompterServiceTest.php (2)
app/Services/PrompterService.php (10)
PrompterService(24-246)text(33-51)password(56-72)confirm(77-93)pause(98-103)select(110-128)multiselect(138-158)suggest(165-187)search(192-210)spin(221-229)tests/Fixtures/MockPrompter.php (9)
text(41-54)password(59-71)confirm(76-88)pause(93-100)select(107-120)multiselect(130-144)suggest(151-166)search(171-184)spin(195-201)
tests/Fixtures/MockPrompter.php (4)
app/Services/PrompterService.php (10)
PrompterService(24-246)text(33-51)password(56-72)confirm(77-93)pause(98-103)select(110-128)multiselect(138-158)suggest(165-187)search(192-210)spin(221-229)app/Contracts/BaseCommand.php (1)
__construct(36-45)tests/Fixtures/TestConsoleCommand.php (1)
__construct(32-41)tests/Unit/Contracts/BaseCommandTest.php (1)
__construct(27-37)
tests/Fixtures/TestConsoleCommand.php (3)
app/Contracts/BaseCommand.php (1)
__construct(36-45)tests/Fixtures/MockPrompter.php (1)
__construct(30-32)tests/Unit/Contracts/BaseCommandTest.php (1)
__construct(27-37)
tests/Fixtures/MockSSHService.php (1)
app/Services/SSHService.php (1)
SSHService(40-327)
tests/Integration/Console/Server/ServerListCommandTest.php (3)
app/DTOs/ServerDTO.php (1)
ServerDTO(7-17)app/Repositories/ServerRepository.php (2)
ServerRepository(15-168)loadInventory(31-43)tests/TestHelpers.php (2)
mockSSHService(203-209)mockPrompter(258-269)
tests/Integration/Console/Server/ServerAddCommandTest.php (3)
app/Repositories/ServerRepository.php (2)
ServerRepository(15-168)loadInventory(31-43)tests/TestHelpers.php (2)
mockSSHService(203-209)mockPrompter(258-269)app/Console/Server/ServerAddCommand.php (1)
execute(50-202)
tests/Integration/Console/Server/ServerDeleteCommandTest.php (2)
app/Repositories/ServerRepository.php (2)
ServerRepository(15-168)loadInventory(31-43)tests/TestHelpers.php (1)
mockPrompter(258-269)
app/Contracts/BaseCommand.php (1)
app/Services/PrompterService.php (1)
PrompterService(24-246)
app/Services/PrompterService.php (1)
tests/Fixtures/MockPrompter.php (9)
confirm(76-88)multiselect(130-144)password(59-71)pause(93-100)search(171-184)select(107-120)spin(195-201)suggest(151-166)text(41-54)
tests/TestHelpers.php (4)
tests/Fixtures/MockFilesystem.php (2)
MockFilesystem(28-132)exists(53-83)tests/Fixtures/MockPrompter.php (9)
MockPrompter(16-202)text(41-54)password(59-71)confirm(76-88)select(107-120)multiselect(130-144)suggest(151-166)search(171-184)pause(93-100)tests/Fixtures/MockSSHService.php (1)
MockSSHService(27-87)tests/Fixtures/TestConsoleCommand.php (1)
TestConsoleCommand(25-236)
🪛 GitHub Actions: Pint
app/Services/PrompterService.php
[error] 1-1: Pint PSR-12 style issue: no_extra_blank_lines, blank_line_between…
🪛 PHPMD (2.15.0)
tests/Fixtures/MockPrompter.php
43-43: Avoid unused parameters such as '$placeholder'. (undefined)
(UnusedFormalParameter)
44-44: Avoid unused parameters such as '$default'. (undefined)
(UnusedFormalParameter)
45-45: Avoid unused parameters such as '$required'. (undefined)
(UnusedFormalParameter)
46-46: Avoid unused parameters such as '$validate'. (undefined)
(UnusedFormalParameter)
47-47: Avoid unused parameters such as '$hint'. (undefined)
(UnusedFormalParameter)
61-61: Avoid unused parameters such as '$placeholder'. (undefined)
(UnusedFormalParameter)
62-62: Avoid unused parameters such as '$required'. (undefined)
(UnusedFormalParameter)
63-63: Avoid unused parameters such as '$validate'. (undefined)
(UnusedFormalParameter)
64-64: Avoid unused parameters such as '$hint'. (undefined)
(UnusedFormalParameter)
78-78: Avoid unused parameters such as '$default'. (undefined)
(UnusedFormalParameter)
79-79: Avoid unused parameters such as '$yes'. (undefined)
(UnusedFormalParameter)
80-80: Avoid unused parameters such as '$no'. (undefined)
(UnusedFormalParameter)
81-81: Avoid unused parameters such as '$hint'. (undefined)
(UnusedFormalParameter)
93-93: Avoid unused parameters such as '$message'. (undefined)
(UnusedFormalParameter)
109-109: Avoid unused parameters such as '$options'. (undefined)
(UnusedFormalParameter)
110-110: Avoid unused parameters such as '$default'. (undefined)
(UnusedFormalParameter)
111-111: Avoid unused parameters such as '$scroll'. (undefined)
(UnusedFormalParameter)
112-112: Avoid unused parameters such as '$validate'. (undefined)
(UnusedFormalParameter)
113-113: Avoid unused parameters such as '$hint'. (undefined)
(UnusedFormalParameter)
132-132: Avoid unused parameters such as '$options'. (undefined)
(UnusedFormalParameter)
133-133: Avoid unused parameters such as '$default'. (undefined)
(UnusedFormalParameter)
134-134: Avoid unused parameters such as '$scroll'. (undefined)
(UnusedFormalParameter)
135-135: Avoid unused parameters such as '$required'. (undefined)
(UnusedFormalParameter)
136-136: Avoid unused parameters such as '$validate'. (undefined)
(UnusedFormalParameter)
137-137: Avoid unused parameters such as '$hint'. (undefined)
(UnusedFormalParameter)
153-153: Avoid unused parameters such as '$options'. (undefined)
(UnusedFormalParameter)
154-154: Avoid unused parameters such as '$placeholder'. (undefined)
(UnusedFormalParameter)
155-155: Avoid unused parameters such as '$default'. (undefined)
(UnusedFormalParameter)
156-156: Avoid unused parameters such as '$scroll'. (undefined)
(UnusedFormalParameter)
157-157: Avoid unused parameters such as '$required'. (undefined)
(UnusedFormalParameter)
158-158: Avoid unused parameters such as '$validate'. (undefined)
(UnusedFormalParameter)
159-159: Avoid unused parameters such as '$hint'. (undefined)
(UnusedFormalParameter)
173-173: Avoid unused parameters such as '$options'. (undefined)
(UnusedFormalParameter)
174-174: Avoid unused parameters such as '$placeholder'. (undefined)
(UnusedFormalParameter)
175-175: Avoid unused parameters such as '$scroll'. (undefined)
(UnusedFormalParameter)
176-176: Avoid unused parameters such as '$validate'. (undefined)
(UnusedFormalParameter)
177-177: Avoid unused parameters such as '$hint'. (undefined)
(UnusedFormalParameter)
197-197: Avoid unused parameters such as '$message'. (undefined)
(UnusedFormalParameter)
tests/Fixtures/MockSSHService.php
35-35: Avoid unused parameters such as '$host'. (undefined)
(UnusedFormalParameter)
36-36: Avoid unused parameters such as '$port'. (undefined)
(UnusedFormalParameter)
37-37: Avoid unused parameters such as '$username'. (undefined)
(UnusedFormalParameter)
38-38: Avoid unused parameters such as '$privateKeyPath'. (undefined)
(UnusedFormalParameter)
47-47: Avoid unused parameters such as '$host'. (undefined)
(UnusedFormalParameter)
48-48: Avoid unused parameters such as '$port'. (undefined)
(UnusedFormalParameter)
49-49: Avoid unused parameters such as '$username'. (undefined)
(UnusedFormalParameter)
50-50: Avoid unused parameters such as '$command'. (undefined)
(UnusedFormalParameter)
51-51: Avoid unused parameters such as '$privateKeyPath'. (undefined)
(UnusedFormalParameter)
57-57: Avoid unused parameters such as '$host'. (undefined)
(UnusedFormalParameter)
58-58: Avoid unused parameters such as '$port'. (undefined)
(UnusedFormalParameter)
59-59: Avoid unused parameters such as '$username'. (undefined)
(UnusedFormalParameter)
60-60: Avoid unused parameters such as '$scriptPath'. (undefined)
(UnusedFormalParameter)
61-61: Avoid unused parameters such as '$privateKeyPath'. (undefined)
(UnusedFormalParameter)
67-67: Avoid unused parameters such as '$host'. (undefined)
(UnusedFormalParameter)
68-68: Avoid unused parameters such as '$port'. (undefined)
(UnusedFormalParameter)
69-69: Avoid unused parameters such as '$username'. (undefined)
(UnusedFormalParameter)
70-70: Avoid unused parameters such as '$localPath'. (undefined)
(UnusedFormalParameter)
71-71: Avoid unused parameters such as '$remotePath'. (undefined)
(UnusedFormalParameter)
72-72: Avoid unused parameters such as '$privateKeyPath'. (undefined)
(UnusedFormalParameter)
78-78: Avoid unused parameters such as '$host'. (undefined)
(UnusedFormalParameter)
79-79: Avoid unused parameters such as '$port'. (undefined)
(UnusedFormalParameter)
80-80: Avoid unused parameters such as '$username'. (undefined)
(UnusedFormalParameter)
81-81: Avoid unused parameters such as '$remotePath'. (undefined)
(UnusedFormalParameter)
82-82: Avoid unused parameters such as '$localPath'. (undefined)
(UnusedFormalParameter)
83-83: Avoid unused parameters such as '$privateKeyPath'. (undefined)
(UnusedFormalParameter)
🔇 Additional comments (30)
tests/Integration/Console/Server/ServerAddCommandTest.php (2)
18-33: LGTM!The test helper correctly wires the new prompter dependency and passes all required dependencies to
ServerAddCommand. The use ofmockPrompter()ensures tests run non-interactively.
44-71: Confirmed CLI options coverage for non-interactive execution
ServerAddCommand defines all required options (--name,--host,--port,--username,--private-key-path,--skip,--yes); non-interactive runs will skip prompts.tests/Unit/Traits/ConsoleInputTraitTest.php (2)
120-122: LGTM!The note correctly reflects that spacing suppression is now handled by
PrompterServiceinternally, andMockPrompteroutputs no ANSI sequences in tests. This aligns with the broader refactoring.
36-47: Confirm empty string handling in commands
ServerAddCommandusesdefault: ''forprivate-key-pathand then normalizes''tonull, so providing--private-key-path=''yields the intendednullvalue. Tests correctly reflect this behavior.tests/Integration/Console/Server/ServerListCommandTest.php (1)
18-46: LGTM!The test helper correctly wires the new prompter dependency, consistent with changes in other integration tests.
app/Traits/ConsoleInputTrait.php (3)
56-59: LGTM!The updated boolean handling correctly treats both
trueandfalseas valid option values. This is more correct than the previous implementation which may have only consideredtrueas provided.
87-103: LGTM!All prompt wrapper methods correctly delegate to
$this->prompterinstead of calling global Laravel Prompts functions directly. This aligns with the broader refactoring to centralize prompt handling throughPrompterService.Based on learnings.
61-68: Empty string options are intentionally supported and correctly handled (e.g.,--private-key-path=''→ null in ServerAddCommand).app/Contracts/BaseCommand.php (1)
11-11: LGTM!The
PrompterServicedependency is correctly injected via constructor using property promotion, following Symfony DI best practices. This makes the prompter available to all commands extendingBaseCommandand aligns with the trait's requirement for a$prompterproperty.As per coding guidelines.
Also applies to: 42-42
tests/Fixtures/TestConsoleCommand.php (1)
12-12: LGTM!The test fixture correctly accepts and propagates the
PrompterServicedependency to the parentBaseCommandconstructor, maintaining consistency with the production code changes.Also applies to: 38-40
tests/Unit/Services/PrompterServiceTest.php (2)
14-36: Verify test behavior in different terminal environments.The test captures raw output and asserts ANSI escape sequences are present. This approach works for testing spacing suppression but may be fragile in different terminal environments or CI systems where TTY detection behaves differently.
Consider running this test in your CI environment to ensure it behaves consistently. If it fails intermittently, you may need to mock the output or adjust the test strategy.
Based on learnings.
78-102: LGTM!The test correctly verifies that
spin()does not callsuppressPromptSpacing()and returns the callback result. The assertions check both the absence of ANSI sequences and the proper callback execution.tests/Integration/Console/Server/ServerDeleteCommandTest.php (2)
8-8: LGTM!The addition of the
ServerRepositoryimport eliminates the need for fully qualified names, improving readability.
38-44: LGTM!The integration of
mockPrompter()correctly wires the newPrompterServicedependency into the command. Since all tests use--yesto bypass interactive prompts, the empty mock prompter is appropriate for these non-interactive test scenarios.tests/Unit/Contracts/BaseCommandTest.php (2)
12-12: LGTM!The PrompterService import and constructor updates correctly implement the new dependency injection pattern for BaseCommand testing.
Also applies to: 33-36
65-68: LGTM!Both test cases correctly instantiate the mock prompter and wire it into the TestableBaseCommand. The empty mock is appropriate since these tests focus on command configuration and execution flow rather than prompt interactions.
Also applies to: 87-88
tests/Fixtures/MockSSHService.php (1)
1-87: LGTM!The MockSSHService fixture is well-designed for testing SSH-dependent code paths without network I/O. The configurable connection behavior enables both success and failure scenarios.
Note: The PHPMD warnings about unused parameters are false positives. Mock implementations must preserve method signatures for substitutability, even when parameters aren't used internally.
app/Services/PrompterService.php (2)
23-229: LGTM!The PrompterService provides a clean, injectable wrapper around Laravel Prompts functions. The design correctly:
- Enables dependency injection and testability
- Suppresses extra spacing for all interactive prompts (text, password, confirm, pause, select, multiselect, suggest, search)
- Preserves spinner behavior by not suppressing spacing for
spin()Based on learnings.
240-245: LGTM!The ANSI escape sequence implementation correctly addresses the extra newline that Laravel Prompts adds before each prompt. The approach is clean and maintains a consistent user experience.
tests/Fixtures/MockPrompter.php (1)
1-202: LGTM!The MockPrompter fixture provides excellent test infrastructure:
- Queue-based design enables deterministic testing with predefined responses
- Clear error messages when queues are exhausted aid test debugging
- The
spin()implementation correctly executes callbacks without displaying spinners in tests- All methods maintain API compatibility with PrompterService
Note: PHPMD warnings about unused parameters are false positives—mock implementations must preserve method signatures for substitutability.
tests/TestHelpers.php (10)
13-15: LGTM!The addition of fixture imports and section headers significantly improves code organization and adheres to the coding guidelines for comment-separated sections.
Also applies to: 21-23, 46-48, 100-102, 304-306, 344-346
50-73: LGTM!The
mockFilesystem()helper is well-designed with clear examples demonstrating both basic usage and error simulation scenarios.
75-98: LGTM!The
mockFilesystemService()helper correctly wrapsmockFilesystem()to provide a higher-level service mock, maintaining consistency with the existing helper patterns.
155-171: LGTM!The enhanced
mockInventoryService()helper now accepts both array data (auto-converted to YAML) and raw YAML strings, providing flexibility for different testing scenarios. The match expression handles all cases cleanly.
192-210: LGTM!The
mockSSHService()helper provides a real SSHService instance with mocked dependencies, enabling tests that depend on SSHService without requiring network calls.
212-232: LGTM!The
mockSSHServiceWithBehavior()helper enables behavior-driven testing by allowing tests to simulate both successful and failed SSH connections. The clear examples demonstrate the intended usage patterns.
234-270: LGTM!The
mockPrompter()helper provides a clean factory function for creating MockPrompter instances with predefined prompt responses. The design enables deterministic testing of interactive command flows. The comprehensive examples demonstrate various usage patterns.
289-301: LGTM!The match expression in
mockVersionService()cleanly handles all constructor parameter combinations, improving upon the previous implementation.
328-342: LGTM!The
mockServerRepository()helper correctly accepts both array and string data (matching the updatedmockInventoryService()signature) and returns a fully initialized repository ready for use in tests.
368-382: LGTM!The
mockTestConsoleCommand()helper now correctly wires themockPrompter()dependency, completing the integration of the PrompterService across the test infrastructure.
Update exists() and getContents() to support basename matching alongside path suffix matching. This allows more flexible mocking of files by name without requiring full path specification, improving test usability.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
app/Services/PrompterService.php (1)
1-246: Formatting issue already flagged.The Pint/PSR-12 formatting violations have been identified in a previous review comment. Please address those style issues before merging.
🧹 Nitpick comments (3)
tests/Fixtures/MockFilesystem.php (2)
47-47: Document the magic.deployerdirectory initialization.The default initialization of the
.deployerdirectory is undocumented and may cause confusion. If tests depend on this directory existing by default, it should be documented in the class docblock or made explicit via a constructor parameter.Consider either:
- Documenting this behavior in the class docblock with an explanation of why
.deployeris special, or- Removing the magic initialization and requiring tests to explicitly call
mkdir('.deployer')when needed+ /** + * @param bool $initialExists Whether the initial file should exist + * @param string $initialContent Content of the initial file + * @param bool $throwOnRead Simulate read permission errors + * @param bool $throwOnMkdir Simulate directory creation errors + * @param bool $throwOnDump Simulate write errors + * @param string $initialPath Path of the initial file + * + * Note: The .deployer directory is pre-created by default unless throwOnMkdir is true. + */ public function __construct(
69-74: Clarify the assumptions about stored file keys.The matching logic assumes that keys in
$this->filesare simple filenames (e.g.,'config.yml') rather than paths with directories (e.g.,'config/app.yml'). Thebasename($files) === $storedPathcheck on line 71 would not work correctly if$storedPathcontains directory separators.Consider documenting this assumption in the class docblock or adding validation in the constructor/dumpFile():
/** * Mock filesystem for testing with error simulation and in-memory storage. * * Simulates filesystem operations without touching disk, supporting: * - File existence checks with path matching + * - File keys should be simple filenames without directory separators * - File read/write operationsOr add validation when storing files:
public function dumpFile(string $filename, mixed $content): void { if ($this->throwOnDump) { throw new IOException('Write failed', 0, null, $filename); } + // Store using basename for consistent key format + $key = basename($filename); - $this->files[$filename] = (string) $content; + $this->files[$key] = (string) $content; }app/Services/PrompterService.php (1)
1-246: LGTM! Clean wrapper enabling DI and testability.The implementation correctly wraps Laravel Prompts functions and centralizes spacing suppression as intended. The architecture is sound:
- Enables dependency injection and mocking (as demonstrated by MockPrompter test fixture)
- Consistent method signatures with proper type hints and docblocks
- Correctly omits spacing suppression for
spin()since spinners manage their own output- Follows coding guidelines (strict types, explicit return types, proper generics, section comments)
Optional nitpick: The docblock comment on line 236 uses informal language ("annoying newline"). While clear and accurate, a more professional tone like "Suppress the extra newline that Laravel Prompts inserts before prompts" would better align with typical API documentation standards.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
app/Services/PrompterService.php(1 hunks)tests/Fixtures/MockFilesystem.php(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.php
📄 CodeRabbit inference engine (.cursor/rules/00-main.mdc)
**/*.php: Eliminate single-use private methods by inlining them directly
Cache expensive computed values by initializing them in the constructor instead of recomputing
Prefer direct property access over method calls when appropriate to avoid call overhead
Organize code into comment-separated sections; prefer alphabetical ordering when it does not conflict with logical grouping
**/*.php: Adhere to PSR-12 for all PHP code
Declare strict_types and write code assuming strict typing
Prefer PHP 8.x language features where appropriate (union types, match, attributes, readonly)
Use import statements (use ...) instead of fully qualified class names in code
All methods must have explicit return types, and use proper generics in types (e.g., Collection<int, User>)
Use dependency injection instead of manually resolving or instantiating classes
Prefer Symfony component classes (e.g., Filesystem, Process) over native PHP functions for testability
All object creation must use $container->build(ClassName::class), except value objects, DTOs, and pure data structures
In production code, access the container via constructor injection (no service locator or global access)
Add DocBlock comments with minimalist descriptions, parameters, and return types for classes and functions
Use comments as visual separators with section headers/subheaders and avoid obvious or stale comments
Files:
app/Services/PrompterService.phptests/Fixtures/MockFilesystem.php
{tests/**,test/**,**/*@(Test|Spec).php}
📄 CodeRabbit inference engine (.cursor/rules/00-main.mdc)
Do not run or edit tests unless explicitly instructed
Files:
tests/Fixtures/MockFilesystem.php
tests/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)
tests/**/*.php: In tests, it's allowed to instantiate the Container directly for isolation
Exclude tests from PHPStan static analysis
tests/**/*.php: Write Pest tests usingit()syntax
In unit tests, prefer manual instantiation with explicit mocks (e.g.,new ClassName(...)) over using the DI container
Use the DI container only in integration tests when verifying multiple services together or DI configuration
DI container conventions for production do not apply to tests
Apply the AAA pattern (Arrange, Act, Assert) in every test
For exception tests, combine phases with a// ACT & ASSERTcomment when the act triggers the assertion
Organize tests withdescribe()blocks and shared setup viabeforeEach(); extract helpers/traits for DRY tests
Keep test files under 1.8x the size of the source they test, without sacrificing readability
Focus tests on core business logic; avoid testing the framework itself
Use dataset-driven testing with->with([])for multiple scenarios
Eliminate overlap: avoid multiple tests covering the same functionality
Consolidate assertions using chained expectations (e.g.,expect($x)->toBe(1)->and($y)->toBe(2))
Mock only external dependencies; do not perform real I/O in unit tests
Avoid performance tests unless performance is the primary concern
Forbidden in tests:toBeInstanceOf(...),toBeArray(), genericnot->toBeNull(),expect(true)->toBeTrue(), andsleep(...)(use time mocking)
Prefer meaningful assertions on behavior and values (e.g., checking specific config values, validator outcomes, and configured mock interactions)
Unit tests: mock all external dependencies, test single units in isolation, complete in milliseconds
Integration tests: allow real file operations and external processes; cover CLI commands and full workflows
Do not run or gate tests on PHPStan compliance; ignore PHPStan issues in tests and avoid excessive phpdoc just for types
Files:
tests/Fixtures/MockFilesystem.php
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-04T12:08:48.865Z
Learning: Applies to app/Traits/ConsoleInputTrait.php : Add new input-gathering methods to ConsoleInputTrait and implement them using Laravel Prompts; methods should operate via $this->input
📚 Learning: 2025-10-04T12:08:48.865Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-04T12:08:48.865Z
Learning: Use laravel/prompts for all user interactions (text, password, confirm, select, multiselect, suggest, search, spin) rather than raw Symfony IO
Applied to files:
app/Services/PrompterService.php
📚 Learning: 2025-10-04T12:08:48.865Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-04T12:08:48.865Z
Learning: Applies to app/Traits/ConsoleInputTrait.php : ConsoleInputTrait wrappers (promptText, promptPassword, promptConfirm, promptSelect, promptMultiselect, promptSuggest, promptSearch, promptPause, promptSpin) should call Laravel Prompts and suppress extra spacing
Applied to files:
app/Services/PrompterService.php
📚 Learning: 2025-10-04T12:08:48.865Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-04T12:08:48.865Z
Learning: Applies to app/Traits/ConsoleInputTrait.php : Add new input-gathering methods to ConsoleInputTrait and implement them using Laravel Prompts; methods should operate via $this->input
Applied to files:
app/Services/PrompterService.php
🧬 Code graph analysis (1)
app/Services/PrompterService.php (1)
tests/Fixtures/MockPrompter.php (9)
confirm(76-88)multiselect(130-144)password(59-71)pause(93-100)search(171-184)select(107-120)spin(195-201)suggest(151-166)text(41-54)
🔇 Additional comments (1)
tests/Fixtures/MockFilesystem.php (1)
111-133: LGTM!The
mkdir()anddumpFile()methods correctly implement in-memory storage with appropriate error simulation. Ignoring the$modeparameter inmkdir()is acceptable for a test mock.
Replace hardcoded '.deployer' directory in MockFilesystem with dynamic extraction from the initial path parameter. Simplifies path matching logic by removing basename checks in favor of consistent path ending matches. Changes: - Extract parent directory from initialPath in MockFilesystem constructor - Simplify exists() and readFile() methods to use consistent path matching - Update mockFilesystem() default path from '.deployer/inventory.yml' to 'inventory.yml' - Update test datasets to reflect new flexible directory handling
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
tests/Fixtures/MockFilesystem.php (1)
69-107: Suffix matching still yields false positives.
Thestr_ends_with()fallback continues to report unrelated files (e.g.,myinventory.yml) as present, so mocks can hide real bugs. Please normalize paths and require exact equality instead of suffix matching.- // Check files (direct match or path ends with stored key) - if (isset($this->files[$files])) { - return true; - } - - foreach (array_keys($this->files) as $storedPath) { - if (str_ends_with($files, $storedPath)) { - return true; - } - } + if (isset($this->files[$files])) { + return true; + } + + $normalizedQuery = $this->normalizePath($files); + + foreach (array_keys($this->files) as $storedPath) { + if ($normalizedQuery === $this->normalizePath($storedPath)) { + return true; + } + } @@ - // Try direct match first - if (array_key_exists($filename, $this->files)) { - return $this->files[$filename]; - } - - // Try path ending match - foreach ($this->files as $storedPath => $content) { - if (str_ends_with($filename, $storedPath)) { - return $content; - } - } + if (array_key_exists($filename, $this->files)) { + return $this->files[$filename]; + } + + $normalizedFilename = $this->normalizePath($filename); + + foreach ($this->files as $storedPath => $content) { + if ($normalizedFilename === $this->normalizePath($storedPath)) { + return $content; + } + } + + throw new IOException("File does not exist: {$filename}", 0, null, $filename); + } + + private function normalizePath(string $path): string + { + $normalized = str_replace('\\', '/', $path); + + while (str_contains($normalized, '//')) { + $normalized = str_replace('//', '/', $normalized); + } + + $normalized = rtrim($normalized, '/'); + + if (str_starts_with($normalized, './')) { + $normalized = substr($normalized, 2); + } + + return $normalized;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
tests/Fixtures/MockFilesystem.php(1 hunks)tests/TestHelpers.php(6 hunks)tests/Unit/TestHelpersTest.php(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.php
📄 CodeRabbit inference engine (.cursor/rules/00-main.mdc)
**/*.php: Eliminate single-use private methods by inlining them directly
Cache expensive computed values by initializing them in the constructor instead of recomputing
Prefer direct property access over method calls when appropriate to avoid call overhead
Organize code into comment-separated sections; prefer alphabetical ordering when it does not conflict with logical grouping
**/*.php: Adhere to PSR-12 for all PHP code
Declare strict_types and write code assuming strict typing
Prefer PHP 8.x language features where appropriate (union types, match, attributes, readonly)
Use import statements (use ...) instead of fully qualified class names in code
All methods must have explicit return types, and use proper generics in types (e.g., Collection<int, User>)
Use dependency injection instead of manually resolving or instantiating classes
Prefer Symfony component classes (e.g., Filesystem, Process) over native PHP functions for testability
All object creation must use $container->build(ClassName::class), except value objects, DTOs, and pure data structures
In production code, access the container via constructor injection (no service locator or global access)
Add DocBlock comments with minimalist descriptions, parameters, and return types for classes and functions
Use comments as visual separators with section headers/subheaders and avoid obvious or stale comments
Files:
tests/Fixtures/MockFilesystem.phptests/Unit/TestHelpersTest.phptests/TestHelpers.php
{tests/**,test/**,**/*@(Test|Spec).php}
📄 CodeRabbit inference engine (.cursor/rules/00-main.mdc)
Do not run or edit tests unless explicitly instructed
Files:
tests/Fixtures/MockFilesystem.phptests/Unit/TestHelpersTest.phptests/TestHelpers.php
tests/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)
tests/**/*.php: In tests, it's allowed to instantiate the Container directly for isolation
Exclude tests from PHPStan static analysis
tests/**/*.php: Write Pest tests usingit()syntax
In unit tests, prefer manual instantiation with explicit mocks (e.g.,new ClassName(...)) over using the DI container
Use the DI container only in integration tests when verifying multiple services together or DI configuration
DI container conventions for production do not apply to tests
Apply the AAA pattern (Arrange, Act, Assert) in every test
For exception tests, combine phases with a// ACT & ASSERTcomment when the act triggers the assertion
Organize tests withdescribe()blocks and shared setup viabeforeEach(); extract helpers/traits for DRY tests
Keep test files under 1.8x the size of the source they test, without sacrificing readability
Focus tests on core business logic; avoid testing the framework itself
Use dataset-driven testing with->with([])for multiple scenarios
Eliminate overlap: avoid multiple tests covering the same functionality
Consolidate assertions using chained expectations (e.g.,expect($x)->toBe(1)->and($y)->toBe(2))
Mock only external dependencies; do not perform real I/O in unit tests
Avoid performance tests unless performance is the primary concern
Forbidden in tests:toBeInstanceOf(...),toBeArray(), genericnot->toBeNull(),expect(true)->toBeTrue(), andsleep(...)(use time mocking)
Prefer meaningful assertions on behavior and values (e.g., checking specific config values, validator outcomes, and configured mock interactions)
Unit tests: mock all external dependencies, test single units in isolation, complete in milliseconds
Integration tests: allow real file operations and external processes; cover CLI commands and full workflows
Do not run or gate tests on PHPStan compliance; ignore PHPStan issues in tests and avoid excessive phpdoc just for types
Files:
tests/Fixtures/MockFilesystem.phptests/Unit/TestHelpersTest.phptests/TestHelpers.php
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-04T12:08:48.865Z
Learning: Applies to app/Traits/ConsoleInputTrait.php : Add new input-gathering methods to ConsoleInputTrait and implement them using Laravel Prompts; methods should operate via $this->input
📚 Learning: 2025-10-04T14:36:28.928Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/02-tests.mdc:0-0
Timestamp: 2025-10-04T14:36:28.928Z
Learning: Applies to tests/**/*.php : Mock only external dependencies; do not perform real I/O in unit tests
Applied to files:
tests/Fixtures/MockFilesystem.php
🧬 Code graph analysis (2)
tests/Fixtures/MockFilesystem.php (1)
tests/Fixtures/MockSSHService.php (1)
__construct(29-32)
tests/TestHelpers.php (8)
tests/Fixtures/MockFilesystem.php (2)
MockFilesystem(28-137)exists(58-88)tests/Fixtures/MockPrompter.php (9)
MockPrompter(16-202)text(41-54)password(59-71)confirm(76-88)select(107-120)multiselect(130-144)suggest(151-166)search(171-184)pause(93-100)tests/Fixtures/MockSSHService.php (1)
MockSSHService(27-87)tests/Fixtures/TestConsoleCommand.php (1)
TestConsoleCommand(25-236)app/Services/FilesystemService.php (2)
exists(41-44)FilesystemService(27-106)app/Services/InventoryService.php (1)
InventoryService(33-264)app/Services/SSHService.php (1)
SSHService(40-327)app/Services/PrompterService.php (8)
text(33-51)password(56-72)confirm(77-93)select(110-128)multiselect(138-158)suggest(165-187)search(192-210)pause(98-103)
| 'directory exists' => [true, 'content', 'config/app.yml', 'config', true, 'directory should exist'], | ||
| 'directory with trailing slash' => [true, 'content', 'config/app.yml', 'config/', true, 'directory with trailing slash should exist'], | ||
| 'existing file' => [true, 'content', 'inventory.yml', 'inventory.yml', true, 'existing file should exist'], | ||
| 'non-existent file in existing dir' => [true, 'content', 'config/app.yml', 'config/missing.yml', false, 'non-existent file should not exist'], | ||
| 'directory exists when file does not' => [false, '', 'config/app.yml', 'config', true, 'directory should exist'], | ||
| 'non-existent file (no substring match)' => [false, '', 'inventory.yml', 'inventory.yml', false, 'non-existent file should not exist even if directory matches'], | ||
| 'different path no substring match' => [false, '', 'config/app.yml', '/path/to/config/other.yml', false, 'non-existent file with directory substring should not exist'], | ||
| 'direct path match' => [true, 'test', 'inventory.yml', 'inventory.yml', true, 'direct match should work'], | ||
| 'path ending match' => [true, 'test', 'inventory.yml', '/path/to/inventory.yml', true, 'path ending match should work'], | ||
| 'different path ending' => [true, 'test', 'inventory.yml', '/different/inventory.yml', true, 'different path ending should work'], |
There was a problem hiding this comment.
Incorrect expectation encourages bogus suffix matches.
Expecting /different/inventory.yml to exist after seeding only inventory.yml diverges from Symfony's Filesystem (which requires the exact path) and hides regressions the new MockFilesystem should catch. Please align the expectation with real behavior.
- 'different path ending' => [true, 'test', 'inventory.yml', '/different/inventory.yml', true, 'different path ending should work'],
+ 'different path ending' => [true, 'test', 'inventory.yml', '/different/inventory.yml', false, 'different full path should not match unless identical'],📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 'directory exists' => [true, 'content', 'config/app.yml', 'config', true, 'directory should exist'], | |
| 'directory with trailing slash' => [true, 'content', 'config/app.yml', 'config/', true, 'directory with trailing slash should exist'], | |
| 'existing file' => [true, 'content', 'inventory.yml', 'inventory.yml', true, 'existing file should exist'], | |
| 'non-existent file in existing dir' => [true, 'content', 'config/app.yml', 'config/missing.yml', false, 'non-existent file should not exist'], | |
| 'directory exists when file does not' => [false, '', 'config/app.yml', 'config', true, 'directory should exist'], | |
| 'non-existent file (no substring match)' => [false, '', 'inventory.yml', 'inventory.yml', false, 'non-existent file should not exist even if directory matches'], | |
| 'different path no substring match' => [false, '', 'config/app.yml', '/path/to/config/other.yml', false, 'non-existent file with directory substring should not exist'], | |
| 'direct path match' => [true, 'test', 'inventory.yml', 'inventory.yml', true, 'direct match should work'], | |
| 'path ending match' => [true, 'test', 'inventory.yml', '/path/to/inventory.yml', true, 'path ending match should work'], | |
| 'different path ending' => [true, 'test', 'inventory.yml', '/different/inventory.yml', true, 'different path ending should work'], | |
| 'directory exists' => [true, 'content', 'config/app.yml', 'config', true, 'directory should exist'], | |
| 'directory with trailing slash' => [true, 'content', 'config/app.yml', 'config/', true, 'directory with trailing slash should exist'], | |
| 'existing file' => [true, 'content', 'inventory.yml', 'inventory.yml', true, 'existing file should exist'], | |
| 'non-existent file in existing dir' => [true, 'content', 'config/app.yml', 'config/missing.yml', false, 'non-existent file should not exist'], | |
| 'directory exists when file does not' => [false, '', 'config/app.yml', 'config', true, 'directory should exist'], | |
| 'non-existent file (no substring match)' => [false, '', 'inventory.yml', 'inventory.yml', false, 'non-existent file should not exist even if directory matches'], | |
| 'different path no substring match' => [false, '', 'config/app.yml', '/path/to/config/other.yml', false, 'non-existent file with directory substring should not exist'], | |
| 'direct path match' => [true, 'test', 'inventory.yml', 'inventory.yml', true, 'direct match should work'], | |
| 'path ending match' => [true, 'test', 'inventory.yml', '/path/to/inventory.yml', true, 'path ending match should work'], | |
| 'different path ending' => [true, 'test', 'inventory.yml', '/different/inventory.yml', false, 'different full path should not match unless identical'], |
🤖 Prompt for AI Agents
In tests/Unit/TestHelpersTest.php around lines 21 to 30, the test case
"different path ending" incorrectly expects /different/inventory.yml to exist
when only inventory.yml was seeded; change the expected boolean from true to
false and update the assertion message to reflect that different path endings
should not match an exact file seed (aligning the mock with Symfony Filesystem
behavior).
Summary by CodeRabbit