refactor: console output trait extraction - #23
Conversation
Extract console output formatting methods from BaseCommand into a reusable ConsoleOutputTrait to promote code reuse and separation of concerns. Changes: - Create ConsoleOutputTrait with status messages (error, success, warning) - Add output formatting methods (h1, hr, text, writeln) - Add user input helper (getOptionOrPrompt) - Add command hint display (showCommandHint) - Refactor BaseCommand to use the new trait - Add comprehensive test coverage (ConsoleOutputTraitTest) - Update BaseCommandTest to reflect extracted methods - Update documentation in .cursor/rules/03-commands.mdc
Eliminate repetitive setup code by extracting command and tester initialization to a beforeEach() hook. Improvements: - Reduce test file size from 339 to 302 lines (-37 lines, 11% reduction) - Improve test:source ratio from 1.695:1 to 1.51:1 - Enhance maintainability with single point of setup - Follow Pest best practices for test organization - All 14 tests pass with no regressions
Move getOptionOrPrompt and related input logic from ConsoleOutputTrait to new ConsoleInputTrait. Update BaseCommand to use both traits and set input/output properties. Simplify output methods and add info/note helpers. Update documentation example to reflect new method signature.
…ests Introduce TestConsoleCommand fixture for trait testing. Add unit tests for input trait's getOptionOrPrompt method. Update output trait tests to use the shared fixture and remove the now-migrated input-related tests.
Update pint.json to include ordered_imports (alpha sort) and no_unused_imports rules as per user preference. Reorder use statements in affected test files to apply the new rules.
Add comprehensive documentation on when to add methods to ConsoleOutputTrait, ConsoleInputTrait, or BaseCommand. Include integration points for both output and input traits. Enhance docblocks in BaseCommand and ConsoleOutputTrait to reflect trait usage patterns.
Add tests for text(), info(), and note() methods in ConsoleOutputTrait. Extend TestConsoleCommand fixture to support testing these basic output methods.
WalkthroughAdds ConsoleInputTrait and ConsoleOutputTrait, refactors BaseCommand to use them (exposing getOptionOrPrompt and output helpers), updates HelloCommand to use BaseCommand helpers, adds TestConsoleCommand fixture, expands unit tests for the new traits, and tweaks pint import rules. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Console as "Symfony Console"
participant Cmd as "BaseCommand (Traits)"
participant IO as "SymfonyStyle"
note over Cmd: initialize() sets $input/$output and $io
User->>Console: run command (with options)
Console->>Cmd: initialize(input, output)
Cmd->>IO: setup style
alt option provided
Cmd->>Cmd: getOptionOrPrompt(name) → returns option (wasProvided=true)
else option missing
Cmd->>User: prompt "Name:" via Prompts::text()
User-->>Cmd: enters value (wasProvided=false)
end
Cmd->>IO: call output helpers (text/info/success/...)
Cmd-->>Console: exit with status
sequenceDiagram
autonumber
participant Cmd as "BaseCommand (ConsoleOutputTrait)"
participant IO as "SymfonyStyle"
Cmd->>IO: h1("Heading", icon)
Cmd->>IO: text([...])
Cmd->>IO: hr()
Cmd->>IO: showCommandHint(command, options, providedFlags)
note right of IO: Renders hint, skips empty/null values, highlights provided vs prompted parts
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
Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/Unit/Contracts/BaseCommandTest.php (1)
39-44: Use BaseCommand’s output helper instead of raw IOAvoid calling $this->io->text() directly in commands; prefer the wrapper for consistency with the traits.
As per coding guidelines
- $result = parent::execute($input, $output); - $this->io->text('Test command executed successfully'); - return $result; + $result = parent::execute($input, $output); + $this->text('Test command executed successfully'); + return $result;app/Contracts/BaseCommand.php (1)
102-103: Suppress PHPMD unused parameter warnings on execute()execute() must keep the Symfony signature even if $input/$output aren’t used; suppress the warning to keep CI green.
- /** - * Common execution logic. - */ + /** + * Common execution logic. + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ protected function execute(InputInterface $input, OutputInterface $output): int
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
.cursor/rules/03-commands.mdc(4 hunks)app/Console/HelloCommand.php(1 hunks)app/Contracts/BaseCommand.php(4 hunks)app/Traits/ConsoleInputTrait.php(1 hunks)app/Traits/ConsoleOutputTrait.php(1 hunks)pint.json(1 hunks)tests/Fixtures/TestConsoleCommand.php(1 hunks)tests/Integration/SymfonyAppTest.php(1 hunks)tests/Unit/ContainerTest.php(1 hunks)tests/Unit/Contracts/BaseCommandTest.php(2 hunks)tests/Unit/Traits/ConsoleInputTraitTest.php(1 hunks)tests/Unit/Traits/ConsoleOutputTraitTest.php(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.php
📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)
**/*.php: Follow PSR-12 coding standard in all PHP files
Declare strict types in all PHP files (declare(strict_types=1);)
Use PHP 8.x features where appropriate (unions, match, attributes, readonly)
Use import statements (use ...) instead of fully qualified class names in code
All methods must declare explicit return types with proper generics (e.g., Collection<int, User>)
Prefer Dependency Injection over manual class resolution/instantiation
Use Symfony component classes (e.g., Filesystem, Process) instead of native PHP functions for easier mocking
All object creation must use $container->build(ClassName::class) except for value objects, DTOs, and pure data structures
Access the container via constructor injection in production code; tests may instantiate Container directly
Services must receive dependencies via constructor injection
Use SymfonyStyle consistently for all user-facing console output
Add DocBlock comments with minimalist descriptions, parameters, and return types for classes and functions
Use comments to separate sections and explain complex logic; avoid obvious or stale comments
Use the exact section header comment format with a single newline between headers/subheaders/paragraphs
**/*.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
Files:
app/Traits/ConsoleInputTrait.phptests/Unit/Traits/ConsoleInputTraitTest.phptests/Unit/Traits/ConsoleOutputTraitTest.phptests/Unit/Contracts/BaseCommandTest.phptests/Integration/SymfonyAppTest.phptests/Fixtures/TestConsoleCommand.phpapp/Contracts/BaseCommand.phpapp/Traits/ConsoleOutputTrait.phpapp/Console/HelloCommand.phptests/Unit/ContainerTest.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/Traits/ConsoleInputTraitTest.phptests/Unit/Traits/ConsoleOutputTraitTest.phptests/Unit/Contracts/BaseCommandTest.phptests/Integration/SymfonyAppTest.phptests/Fixtures/TestConsoleCommand.phptests/Unit/ContainerTest.php
tests/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/02-tests.mdc)
tests/**/*.php: Use Pest exclusively with it() syntax for tests
In unit tests, instantiate classes manually with explicit mocks; use the container only for integration tests
Keep individual test files under ~1.8x the size of the source they cover
Test core business logic; avoid testing the framework itself
Prefer dataset-driven testing with ->with([...]) for multiple scenarios
Eliminate overlapping tests; avoid two tests covering the same functionality
Consolidate assertions with expect(...)->and(...) when appropriate
Mock external dependencies only; do not mock internal behavior
Avoid performance tests unless performance is the primary concern
Do not sacrifice readability to hit size/ratio targets
Follow the AAA pattern (Arrange, Act, Assert) in tests; use ACT & ASSERT for exception tests when act triggers assertion
Organize tests with describe() blocks, beforeEach() setup, and extract helpers/traits for DRY
Forbid meaningless assertions (e.g., toBeTrue, not->toBeNull, type-only checks, sleep(...)); use time mocking instead of sleep
Prefer meaningful assertions on behavior and results, and proper mocks (e.g., expect domain outputs; mock->shouldReceive(...))
Unit tests: mock all external dependencies; test single units in isolation; execute in milliseconds
Integration tests: perform real file operations/external processes; cover CLI commands and full workflows
Ignore PHPStan issues in tests; avoid excessive PHPDoc added only to appease types
Files:
tests/Unit/Traits/ConsoleInputTraitTest.phptests/Unit/Traits/ConsoleOutputTraitTest.phptests/Unit/Contracts/BaseCommandTest.phptests/Integration/SymfonyAppTest.phptests/Fixtures/TestConsoleCommand.phptests/Unit/ContainerTest.php
app/Contracts/BaseCommand.php
📄 CodeRabbit inference engine (.cursor/rules/03-commands.mdc)
If output functionality is missing, add a new method to BaseCommand with modern styling, keep it reusable and minimal, and document with examples
Files:
app/Contracts/BaseCommand.php
🧠 Learnings (10)
📚 Learning: 2025-10-01T13:56:16.653Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/01-architecture.mdc:0-0
Timestamp: 2025-10-01T13:56:16.653Z
Learning: Applies to app/SymfonyApp.php : Register commands via $this->container->build(CommandClass::class) in SymfonyApp.php
Applied to files:
tests/Integration/SymfonyAppTest.php
📚 Learning: 2025-10-01T15:31:28.222Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-01T15:31:28.222Z
Learning: Applies to app/Console/Commands/**/*.php : Never use Symfony IO methods directly inside commands; use BaseCommand custom methods like writeln(), text(), and hr() exclusively for all console output
Applied to files:
app/Contracts/BaseCommand.phpapp/Traits/ConsoleOutputTrait.php.cursor/rules/03-commands.mdc
📚 Learning: 2025-10-01T15:31:28.222Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-01T15:31:28.222Z
Learning: Applies to app/Contracts/BaseCommand.php : If output functionality is missing, add a new method to BaseCommand with modern styling, keep it reusable and minimal, and document with examples
Applied to files:
app/Contracts/BaseCommand.php.cursor/rules/03-commands.mdc
📚 Learning: 2025-10-02T19:48:48.339Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/02-tests.mdc:0-0
Timestamp: 2025-10-02T19:48:48.339Z
Learning: Applies to tests/**/*.php : In unit tests, instantiate classes manually with explicit mocks; use the container only for integration tests
Applied to files:
tests/Unit/ContainerTest.php
📚 Learning: 2025-10-02T19:48:48.339Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/02-tests.mdc:0-0
Timestamp: 2025-10-02T19:48:48.339Z
Learning: Applies to tests/**/*.php : Unit tests: mock all external dependencies; test single units in isolation; execute in milliseconds
Applied to files:
tests/Unit/ContainerTest.php
📚 Learning: 2025-10-01T15:31:28.222Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-01T15:31:28.222Z
Learning: Applies to app/Console/Commands/**/*.php : Use laravel/prompts for all user interactions (text, password, confirm, select, multiselect, suggest, search) and prefer an interaction check when applicable; use spin() for long operations
Applied to files:
.cursor/rules/03-commands.mdc
📚 Learning: 2025-10-01T15:31:28.222Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-01T15:31:28.222Z
Learning: Applies to app/Console/Commands/**/*.php : Use consistent styling patterns across all commands
Applied to files:
.cursor/rules/03-commands.mdc
📚 Learning: 2025-10-01T15:31:28.222Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-01T15:31:28.222Z
Learning: Applies to app/Console/Commands/**/*.php : Commands handle all user interaction (input/output)
Applied to files:
.cursor/rules/03-commands.mdc
📚 Learning: 2025-10-01T13:56:16.653Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/01-architecture.mdc:0-0
Timestamp: 2025-10-01T13:56:16.653Z
Learning: Commands are responsible for console styling, error formatting, and user prompts
Applied to files:
.cursor/rules/03-commands.mdc
📚 Learning: 2025-10-01T15:31:28.222Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-01T15:31:28.222Z
Learning: Applies to app/Console/Commands/**/*.php : Commands orchestrate Services and format output
Applied to files:
.cursor/rules/03-commands.mdc
🧬 Code graph analysis (8)
app/Traits/ConsoleInputTrait.php (1)
app/Traits/ConsoleOutputTrait.php (1)
text(38-41)
tests/Unit/Traits/ConsoleInputTraitTest.php (3)
app/Container.php (1)
Container(23-227)tests/Fixtures/TestConsoleCommand.php (3)
TestConsoleCommand(21-83)setTestMethod(38-42)execute(52-72)tests/TestHelpers.php (2)
mockEnvService(140-148)mockInventoryService(156-173)
tests/Unit/Traits/ConsoleOutputTraitTest.php (4)
app/Container.php (1)
Container(23-227)tests/Fixtures/TestConsoleCommand.php (3)
TestConsoleCommand(21-83)setTestMethod(38-42)execute(52-72)tests/TestHelpers.php (2)
mockEnvService(140-148)mockInventoryService(156-173)app/Contracts/BaseCommand.php (1)
execute(102-123)
tests/Unit/Contracts/BaseCommandTest.php (1)
app/Contracts/BaseCommand.php (1)
BaseCommand(24-124)
tests/Fixtures/TestConsoleCommand.php (3)
app/Contracts/BaseCommand.php (1)
BaseCommand(24-124)app/Traits/ConsoleOutputTrait.php (10)
text(38-41)info(46-49)note(54-57)error(78-87)success(62-65)warning(70-73)h1(96-99)hr(104-110)writeln(23-29)showCommandHint(122-154)app/Traits/ConsoleInputTrait.php (1)
getOptionOrPrompt(31-55)
app/Contracts/BaseCommand.php (2)
tests/Unit/Contracts/BaseCommandTest.php (1)
execute(39-44)app/Console/HelloCommand.php (1)
execute(19-28)
app/Console/HelloCommand.php (1)
app/Traits/ConsoleOutputTrait.php (1)
success(62-65)
tests/Unit/ContainerTest.php (1)
tests/Fixtures/ContainerFixtures.php (13)
AbstractClass(179-181)CircularA(92-97)NoConstructorService(19-25)PrivateConstructor(124-129)ServiceWithDefaults(64-74)ServiceWithIntersectionType(147-157)ServiceWithMultipleDeps(43-58)ServiceWithOptionalClassDep(76-86)ServiceWithScalarParam(110-115)ServiceWithUnionAndCircular(159-169)ServiceWithUnionType(135-145)ServiceWithUnresolvableDependency(117-122)SimpleService(11-17)
🪛 PHPMD (2.15.0)
tests/Fixtures/TestConsoleCommand.php
52-52: Avoid unused parameters such as '$input'. (undefined)
(UnusedFormalParameter)
52-52: Avoid unused parameters such as '$output'. (undefined)
(UnusedFormalParameter)
app/Contracts/BaseCommand.php
102-102: Avoid unused parameters such as '$input'. (undefined)
(UnusedFormalParameter)
102-102: Avoid unused parameters such as '$output'. (undefined)
(UnusedFormalParameter)
🔇 Additional comments (26)
pint.json (1)
3-8: Import hygiene rules look goodAlpha-ordered imports and removing unused imports align with PSR-12 and keep diffs clean.
app/Console/HelloCommand.php (1)
25-25: Good move to trait-based helperUsing $this->success(...) instead of accessing $this->io directly matches the new ConsoleOutputTrait API and keeps commands consistent.
tests/Unit/Traits/ConsoleInputTraitTest.php (1)
23-34: Covers option vs prompt flag correctlyNice assertion of value and wasProvided=true for getOptionOrPrompt when option is supplied.
tests/Integration/SymfonyAppTest.php (1)
7-8: Imports tidy-up LGTMExplicit imports for Command and CommandNotFoundException improve clarity in assertions/try-catch.
tests/Unit/ContainerTest.php (1)
8-22: Import set is coherent with fixtures usedAdded/moved fixture imports match the covered scenarios (abstract, circular, union/intersection).
tests/Unit/Contracts/BaseCommandTest.php (1)
71-93: Test intent and expectations read wellValidates both presence of env/inventory sections and dynamic env message; data provider cases are clear.
tests/Unit/Traits/ConsoleOutputTraitTest.php (4)
121-145: Heading and separator coverageAsserting presence of the icon and a minimum separator length makes the test resilient to width differences.
175-193: Command hint rendering checks are thoroughGood coverage for flags, names, and non-interactive hint text.
195-212: Highlights and values verification LGTMVerifies both option names and shown values; balanced assertions.
214-230: Null/empty filtering is testedEnsures noise-free hints by skipping null/empty values.
app/Contracts/BaseCommand.php (2)
26-31: Trait integration and IO properties are appropriateStoring InputInterface/OutputInterface and using the traits aligns with the refactor goal and keeps IO centralized.
107-121: Status output logic is concise and readableUsing $this->writeln with color tags keeps the UX consistent. No issues spotted.
app/Traits/ConsoleOutputTrait.php (4)
18-29: LGTM!The
writeln()method correctly normalizes string or array input, prepends a space to each line, and delegates to$this->io->writeln(). The logic is clear and the DocBlock is appropriate.
35-87: LGTM!The message helper methods (
text(),info(),note(),success(),warning(),error()) provide consistent, well-formatted console output with appropriate color-coding and symbols. Theerror()method's optional$tipparameter is a nice touch for user guidance.
93-110: LGTM!The
h1()andhr()methods provide consistent heading and separator formatting with appropriate color-coding. The decorative separator line is visually appealing and maintains consistency across the console output.
116-154: LGTM with minor note on edge case handling.The
showCommandHint()method correctly builds a non-interactive command invocation snippet with color-coding based on provided vs prompted values. The use ofescapeshellarg()ensures shell safety for string values.Note: Line 145 handles non-scalar values by casting to an empty string after the
is_scalar()check. While this is safe, consider logging or explicitly handling unexpected types if this method is extended in the future.app/Traits/ConsoleInputTrait.php (1)
16-55: LGTM!The
getOptionOrPrompt()method correctly implements the interactive + options pattern: it checks for a provided CLI option and falls back to prompting the user with Laravel\Prompts\text. The by-ref$wasProvidedparameter is a clean way to track the input source for downstream usage (e.g., inshowCommandHint()).tests/Fixtures/TestConsoleCommand.php (5)
27-33: LGTM!The constructor correctly injects dependencies via constructor injection and delegates to the parent constructor. This follows the coding guidelines for dependency injection.
35-42: LGTM!The
setTestMethod()setter provides a clean way to configure which trait method to test. This is appropriate for a test fixture.
44-50: LGTM!The
configure()method correctly sets up the command name, description, and options for testing. This follows standard Symfony console conventions.
52-72: LGTM!The
execute()method correctly dispatches to trait methods via a match expression for testing purposes. The unused$inputand$outputparameters flagged by PHPMD are a false positive—these are required by theCommand::execute()signature, and the fixture relies onBaseCommand::initialize()to set$this->inputand$this->outputfor use by trait methods.Per coding guidelines, static analysis warnings in test code can be safely ignored when they don't indicate real issues.
77-82: Use$this->text()instead of$this->io->text().Line 81 uses
$this->io->text()directly, which violates the coding guideline: "Never use Symfony IO methods directly; use BaseCommand custom methods." Based on learnings.Apply this diff to align with the coding guidelines:
- $this->io->text("Result: {$result}, Provided: ".($wasProvided ? 'true' : 'false')); + $this->text("Result: {$result}, Provided: ".($wasProvided ? 'true' : 'false'));Likely an incorrect or invalid review comment.
.cursor/rules/03-commands.mdc (4)
21-32: LGTM!The updated examples correctly demonstrate the new custom IO methods (
text(),hr(),h1(),success(),error(),warning()) introduced inConsoleOutputTrait. The examples are clear and consistent with the trait implementation.
59-86: LGTM!The updated integration points and trait organization guidance clearly explain when to add methods to
ConsoleOutputTraitvsConsoleInputTraitvsBaseCommand. This promotes separation of concerns and reusability, which aligns with best practices.
87-113: LGTM!The new "Status Message Helpers" section clearly documents the
success(),error(), andwarning()methods with practical examples. The listed benefits emphasize consistency and UX, which aligns with the PR's goals.
187-252: LGTM!The new "Interactive + Options Pattern" section comprehensively documents the
getOptionOrPrompt()andshowCommandHint()workflow with clear examples and explanations. The color-coding details and listed benefits effectively communicate the value of this pattern for both script-friendly and user-friendly CLI experiences.
… test fixture - Replace direct io->text() call with text() wrapper method - Ensures test fixture follows architectural pattern for console output - Aligns with mandatory rule: use BaseCommand methods exclusively
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
tests/Unit/Contracts/BaseCommandTest.php (1)
71-93: Consider adding inventory status variation to the dataset.The test correctly uses dataset-driven testing for environment file scenarios. However, Line 88 assumes the inventory always exists ('Reading inventory from'), while only the environment status varies in the dataset.
For more comprehensive coverage, consider expanding the dataset to include inventory variations:
})->with([ - 'env file exists' => [true, 'Reading variables from'], - 'no env file' => [false, 'No .env file found'], + 'env and inventory exist' => [true, true, 'Reading variables from', 'Reading inventory from'], + 'no env, inventory exists' => [false, true, 'No .env file found', 'Reading inventory from'], + 'env exists, no inventory' => [true, false, 'Reading variables from', 'No inventory.yml file'], + 'neither exist' => [false, false, 'No .env file found', 'No inventory.yml file'], ]);Alternatively, if inventory variations are tested elsewhere or aren't a concern for BaseCommand's core logic, the current focused approach is acceptable.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
tests/Unit/Contracts/BaseCommandTest.php(3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.php
📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)
**/*.php: Follow PSR-12 coding standard in all PHP files
Declare strict types in all PHP files (declare(strict_types=1);)
Use PHP 8.x features where appropriate (unions, match, attributes, readonly)
Use import statements (use ...) instead of fully qualified class names in code
All methods must declare explicit return types with proper generics (e.g., Collection<int, User>)
Prefer Dependency Injection over manual class resolution/instantiation
Use Symfony component classes (e.g., Filesystem, Process) instead of native PHP functions for easier mocking
All object creation must use $container->build(ClassName::class) except for value objects, DTOs, and pure data structures
Access the container via constructor injection in production code; tests may instantiate Container directly
Services must receive dependencies via constructor injection
Use SymfonyStyle consistently for all user-facing console output
Add DocBlock comments with minimalist descriptions, parameters, and return types for classes and functions
Use comments to separate sections and explain complex logic; avoid obvious or stale comments
Use the exact section header comment format with a single newline between headers/subheaders/paragraphs
**/*.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
Files:
tests/Unit/Contracts/BaseCommandTest.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.php
tests/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/02-tests.mdc)
tests/**/*.php: Use Pest exclusively with it() syntax for tests
In unit tests, instantiate classes manually with explicit mocks; use the container only for integration tests
Keep individual test files under ~1.8x the size of the source they cover
Test core business logic; avoid testing the framework itself
Prefer dataset-driven testing with ->with([...]) for multiple scenarios
Eliminate overlapping tests; avoid two tests covering the same functionality
Consolidate assertions with expect(...)->and(...) when appropriate
Mock external dependencies only; do not mock internal behavior
Avoid performance tests unless performance is the primary concern
Do not sacrifice readability to hit size/ratio targets
Follow the AAA pattern (Arrange, Act, Assert) in tests; use ACT & ASSERT for exception tests when act triggers assertion
Organize tests with describe() blocks, beforeEach() setup, and extract helpers/traits for DRY
Forbid meaningless assertions (e.g., toBeTrue, not->toBeNull, type-only checks, sleep(...)); use time mocking instead of sleep
Prefer meaningful assertions on behavior and results, and proper mocks (e.g., expect domain outputs; mock->shouldReceive(...))
Unit tests: mock all external dependencies; test single units in isolation; execute in milliseconds
Integration tests: perform real file operations/external processes; cover CLI commands and full workflows
Ignore PHPStan issues in tests; avoid excessive PHPDoc added only to appease types
Files:
tests/Unit/Contracts/BaseCommandTest.php
🧬 Code graph analysis (1)
tests/Unit/Contracts/BaseCommandTest.php (2)
app/Contracts/BaseCommand.php (1)
BaseCommand(24-124)app/Traits/ConsoleOutputTrait.php (1)
text(38-41)
🔇 Additional comments (3)
tests/Unit/Contracts/BaseCommandTest.php (3)
8-8: LGTM!The import is correctly positioned alphabetically after
Container, aligning with the updated Pint rules for import ordering.
39-44: LGTM!The refactor from
$this->io->text(...)to$this->text(...)correctly utilizes the newConsoleOutputTraitmethod, aligning with the trait extraction objective.
52-69: LGTM!The test follows the AAA pattern, consolidates assertions effectively with
expect()->and(), and uses manual instantiation with explicit mocks as recommended for unit tests.
Summary by CodeRabbit
New Features
Refactor
Documentation
Tests
Style/Chores