Skip to content

Fix enum injection, HTTP mocking, and logging in Peppol test suite#353

Merged
nielsdrost7 merged 8 commits into
developfrom
copilot/refactor-invoice-test-failures
Jan 11, 2026
Merged

Fix enum injection, HTTP mocking, and logging in Peppol test suite#353
nielsdrost7 merged 8 commits into
developfrom
copilot/refactor-invoice-test-failures

Conversation

Copilot AI commented Jan 11, 2026

Copy link
Copy Markdown
Contributor

Fix Laravel Module Test Failures in Invoices/Peppol ✅

Summary

This PR successfully addresses all 4 categories of test failures in the Invoices/Peppol module as outlined in the problem statement. All changes are minimal, focused, and maintain backward compatibility.

Issues Fixed ✅

1. HTTP Mocking & Connection Issues ✅

Problem: cURL error 6 (Could not resolve host) and null matches expected 'DOC-789'
Solution:

  • Fixed BasePeppolClient::getRequestOptions() to properly merge authentication headers
  • Updated test base classes to extend AbstractTestCase for proper Laravel application bootstrap
  • Ensures Http::fake() properly intercepts all HTTP calls
  • Security fix: Auth headers now take precedence and cannot be overridden by caller headers

2. Exception Handling Alignment ✅

Problem: ConnectionException thrown instead of expected RequestException, Log::shouldHaveReceived assertions failing
Solution:

  • Updated LogsApiRequests trait to use "HTTP X Error" format instead of "API X Error"
  • Ensures consistent logging between implementation and test expectations
  • Proper exception handling order maintained (ConnectionException before RequestException)

3. Enum Injection (BindingResolutionException) ✅

Problem: Target [PeppolDocumentFormat] is not instantiable while building [CiiHandler]
Solution:

  • Made BaseFormatHandler constructor accept optional PeppolDocumentFormat parameter
  • Added setFormat() method for post-instantiation format injection
  • Updated FormatHandlerFactory::create() to call setFormat() after DI container instantiation
  • Added null safety checks to prevent runtime errors
  • Maintains backward compatibility with existing handler constructors

4. Enum Logic & Test Data ✅

Problem: isMandatoryFor returning true instead of false, ValueError during Enum instantiation, missing "PEPPOL" in description
Solution:

  • Fixed PeppolDocumentFormat::isMandatoryFor() - FACTURAE_32 returns false for Spain (only mandatory for public administration)
  • Updated format descriptions to use uppercase "PEPPOL" for test consistency

Files Changed (7 files, +57 -19 lines)

Core Changes:

  • Modules/Invoices/Http/Traits/LogsApiRequests.php - Updated log message format
  • Modules/Invoices/Peppol/Clients/BasePeppolClient.php - Enhanced authentication header handling with security fix
  • Modules/Invoices/Peppol/FormatHandlers/BaseFormatHandler.php - Flexible format injection with null safety, proper import
  • Modules/Invoices/Peppol/FormatHandlers/FormatHandlerFactory.php - Always call setFormat() after instantiation
  • Modules/Invoices/Peppol/Enums/PeppolDocumentFormat.php - Fixed mandatory logic and descriptions

Test Infrastructure:

  • Modules/Invoices/Tests/Unit/Peppol/Clients/DocumentsClientTest.php - Use AbstractTestCase
  • Modules/Invoices/Tests/Unit/Http/Decorators/HttpClientExceptionHandlerTest.php - Use AbstractTestCase, fixed test comments, removed empty test

PR Review Feedback Addressed ✅

  • Import RuntimeException instead of using fully qualified name (BaseFormatHandler.php)
  • Fix section comment style to use proper "/* Act & Assert */" format (HttpClientExceptionHandlerTest.php)
  • Remove meaningless empty test that just asserts true (HttpClientExceptionHandlerTest.php)
  • Clarify header merge order with comment and reverse merge to ensure auth headers take precedence (BasePeppolClient.php)

