Release Billplz 6.0 with Money objects, bundled Codex internals, and updated CI#59
Release Billplz 6.0 with Money objects, bundled Codex internals, and updated CI#59abdusfauzi merged 22 commits intojomweb:6.xfrom
Conversation
Pull Request Test Coverage Report for Build 22936394180Details
💛 - Coveralls |
There was a problem hiding this comment.
Pull request overview
Prepares the 6.x line for Billplz 6.0 by migrating money handling to Money\Money, bundling Codex internals into the package, and modernizing QA/CI (Pest v4, PHPStan, Pint, repo-managed git hooks).
Changes:
- Migrates the test suite from PHPUnit test classes to Pest tests + shared “register tests” helpers.
- Bundles
Laravie\Codexinternals undersrc/Internal/Codexand updates autoloading accordingly. - Updates project tooling: raises PHP requirement to
^8.3, adds Composer QA scripts and aligns GitHub Actions to run them.
Reviewed changes
Copilot reviewed 107 out of 109 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Three/OpenCollectionTest.php | Migrates v3 open collection tests to Pest + shared registration helper. |
| tests/Three/CollectionTest.php | Migrates v3 collection tests to Pest + shared registration helper. |
| tests/Three/Collection/PaymentMethodTest.php | Migrates v3 payment-method tests to Pest + shared registration helper. |
| tests/Three/BillTest.php | Migrates v3 bill tests to Pest + shared registration helper. |
| tests/Three/Bill/TransactionTest.php | Migrates v3 transaction tests to Pest + shared registration helper. |
| tests/Three/BankAccountTest.php | Migrates v3 bank-account tests to Pest + shared registration helper. |
| tests/SignatureTest.php | Migrates signature verification tests to Pest. |
| tests/SanitizerTest.php | Migrates sanitizer signature test to Pest. |
| tests/Pest.php | Adds Pest bootstrap + shared billplz_register_tests() helper and requires shared test definitions. |
| tests/PaymentCompletionTest.php | Migrates payment completion tests to Pest. |
| tests/Four/WebhookTest.php | Migrates v4 webhook tests to Pest. |
| tests/Four/PayoutTest.php | Migrates v4 payout tests to Pest. |
| tests/Four/PaymentGatewayTest.php | Migrates v4 payment gateway tests to Pest. |
| tests/Four/OpenCollectionTest.php | Migrates v4 open collection tests to Pest + shared registration helper. |
| tests/Four/CollectionTest.php | Migrates v4 collection tests to Pest and adds hook-based proxy version setup. |
| tests/Four/Collection/PayoutTest.php | Migrates v4 collection payout tests to Pest. |
| tests/Four/Collection/PaymentMethodTest.php | Migrates v4 payment-method tests to Pest + shared registration helper. |
| tests/Four/CardTest.php | Migrates v4 card tests to Pest. |
| tests/Four/BillTest.php | Migrates v4 bill tests to Pest; updates assertions to Money\Money. |
| tests/Four/Bill/TransactionTest.php | Migrates v4 transaction tests to Pest + shared registration helper. |
| tests/Four/BankAccountTest.php | Migrates v4 bank account tests to Pest + shared registration helper. |
| tests/Five/WebhookTest.php | Migrates v5 webhook tests to Pest. |
| tests/Five/PayoutTest.php | Migrates v5 payout tests to Pest. |
| tests/Five/PaymentOrderTest.php | Adds Pest tests covering v5 PaymentOrder endpoints. |
| tests/Five/PaymentOrderCollectionTest.php | Adds Pest tests covering v5 PaymentOrderCollection endpoints. |
| tests/Five/BankAccountTest.php | Migrates v5 bank account tests to Pest + shared registration helper. |
| tests/ClientTest.php | Migrates client tests to Pest and extends shared TestCase. |
| tests/Casts/DateTimeTest.php | Migrates DateTime cast tests to Pest. |
| tests/Base/OpenCollectionTests.php | Introduces shared open-collection test registration helper. |
| tests/Base/OpenCollectionTestCase.php | Removes PHPUnit base test-case class in favor of Pest helper registration. |
| tests/Base/CollectionTests.php | Introduces shared collection test registration helper. |
| tests/Base/CollectionTestCase.php | Removes PHPUnit base test-case class in favor of Pest helper registration. |
| tests/Base/Collection/PaymentMethodTests.php | Introduces shared payment-method test registration helper. |
| tests/Base/Collection/PaymentMethodTestCase.php | Removes PHPUnit base test-case class in favor of Pest helper registration. |
| tests/Base/BillTestCase.php | Removes large PHPUnit base test-case class in favor of Pest helper registration. |
| tests/Base/Bill/TransactionTests.php | Introduces shared bill-transaction test registration helper. |
| tests/Base/Bill/TransactionTestCase.php | Removes PHPUnit transaction test-case class in favor of Pest helper registration. |
| tests/Base/BankAccountTests.php | Introduces shared bank-account test registration helper. |
| tests/Base/BankAccountTestCase.php | Removes PHPUnit base test-case class in favor of Pest helper registration. |
| tests/ArraySubsetTest.php | Adds test for updated ArraySubset exporter behavior. |
| src/Sanitizer.php | Switches default money caster from Ringgit to Money. |
| src/Request.php | Minor style change (new Sanitizer without parentheses). |
| src/Internal/Codex/Testing/Faker.php | Bundles Codex testing Faker implementation used by tests. |
| src/Internal/Codex/Testing/Assert.php | Bundles Codex assert compatibility layer (array subset). |
| src/Internal/Codex/Testing/ArraySubset.php | Bundles Codex ArraySubset constraint with PHPUnit version branching. |
| src/Internal/Codex/Support/Versioning.php | Bundles Codex versioning + proxy-version request helper. |
| src/Internal/Codex/Support/Responsable.php | Bundles Codex response interaction helper for requests. |
| src/Internal/Codex/Support/HttpClient.php | Bundles Codex HttpClient trait wrapper. |
| src/Internal/Codex/Response.php | Bundles Codex Response wrapper class. |
| src/Internal/Codex/Request.php | Bundles Codex base Request implementation. |
| src/Internal/Codex/Payload.php | Bundles Codex Payload wrapper class. |
| src/Internal/Codex/Filter/WithSanitizer.php | Bundles Codex filterable sanitizer trait. |
| src/Internal/Codex/Filter/Sanitizer.php | Bundles Codex sanitizer implementation. |
| src/Internal/Codex/Filter/Cast.php | Bundles Codex cast base class. |
| src/Internal/Codex/Exceptions/UnauthorizedException.php | Bundles Codex Unauthorized exception. |
| src/Internal/Codex/Exceptions/NotFoundException.php | Bundles Codex NotFound exception. |
| src/Internal/Codex/Exceptions/HttpException.php | Bundles Codex HttpException base. |
| src/Internal/Codex/Endpoint.php | Bundles Codex Endpoint wrapper class. |
| src/Internal/Codex/Discovery.php | Bundles Codex discovery wrapper class. |
| src/Internal/Codex/Contracts/Sanitizer.php | Bundles Codex sanitizer contract. |
| src/Internal/Codex/Contracts/Response.php | Bundles Codex response contract. |
| src/Internal/Codex/Contracts/Request.php | Bundles Codex request contract. |
| src/Internal/Codex/Contracts/Filterable.php | Bundles Codex filterable contract. |
| src/Internal/Codex/Contracts/Endpoint.php | Bundles Codex endpoint contract. |
| src/Internal/Codex/Contracts/Client.php | Bundles Codex client contract. |
| src/Internal/Codex/Contracts/Cast.php | Bundles Codex cast contract. |
| src/Internal/Codex/Concerns/Request/Multipart.php | Bundles Codex multipart request concern. |
| src/Internal/Codex/Concerns/Request/Json.php | Bundles Codex JSON request concern. |
| src/Internal/Codex/Concerns/Passport.php | Bundles Codex “Passport” credential helpers. |
| src/Internal/Codex/Common/Response.php | Bundles Codex common response implementation. |
| src/Internal/Codex/Common/Request.php | Bundles Codex common request implementation. |
| src/Internal/Codex/Common/Payload.php | Bundles Codex common payload implementation. |
| src/Internal/Codex/Common/HttpClient.php | Bundles Codex HTTP client behavior (payload prep + query handling). |
| src/Internal/Codex/Common/Endpoint.php | Bundles Codex endpoint implementation. |
| src/Internal/Codex/Common/Discovery.php | Bundles Codex HTTP discovery. |
| src/Internal/Codex/Client.php | Bundles Codex base client implementation (uses()/version selection). |
| src/Four/Bill.php | Updates docblock amount type to `Money\Money |
| src/Five/PaymentOrder.php | Removes identity number parameter from create() signature/payload. |
| src/Contracts/PaymentOrder.php | Updates contract to match PaymentOrder::create() signature change. |
| src/Contracts/OpenCollection.php | Updates docblock amount type to `Money\Money |
| src/Contracts/Bill.php | Updates docblock amount type to `Money\Money |
| src/Checksum.php | Fixes comment spacing. |
| src/Casts/Ringgit.php | Removes Ringgit caster (Duit integration). |
| src/Casts/Money.php | Updates money cast validation/docblocks to only accept Money\Money. |
| src/Base/PaymentCompletion.php | Minor style change when throwing exception. |
| src/Base/OpenCollection.php | Updates docblock amount type to `Money\Money |
| src/Base/Bill.php | Updates docblock amount type to `Money\Money |
| phpunit.xml | Updates PHPUnit config schema to PHPUnit 12.5 format. |
| phpstan.neon.dist | Removes checkMissingIterableValueType override. |
| examples/v5/creating-payment-order.php | Updates example to match PaymentOrder signature change. |
| docs/release-notes-v6.0.0.md | Adds v6.0.0 release notes draft. |
| docs/release-6.0.0.md | Adds maintainer release checklist. |
| docs/pr-jomweb-billplz-6x.md | Adds upstream PR draft. |
| docs/plans/2026-03-11-ci-alignment-and-release-drafts-plan.md | Adds CI alignment + draft docs plan. |
| docs/plans/2026-03-10-release-docs-implementation-plan.md | Adds release docs implementation plan. |
| docs/plans/2026-03-10-release-docs-design.md | Adds release docs design notes. |
| docs/plans/2026-03-10-git-hooks-qa-plan.md | Adds repo-managed git hooks QA plan. |
| composer.json | Updates dependencies (PHP 8.3+, Money, bundled Codex), adds scripts and autoload mapping for internal Codex. |
| README.md | Updates badges/installation/upgrade notes + replaces Duit examples with Money. |
| CONTRIBUTING.md | Updates contributor workflow to use Composer scripts + repo git hooks; updates CI reference. |
| CHANGELOG-6.x.md | Adds v6.x changelog and upgrade notes. |
| .gitignore | Adds PHPUnit cache directory. |
| .github/workflows/tests.yml | Updates CI matrix (PHP versions) and runs tests via Composer script. |
| .github/workflows/coveralls.yml | Runs coverage via Composer script. |
| .github/workflows/analyse.yml | Aligns Pint/PHPStan steps to Composer scripts and updates PHP matrix. |
| .githooks/pre-push | Adds repo-managed pre-push hook to run analyse + parallel tests. |
| .githooks/pre-commit | Adds repo-managed pre-commit hook to run Pint lint. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| it('can create payment order collection', function (): void { | ||
| $title = 'My First API Payment Order Collection'; | ||
| $epoch = time(); | ||
| $expected = '{"id":"8f4e331f-ac71-435e-a870-72fe520b4563","title":"My First API Payment Order Collection","callback_url":"https:\/\/example.com\/payment-orders\/callback"}'; | ||
|
|
||
| $payload = [ | ||
| 'title' => $title, | ||
| 'epoch' => $epoch, | ||
| 'checksum' => Checksum::create(TestCase::X_SIGNATURE, [ | ||
| $title, | ||
| 'https://example.com/payment-orders/callback', | ||
| $epoch, | ||
| ]), | ||
| 'callback_url' => 'https://example.com/payment-orders/callback', | ||
| ]; |
There was a problem hiding this comment.
This test computes $epoch = time() and a checksum based on it, but the PaymentOrderCollection implementation also calls time() internally to build the request. That makes the expected request payload fragile/flaky if time advances between the two calls. Make the request deterministic by allowing a caller-supplied epoch (and computing checksum from that), or by injecting a clock that can be controlled in tests.
| /** @var class-string<\Laravie\Codex\Contracts\Request> $class */ | ||
| $class = sprintf('%s\%s\%s', $this->getResourceNamespace(), $this->supportedVersions[$version], $name); | ||
|
|
||
| if (! class_exists($class)) { | ||
| throw new InvalidArgumentException("Resource [{$service}] for version [{$version}] is not available."); | ||
| } | ||
|
|
||
| return $this->via(new $class($this)); | ||
| } |
There was a problem hiding this comment.
uses() instantiates the request with new $class($this), but the request classes (e.g. Billplz\Request / Laravie\Codex\Request) don’t accept a client argument in their constructors. This will trigger an ArgumentCountError the first time any resource is resolved. Instantiate with new $class() and rely on via() to call setClient(), or update the request base class constructor signature consistently across resources.
| 'can check bill transaction' => function (): void { | ||
| $expected = '{"bill_id":"inbmmepb","transactions":[{"id":"60793D4707CD","status":"completed","completed_at":"2017-02-23T12:49:23.612+08:00","payment_channel":"FPX"},{"id":"28F3D3194138","status":"failed","completed_at":,"payment_channel":"FPX"}],"page":1}'; | ||
|
|
There was a problem hiding this comment.
The $expected response body is invalid JSON ("completed_at":,). If any code calls toArray()/getContent() on this response (now using JSON_THROW_ON_ERROR), it will throw. Update the fixture to valid JSON (e.g. "completed_at":null) to avoid decoding failures.
| it('can create payment order', function (): void { | ||
| $paymentOrderCollectionId = '8f4e331f-ac71-435e-a870-72fe520b4563'; | ||
| $bankAccountNumber = '543478924652'; | ||
| $total = 2000; | ||
| $epoch = time(); | ||
| $expected = '{"id":"cc92738f-dfda-4969-91dc-22a44afc7e26","payment_order_collection_id":"8f4e331f-ac71-435e-a870-72fe520b4563","bank_code":"MBBEMYKL","bank_account_number":"543478924652","name":"Michael Yap","description":"Maecenas eu placerat ante.","total":"2000","status":"pending"}'; | ||
|
|
||
| $payload = [ | ||
| 'payment_order_collection_id' => $paymentOrderCollectionId, | ||
| 'bank_code' => 'MBBEMYKL', | ||
| 'bank_account_number' => $bankAccountNumber, | ||
| 'name' => 'Michael Yap', | ||
| 'description' => 'Maecenas eu placerat ante.', | ||
| 'total' => $total, | ||
| 'epoch' => $epoch, | ||
| 'checksum' => Checksum::create(TestCase::X_SIGNATURE, [ | ||
| $paymentOrderCollectionId, | ||
| $bankAccountNumber, | ||
| $total, | ||
| $epoch, | ||
| ]), | ||
| ]; |
There was a problem hiding this comment.
These tests build an expected payload/query using $epoch = time(), but the underlying PaymentOrder methods also call time() internally when computing epoch/checksum. If the second ticks over between the test’s time() and the method’s time(), the expected request won’t match and the test becomes flaky. Prefer passing a fixed epoch (and deriving checksum from it) via method parameters/optional overrides, or inject/mock the clock in the implementation so tests can be deterministic.
| public function send(string $method, EndpointContract $uri, array $headers = [], $body = []): ResponseInterface | ||
| { | ||
| $method = strtoupper($method); | ||
|
|
||
| if ($method === 'GET' && ! $body instanceof StreamInterface) { | ||
| $uri->addQuery($body); | ||
| $body = null; | ||
| } |
There was a problem hiding this comment.
In send(), GET requests call $uri->addQuery($body) for any non-stream body. If $body is a Laravie\Codex\Common\Payload (allowed by the phpdoc), Endpoint::addQuery() will receive an object and can throw (illegal offset type / unexpected key). Consider unwrapping Payload to an array before addQuery(), or restrict GET bodies to arrays and enforce it with a runtime check.
| 'can check bill transaction' => function (): void { | ||
| $expected = '{"bill_id":"inbmmepb","transactions":[{"id":"60793D4707CD","status":"completed","completed_at":"2017-02-23T12:49:23.612+08:00","payment_channel":"FPX"},{"id":"28F3D3194138","status":"failed","completed_at":,"payment_channel":"FPX"}],"page":1}'; | ||
|
|
||
| $faker = $this->expectRequest('GET', 'bills/inbmmepb/transactions') | ||
| ->shouldResponseWithJson(200, $expected); |
There was a problem hiding this comment.
The $expected fixture is invalid JSON ("completed_at":,). With responses now decoded using json_decode(..., JSON_THROW_ON_ERROR), calling toArray() on this response would throw a JsonException. Update the fixture to valid JSON (e.g. "completed_at":null) so it reflects a realistic API response and won’t break decoding.
|
Added a small coverage pass on the Codex internals that Coveralls flagged most heavily. Changes in this push:
Local verification:
Coveralls may still report a large delta here because this bootstrap If the branch checks are otherwise acceptable, please consider ignoring or relaxing the Coveralls gate for this initial |
PR Draft For
jomweb/billplzTitle
Release Billplz 6.0 with Money objects, bundled Codex internals, and updated CIBody
Summary
6.xline for Billplz 6.0.0\Money\MoneyChanges
8.3jomweb/ringgitlaravie/codexandlaravie/codex-filterdependencies6.xlineUpgrade Notes
\Money\Money\Money\Money::MYR(...)or integer minor units\Duit\MYRintegrations should convert from the returned Money amountVerification
composer validate --strictcomposer run qa