Skip to content

Issue/479 command coverage - #485

Merged
armanist merged 6 commits into
quantum-php:masterfrom
armanist:issue/479-command-coverage
Apr 30, 2026
Merged

armanist merged 6 commits into
quantum-php:masterfrom
armanist:issue/479-command-coverage

Conversation

@armanist

@armanist armanist commented Apr 29, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #479

Summary by CodeRabbit

  • Tests
    • Added comprehensive unit tests for console commands: toolkit installation (env updates and success message), migration creation and rollback confirmation behavior, module generation with asset handling and filesystem cleanup, OpenAPI command error handling for missing modules, route listing and module filter errors, dev server startup resolving host/port and URL, and version display output handling.

@coderabbitai

coderabbitai Bot commented Apr 29, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds execution-path unit tests for multiple console command tests, exercising runtime behavior (CommandTester/HelperSet), filesystem effects, env updates, simulated interactive input, and teardown cleanup to isolate state.

Changes

Cohort / File(s) Summary
Module & Install
tests/Unit/Console/Commands/InstallToolkitCommandTest.php, tests/Unit/Console/Commands/ModuleGenerateCommandTest.php
New execution-path tests: verify env variable updates, invoke module generation command with options, assert outputs and filesystem side effects; add setUp/tearDown to snapshot and restore .env and module config/files.
Migrations
tests/Unit/Console/Commands/MigrationGenerateCommandTest.php, tests/Unit/Console/Commands/MigrationMigrateCommandTest.php
Added tests that run migration generation and migrate commands via CommandTester; capture/cleanup created migration files and inject Symfony HelperSet/QuestionHelper to simulate interactive confirmations (including cancel flow).
Diagnostics & Utilities
tests/Unit/Console/Commands/OpenApiCommandTest.php, tests/Unit/Console/Commands/RouteListCommandTest.php, tests/Unit/Console/Commands/ServeCommandTest.php, tests/Unit/Console/Commands/VersionCommandTest.php
Added CommandTester-based tests asserting expected outputs and error messages for missing modules, route table rendering, serve host/port resolution, and version printing (with conditional exception expectation if font asset missing); include asset setup and cleanup where needed.

Sequence Diagram(s)