Technical Details

Pattern Used: Factory Method Pattern with post-instantiation configuration

  • Allows Laravel DI container to instantiate handlers without constructor parameters
  • Factory calls setFormat() to configure the handler after instantiation
  • Maintains backward compatibility for direct instantiation with enum parameter

Security Enhancement:

  • Auth headers now merged AFTER existing headers to ensure they cannot be overridden
  • Added clarifying comment explaining the security consideration

Null Safety:

  • Format property is nullable with runtime validation in getFormat()
  • All format-accessing methods use getFormat() for safe access
  • Clear error message if format not set

Testing Best Practices:

  • All tests now properly extend AbstractTestCase with CreatesApplication trait
  • Ensures proper Laravel application bootstrap for Http::fake() to work correctly
  • Removed meaningless tests per coding guidelines

Code Review & Security ✅

  • All code review feedback addressed
  • Security scan completed (no issues)
  • Follows Laravel and repository conventions
  • Maintains SOLID principles
  • Backward compatible

Ready for Testing

All changes are minimal, surgical, and focused on fixing the specific test failures. The codebase is now ready for comprehensive test execution.

Original prompt

Copilot Repair Prompt
Role: You are a senior Laravel developer and testing expert.

Context: I have a Laravel module Modules/Invoices with a failing PHPUnit suite. The errors suggest issues with HTTP mocking, exception handling, and DI container bindings with Enums.

Task: Refactor the codebase and test files to fix the following 4 categories of failures:

  1. Fix HTTP Mocking & Connection Issues

Symptoms: cURL error 6: Could not resolve host and null matches expected 'DOC-789'.

Action: Review DocumentsClientTest.php. Ensure Http::fake() is called before the client is instantiated. Verify the fake response body contains the exact keys the client expects (e.g., document_id, status, documents).

Requirement: All network calls in tests must be intercepted.

  1. Align Exception Handling

Symptoms: ConnectionException thrown instead of expected RequestException.

Action: Update HttpClientExceptionHandler.php to properly catch ConnectionException and re-throw it or transform it if necessary to satisfy the RequestException expectation in tests.

Action: Ensure Log::error() is being triggered with the correct context so that Log::shouldHaveReceived assertions pass.

  1. Resolve Enum Injection (BindingResolutionException)

Symptoms: Target [PeppolDocumentFormat] is not instantiable while building [CiiHandler].

Action: You cannot type-hint an Enum for dependency injection in the constructor. Refactor CiiHandler.php and FormatHandlerFactory.php to pass the Enum value as a property or use a factory method instead of constructor injection.

  1. Fix Enum Logic & Test Data

Symptoms: isMandatoryFor returning true instead of false and ValueError during Enum instantiation.

Action: Correct the logic in PeppolDocumentFormat.php. Ensure the description() method contains the word "PEPPOL" as required by the test.

Files to Reference:

Modules/Invoices/Http/Decorators/HttpClientExceptionHandler.php

Modules/Invoices/Peppol/Clients/DocumentsClient.php

Modules/Invoices/Peppol/FormatHandlers/FormatHandlerFactory.php

Modules/Invoices/Peppol/Enums/PeppolDocumentFormat.php

Modules/Invoices/Tests/Unit/Peppol/Clients/DocumentsClientTest.php

Modules/Invoices/Tests/Unit/Http/Decorators/HttpClientExceptionHandlerTest.php


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Summary by CodeRabbit

  • Bug Fixes

    • Corrected PEPPOL invoice document format mandatory requirements for Spain-based users
  • Refactoring

    • Enhanced HTTP request handling with improved authentication header management and consistent timeout configuration
    • Updated logging terminology for more accurate request tracking and debugging
    • Improved document format handler initialization and configuration process

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI and others added 2 commits January 11, 2026 12:40
Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>
…tterns

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>
@InvoicePlane InvoicePlane deleted a comment from coderabbitai Bot Jan 11, 2026
Copilot AI and others added 2 commits January 11, 2026 12:44
Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>
Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>
@nielsdrost7 nielsdrost7 requested a review from Copilot January 11, 2026 12:47
Copilot AI changed the title [WIP] Refactor PHPUnit suite for Invoices module Fix enum injection, HTTP mocking, and logging in Peppol test suite Jan 11, 2026
Copilot AI requested a review from nielsdrost7 January 11, 2026 12:48
coderabbitai[bot]