(No sequence diagrams generated — changes are test additions and do not introduce new multi-component runtime control flow requiring visualization.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

enhancement

Suggested reviewers

  • andrey-smaelov

Poem

🐰 I hopped through tests with nimble feet,

Env saved, files cleaned—no mess to meet.
Commands invoked, confirmations replied,
Coverage blossoms, I thump with pride. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Issue/479 command coverage' directly references the linked issue #479 and accurately describes the main objective of adding test coverage for console commands.
Linked Issues check ✅ Passed The PR successfully implements the goals from issue #479 by adding end-to-end execution tests for multiple commands (InstallToolkit, MigrationGenerate, MigrationMigrate, ModuleGenerate, OpenApi, RouteList, Serve, VersionCommand) that actually invoke execute() paths, verify meaningful behavior including arguments/options and success paths, and implement proper state isolation via setUp/tearDown methods.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issue #479: new test methods that execute commands, verify output/behavior, and manage test state cleanup. No unrelated modifications to production code or unrelated test files are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Apr 29, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.98%. Comparing base (590e4b5) to head (fce3398).
⚠️ Report is 7 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master     #485      +/-   ##
============================================
+ Coverage     85.28%   86.98%   +1.69%     
  Complexity     2903     2903              
============================================
  Files           249      249              
  Lines          7651     7651              
============================================
+ Hits           6525     6655     +130     
+ Misses         1126      996     -130     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d5fa5a6617

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tests/Unit/Console/Commands/InstallToolkitCommandTest.php

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
tests/Unit/Console/Commands/MigrationGenerateCommandTest.php (1)

46-58: Assert the migration file side effect, not only output text.

The command’s core behavior is file creation; asserting file count increase will make this test harder to false-pass.

Suggested enhancement
 public function testExecCreatesMigrationFile(): void
 {
+    $before = $this->existingMigrationFiles;
     $tester = new CommandTester($this->command);

     $tester->execute([
         'action' => 'create',
         'table' => 'tickets',
@@
     $output = $tester->getDisplay();
     $this->assertStringContainsString('Migration file', $output);
     $this->assertStringContainsString('successfully created', $output);
+
+    $files = glob(base_dir() . DS . 'migrations' . DS . '*.php');
+    $after = is_array($files) ? $files : [];
+    $this->assertGreaterThan(count($before), count($after));
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/Unit/Console/Commands/MigrationGenerateCommandTest.php` around lines 46
- 58, Update testExecCreatesMigrationFile in MigrationGenerateCommandTest to
assert the actual file-side effect instead of only output: before calling
$tester->execute, record the list/count of migration files (e.g. glob or scandir
for the migrations directory), then execute the command via
CommandTester->execute (the same 'action' => 'create', 'table' => 'tickets'
args), and after execution assert that the migration file count has increased or
that a new migration filename matching the expected pattern (timestamp + table
name) now exists; use the test helper methods in this class and reference
testExecCreatesMigrationFile and CommandTester->execute to locate where to add
the pre/post filesystem checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/Unit/Console/Commands/InstallToolkitCommandTest.php`:
- Around line 37-68: This test mutates env-backed auth values (BASIC_AUTH_NAME,
BASIC_AUTH_PWD) and must restore them: at the start of
testExecUpdatesEnvAndRunsModuleGeneration capture the originals (e.g. $origName
= env('BASIC_AUTH_NAME'); $origPwd = env('BASIC_AUTH_PWD')), then wrap the
exercise/assertions in a try/finally and in finally restore the originals (use
putenv and $_ENV/$_SERVER as appropriate — unset if original was null, or set
back to the saved value) so subsequent tests are not polluted; keep the existing
assertions and calledCommand/calledArguments checks intact.

In `@tests/Unit/Console/Commands/ModuleGenerateCommandTest.php`:
- Around line 13-14: Replace the fixed $moduleName property and unsafe cleanup
with a per-test unique module name and non-destructive teardown: set $moduleName
by generating a unique string (e.g., uniqid('Issue479Module_') or use PHPUnit's
temp directory) in setUp(), record any created paths, and in tearDown() only
remove files/directories if they exist and match the generated $moduleName
(avoid globbing or unconditional deletes). Update
ModuleGenerateCommandTest::$moduleName initialization, the setUp() that prepares
modulesConfigPath, and the tearDown() cleanup logic so it checks file existence
and ownership by the test-generated name before unlink/rmdir (or use an isolated
temp dir/vfsStream) to prevent removing pre-existing modules/configs.

In `@tests/Unit/Console/Commands/OpenApiCommandTest.php`:
- Around line 44-59: The test OpenApiCommandTest mutates the shared OpenAPI
asset (assets_dir() . DS . 'OpenApiUi' / 'index.css') and only best-effort
cleans up, risking state leakage and clobbering existing content; update the
test to detect and back up any existing index.css before writing the stub,
create the OpenApiUi directory if missing, run the CommandTester execution, and
then in a guaranteed cleanup block (try/finally or tearDown) restore the
original file if a backup was made or remove the created file and directory
otherwise; reference $openApiAssets, 'index.css', $this->fs and the
CommandTester usage to locate where to add the backup/restore and ensure cleanup
runs even on test failure.

In `@tests/Unit/Console/Commands/VersionCommandTest.php`:
- Around line 33-39: The current test in VersionCommandTest.php swallows
execution errors by catching any Exception and asserting on its message, which
masks real failures; remove the try/catch and either (A) let the command run
normally and assert the output contains '9.9.9-test' after $tester->execute([])
so any thrown exception fails the test, or (B) if the test genuinely expects a
specific failure, replace the catch with a focused expectation using
$this->expectExceptionMessage('slant.flf') (and/or $this->expectException(...)
for the specific exception class) before calling $tester->execute([]); update
the assertions around $tester->getDisplay() and assertStringContainsString
accordingly to reference the same code paths.

---

Nitpick comments:
In `@tests/Unit/Console/Commands/MigrationGenerateCommandTest.php`:
- Around line 46-58: Update testExecCreatesMigrationFile in
MigrationGenerateCommandTest to assert the actual file-side effect instead of
only output: before calling $tester->execute, record the list/count of migration
files (e.g. glob or scandir for the migrations directory), then execute the
command via CommandTester->execute (the same 'action' => 'create', 'table' =>
'tickets' args), and after execution assert that the migration file count has
increased or that a new migration filename matching the expected pattern
(timestamp + table name) now exists; use the test helper methods in this class
and reference testExecCreatesMigrationFile and CommandTester->execute to locate
where to add the pre/post filesystem checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7c9d458a-0f97-4d14-bb69-c77d11b7fd02

📥 Commits

Reviewing files that changed from the base of the PR and between 590e4b5 and d5fa5a6.

📒 Files selected for processing (8)
  • tests/Unit/Console/Commands/InstallToolkitCommandTest.php
  • tests/Unit/Console/Commands/MigrationGenerateCommandTest.php
  • tests/Unit/Console/Commands/MigrationMigrateCommandTest.php
  • tests/Unit/Console/Commands/ModuleGenerateCommandTest.php
  • tests/Unit/Console/Commands/OpenApiCommandTest.php
  • tests/Unit/Console/Commands/RouteListCommandTest.php
  • tests/Unit/Console/Commands/ServeCommandTest.php
  • tests/Unit/Console/Commands/VersionCommandTest.php

Comment thread tests/Unit/Console/Commands/InstallToolkitCommandTest.php
Comment thread tests/Unit/Console/Commands/ModuleGenerateCommandTest.php Outdated
Comment thread tests/Unit/Console/Commands/OpenApiCommandTest.php
Comment thread tests/Unit/Console/Commands/VersionCommandTest.php Outdated
@armanist
armanist merged commit 317224b into quantum-php:master Apr 30, 2026
6 of 7 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
tests/Unit/Console/Commands/VersionCommandTest.php (2)

34-41: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t let missing font assets count as a functional pass.

At Line 34, the fallback path can pass without validating the command’s success-path output, which weakens coverage confidence for this command. Skip when the asset is unavailable (or ensure the asset is present) so a pass always means behavior was actually asserted.

Proposed change
-        if (!is_file($fontPath)) {
-            $this->expectException(\Exception::class);
-            $this->expectExceptionMessage('slant.flf');
-        }
+        if (!is_file($fontPath)) {
+            $this->markTestSkipped('Missing figlet font: ' . $fontPath);
+        }

-        $tester->execute([]);
+        $exitCode = $tester->execute([]);
         $output = $tester->getDisplay();
+        $this->assertSame(0, $exitCode);
         $this->assertStringContainsString('3.0.0', $output);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/Unit/Console/Commands/VersionCommandTest.php` around lines 34 - 41, The
test currently falls through when the font asset ($fontPath) is missing, letting
the success-path assertions run despite not exercising real behavior; update the
guard that checks is_file($fontPath) to call $this->markTestSkipped('Missing
font asset: slant.flf') (or ensure the asset is installed before running)
instead of setting expectException so the test is skipped when the asset is
absent, leaving the subsequent $tester->execute([]) and the assertion that
'3.0.0' appears in the output to only run when the font file is present.

29-29: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Restore global config after this test.

Line 29 mutates shared config state and does not restore it, which can make later tests order-dependent.

Proposed change
     public function testExecPrintsFrameworkVersion(): void
     {
-        config()->set('app', ['version' => '3.0.0']);
+        $previousAppConfig = config()->get('app');
+        config()->set('app', ['version' => '3.0.0']);

-        $tester = new CommandTester($this->command);
-        $fontPath = assets_dir() . DS . 'shared' . DS . 'fonts' . DS . 'figlet' . DS . 'slant.flf';
+        try {
+            $tester = new CommandTester($this->command);
+            $fontPath = assets_dir() . DS . 'shared' . DS . 'fonts' . DS . 'figlet' . DS . 'slant.flf';

-        if (!is_file($fontPath)) {
-            $this->expectException(\Exception::class);
-            $this->expectExceptionMessage('slant.flf');
-        }
+            if (!is_file($fontPath)) {
+                $this->markTestSkipped('Missing figlet font: ' . $fontPath);
+            }

-        $tester->execute([]);
-        $output = $tester->getDisplay();
-        $this->assertStringContainsString('3.0.0', $output);
+            $tester->execute([]);
+            $output = $tester->getDisplay();
+            $this->assertStringContainsString('3.0.0', $output);
+        } finally {
+            config()->set('app', $previousAppConfig);
+        }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/Unit/Console/Commands/VersionCommandTest.php` at line 29, The test
mutates global config by calling config()->set('app', ['version' => '3.0.0'])
and does not restore it; capture the original app config before setting (e.g.
$originalApp = config('app')) and restore it after the test completes (either in
the test itself or in VersionCommandTest::tearDown()) by calling
config()->set('app', $originalApp) so other tests aren’t affected.
🧹 Nitpick comments (1)
tests/Unit/Console/Commands/ModuleGenerateCommandTest.php (1)

62-67: ⚡ Quick win

Strengthen assertions for module config semantics.

This currently checks only entry presence. Add assertions for the created module config payload (e.g., prefix and enabled) so regressions in option/template wiring are caught.

Suggested assertion upgrade
         $moduleConfigs = $this->fs->require($this->modulesConfigPath);
-        if (is_array($moduleConfigs) && isset($moduleConfigs[$this->moduleName])) {
-            $this->moduleConfigCreatedByTest = true;
-        }
+        $this->assertIsArray($moduleConfigs);
+        $this->assertArrayHasKey($this->moduleName, $moduleConfigs);
+        $this->assertArrayHasKey('prefix', $moduleConfigs[$this->moduleName]);
+        $this->assertArrayHasKey('enabled', $moduleConfigs[$this->moduleName]);
+        $this->moduleConfigCreatedByTest = true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/Unit/Console/Commands/ModuleGenerateCommandTest.php` around lines 62 -
67, The test currently only verifies the module entry exists; update the
assertions after loading $moduleConfigs from $this->modulesConfigPath (and after
the existing $moduleConfigCreatedByTest logic) to assert the created module's
config values explicitly: fetch $moduleConfigs[$this->moduleName] and assert it
is an array, then assert its 'prefix' equals the expected prefix value (derived
from $this->moduleName or the test's expected string) and assert its 'enabled'
flag equals the expected boolean; keep the existing string assertion against
$tester->getDisplay() but add these payload assertions to catch regressions in
prefix/enabled wiring.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/Unit/Console/Commands/ModuleGenerateCommandTest.php`:
- Around line 70-93: The teardown currently skips cleanup when runtime flags
($this->moduleConfigCreatedByTest, $this->moduleCreatedByTest) were not set,
which can leave artifacts if a test fails before setting them; change tearDown()
to base cleanup solely on current state checks: for the modules config use
$this->fs->exists($this->modulesConfigPath), require the file, verify is_array
and isset($moduleConfigs[$this->moduleName]) and then unset and write back
(keeping the existing export and "<?php\n\nreturn " pattern); for module
directory removal remove the $this->moduleCreatedByTest check and instead use
$this->fs->isDirectory($this->modulePath), basename($this->modulePath) ===
$this->moduleName and strpos($this->moduleName, 'Issue479Module_') === 0 to
decide to delete the directory—this ensures cleanup depends only on
filesystem/config state not on test-set flags.

---

Duplicate comments:
In `@tests/Unit/Console/Commands/VersionCommandTest.php`:
- Around line 34-41: The test currently falls through when the font asset
($fontPath) is missing, letting the success-path assertions run despite not
exercising real behavior; update the guard that checks is_file($fontPath) to
call $this->markTestSkipped('Missing font asset: slant.flf') (or ensure the
asset is installed before running) instead of setting expectException so the
test is skipped when the asset is absent, leaving the subsequent
$tester->execute([]) and the assertion that '3.0.0' appears in the output to
only run when the font file is present.
- Line 29: The test mutates global config by calling config()->set('app',
['version' => '3.0.0']) and does not restore it; capture the original app config
before setting (e.g. $originalApp = config('app')) and restore it after the test
completes (either in the test itself or in VersionCommandTest::tearDown()) by
calling config()->set('app', $originalApp) so other tests aren’t affected.

---

Nitpick comments:
In `@tests/Unit/Console/Commands/ModuleGenerateCommandTest.php`:
- Around line 62-67: The test currently only verifies the module entry exists;
update the assertions after loading $moduleConfigs from $this->modulesConfigPath
(and after the existing $moduleConfigCreatedByTest logic) to assert the created
module's config values explicitly: fetch $moduleConfigs[$this->moduleName] and
assert it is an array, then assert its 'prefix' equals the expected prefix value
(derived from $this->moduleName or the test's expected string) and assert its
'enabled' flag equals the expected boolean; keep the existing string assertion
against $tester->getDisplay() but add these payload assertions to catch
regressions in prefix/enabled wiring.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bb8047cc-6b3c-4c9b-8e66-fabcb54027f1

📥 Commits

Reviewing files that changed from the base of the PR and between d5fa5a6 and fce3398.

📒 Files selected for processing (4)
  • tests/Unit/Console/Commands/InstallToolkitCommandTest.php
  • tests/Unit/Console/Commands/ModuleGenerateCommandTest.php
  • tests/Unit/Console/Commands/OpenApiCommandTest.php
  • tests/Unit/Console/Commands/VersionCommandTest.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/Unit/Console/Commands/InstallToolkitCommandTest.php

Comment thread tests/Unit/Console/Commands/ModuleGenerateCommandTest.php
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate command coverage gaps and raise command suite to >=90%

1 participant