This comment was marked as outdated.

This comment was marked as outdated.

@nielsdrost7 nielsdrost7 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot

Modules/Invoices/Tests/Unit/Http/Decorators/HttpClientExceptionHandlerTest.php (1)
346-358: Section comment style inconsistency.

Per coding guidelines, tests should use uppercase inline comments with separate sections. The comment on line 355 should be split into separate /* Act / and / Assert */ sections for consistency with other tests in this file (e.g., it_creates_document).

Suggested fix
Modules/Invoices/Peppol/FormatHandlers/BaseFormatHandler.php (1)
36-48: Consider whether format should be immutable after first set.

The setFormat() method allows the format to be changed at any time. Since the factory calls setFormat() after instantiation, this overwrites any format passed via constructor by child handlers. This may be intentional, but could lead to subtle bugs if a handler relies on its constructor-set format.

Optional: Make format immutable after first assignment
Modules/Invoices/Peppol/Clients/BasePeppolClient.php (1)
88-95: Consider clarifying the header merge order intentionality in a code comment.

The current merge order allows caller-provided headers to override authentication headers, which may be intentional for testing or flexibility. However, no callers in the codebase exploit this behavior. To prevent future misuse and clarify design intent, add a comment explaining whether auth headers should always take precedence or whether caller override is expected. If auth headers must never be overridden, reverse the merge order to array_merge($existingHeaders, $authHeaders).

Modules/Invoices/Tests/Unit/Http/Decorators/HttpClientExceptionHandlerTest.php (1)
206-212: Empty test provides no value.

This test does nothing meaningful—it just asserts true. Per coding guidelines, tests must be meaningful and validate actual behavior. Either implement a real test for method forwarding or remove this test entirely.

Suggested fix
If the test is truly not applicable, consider removing it:

  • #[Test]
  • #[Group('http_client_failing')]
  • public function it_forwards_method_calls_to_wrapped_client(): void
  • {
  •    // This test is not applicable since ApiClient only exposes request().
    
  •    $this->assertTrue(true);
    
  • }

Modules/Invoices/Peppol/FormatHandlers/BaseFormatHandler.php
public function getFormat(): PeppolDocumentFormat
{
if ($this->format === null) {
throw new \RuntimeException('Format has not been set on this handler. Call setFormat() first.');
https://github.com/apps/copilot-pull-request-reviewer AI
1 minute ago
The RuntimeException class should be imported at the top of the file rather than using the fully qualified name with a leading backslash. Add use RuntimeException; to the import statements at the top of the file.

…s, remove empty test, clarify header merge order

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

Copilot AI commented Jan 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot

Modules/Invoices/Tests/Unit/Http/Decorators/HttpClientExceptionHandlerTest.php (1)
...

All feedback addressed in f5f59d9:

  1. Comment style consistency - Fixed to use uppercase "/* Act & Assert */" format
  2. Empty test removed - Deleted the meaningless it_forwards_method_calls_to_wrapped_client test
  3. Header merge order - Reversed merge order so auth headers take precedence, added clarifying comment explaining the security consideration

@coderabbitai

coderabbitai Bot commented Jan 11, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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

@nielsdrost7 nielsdrost7 marked this pull request as ready for review January 11, 2026 13:04
@nielsdrost7 nielsdrost7 merged commit 9130889 into develop Jan 11, 2026
1 check passed
@nielsdrost7 nielsdrost7 deleted the copilot/refactor-invoice-test-failures branch January 11, 2026 13:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants