diff --git a/docs/plans/2026-07-12-framework-coroutine-state-lifecycle-audit-ledger.md b/docs/plans/2026-07-12-framework-coroutine-state-lifecycle-audit-ledger.md
index e47eb2343..1c3019bfb 100644
--- a/docs/plans/2026-07-12-framework-coroutine-state-lifecycle-audit-ledger.md
+++ b/docs/plans/2026-07-12-framework-coroutine-state-lifecycle-audit-ledger.md
@@ -134,3 +134,95 @@ Append package entries in checklist order. Keep each entry compact but complete
- **Implementation and cleanup:** Replaced the generic queue-contract checks with the Eloquent types the restoration path can actually reconstruct. Collection restoration now resolves the model class once before construction and pivot checks, matching the already-correct single-model path. Removed the now-unused generic imports and retained only focused comments at the two non-obvious boundaries; no user-facing difference entry was added.
- **Validation:** Eloquent relation stripping, non-Eloquent entity/collection round trips, and morph-mapped Eloquent collection restoration pass. Pre-implementation second-opinion consensus, owner approval, and work-unit code review are complete; the later full `queue` audit remains pending.
- **Revalidation:** Full `queue` audit remains pending.
+
+### Restore Conditionable proxy truthiness
+
+- **Architecture and inspected risk surfaces:** Conditionable consists of one stateless trait and one short-lived higher-order proxy under the shared `Hypervel\Support` namespace. The audit covered both source files, both package-owned test files, every framework consumer, all consuming split-package manifests, package history, and current Laravel source and tests. It found no static or worker-lifetime state, container lifetime, coroutine, resource, native boundary, or cleanup owner.
+
+| ID | Category | Severity | Confidence | Failure and owning boundary | Final decision |
+|---|---|---|---|---|---|
+| `conditionable-01` | Defect | Major | High | `HigherOrderWhenProxy::condition(bool)` rejects the non-boolean truthy/falsy values accepted by `when()` and returned by higher-order property/method capture | Accept `mixed` at the single setter boundary, normalize once into the existing bool property, and regress direct/property/method truthiness plus the symmetric `unless` path |
+| `conditionable-02` | Improvement | Improvement | High | Eight package-owned test methods omit the repository-required `void` return type | Add `: void` without restructuring the tests |
+| `conditionable-03` | Defect | Minor | High | `hypervel/log` directly uses the trait but is the sole one of 17 Hypervel consumer packages not to declare `hypervel/conditionable` | Add the direct split-package requirement, matching Hypervel's require-what-you-use convention |
+| `testbench-01` | Defect | Minor | High | Testbench CLI subprocesses implicitly rewrite the per-worker package manifest with root providers, and the shared Testbench lifecycle did not restore it between tests | Preserve the manifest once in the Testbench base test lifecycle and make the route-cache test assert its no-provider precondition |
+
+- **Important rejected concerns:** Do not add coroutine context, scoped bindings, cloning, locks, or cleanup machinery to a per-invocation proxy with no hidden shared state. Keep the Eloquent integration test because it verifies the split trait through a real consumer and its Capsule global is reset centrally. Do not consolidate the two upstream-mirrored test locations or add a README absent from this family of Laravel and Hypervel micro-packages.
+- **Cross-package implications:** `conditionable-03` corrects the `log` split manifest; the later full `log` audit must retain and revalidate that direct dependency. Future `macroable` and `collections` audits should repeat the same consumer-manifest sweep rather than assuming either a direct-edge or umbrella dependency convention. `testbench-01` belongs to the shared Testbench lifecycle and is also revalidated by the Foundation route-cache subprocess tests; the later full `testbench` and `foundation` audits must retain that ownership boundary.
+- **Implementation:** The higher-order proxy now accepts unconstrained condition values and stores their boolean normalization in its existing typed property. The log split manifest now declares its direct Conditionable dependency. Testbench snapshots the resolved package-manifest cache after application setup and restores its exact existence and contents through the existing exhaustive pre-destruction callback lifecycle, without rewriting an unchanged file. The route-cache precondition guard now reports unexpected raw package providers directly.
+- **Regression tests:** Conditionable coverage now exercises direct, higher-order property, and higher-order method truthiness with non-boolean values, plus the symmetric `unless` path. The remote-command regression forces a Testbench CLI child to rebuild a deleted manifest, then applies a deterministic probe mutation and verifies teardown restores the exact captured baseline. The previously failing remote-command-before-route-cache sequence passes deterministically.
+- **Performance and complexity:** The Conditionable correction adds one allocation-free boolean normalization per higher-order proxy condition. It adds no lookup, lock, yield, retained state, compatibility path, or abstraction. The manifest dependency and test signatures have no runtime cost. Manifest preservation adds small filesystem reads only to Testbench test setup/teardown and performs no write when the cache is unchanged; production and application hot paths are unaffected.
+- **Validation and review:** Focused Conditionable, remote-command, route-cache, and cross-test ordering regressions pass. The log split manifest validates strictly, `git diff --check` passes, and the full `composer fix` gate is green. Pre-implementation second-opinion consensus, owner approvals, fresh self-review, final code-review sign-off, and coherent commits are complete.
+- **Assessment:** The Conditionable architecture remains stateless, minimal, and coroutine-safe. The accepted changes correct one narrowed truthiness boundary, one split-manifest dependency, and one independently discovered Testbench worker-state leak at their respective owners without adding production machinery.
+
+### Complete Macroable callable and test-state handling
+
+- **Architecture and inspected risk surfaces:** Macroable is a leaf trait package whose only state is the per-using-class static macro registry. The audit covered both package files, current Laravel source and the originating static-closure fix, every framework trait consumer and reset hook, all consuming split-package manifests, package tests, public macro documentation, PHP closure-binding behavior with and without a throwing error handler, and the complete repository caller surface. Macro registration remains intentionally boot-time worker state; valid runtime reads require no lock or coroutine-local copy.
+
+| ID | Category | Severity | Confidence | Failure and owning boundary | Final decision |
+|---|---|---|---|---|---|
+| `macroable-01` | Defect | Minor | High | Instance dispatch fatals for static closures, and both dispatch paths fail valid first-class callable closures because PHP forbids rebinding them | Port Laravel's current static-closure behavior and retain the original callable when every legal rebind fails; cover all closure/call combinations, all three unbindable callable shapes, and invokable objects |
+| `macroable-02` | Defect | Minor | High | Eleven framework Macroable surfaces omit macro cleanup from their existing reset or have no registered reset, allowing one test's macros to survive into later tests | Complete the three existing reset methods, add eight standard static `flushState()` hooks, register them centrally, and exercise the real framework reset including inherited JsonApi macro storage |
+| `macroable-03` | Defect | Minor | High | Cookie, JWT, log, and notifications directly use Macroable but rely on a transitive dependency | Add the direct sorted `hypervel/macroable` requirement to all four split manifests |
+| `macroable-04` | Defect | Minor | High | Collections, HTTP-client, and response documentation contradict centralized framework test cleanup by instructing developers to clear framework macros manually | Document automatic framework cleanup and direct application/package-owned macro state to the existing test-state cleanup mechanism |
+| `macroable-05` | Defect | Minor | High | Macroable's test fixtures retain registered macros across methods | Flush both fixture registries during test teardown |
+| `macroable-06` | Improvement | Improvement | High | Existing Macroable test methods omit the repository-required return type | Add `: void` while merging current upstream coverage |
+| `http-01` | Defect | Minor | High | The new Request reset clears macros but leaves four inherited mutable Symfony configuration surfaces alive between framework tests | Reset only the inherited MIME-format, method-override, allowed-method, and request-factory state that Hypervel still uses |
+
+- **Important rejected concerns:** Do not make macros coroutine-local, lock immutable runtime reads, clone or cache callables, or add a manager/provider/reset registry. Current Laravel 13.x still fails closures produced from internal functions and first-class methods; Hypervel intentionally supports its existing callable contract, and the local source comment explains the PHP invariant without narrating upstream history. Focused PHPUnit coverage disproved the original assumption that unsupported bindings are silent outside a booted application. The checked native `bindTo()` boundaries therefore suppress their expected warnings and immediately inspect the nullable result; per-call reflection costs more, registration-time classification adds disproportionate parallel state, and warning-tolerant tests would hide real standalone behavior.
+- **Cross-package implications:** The later full audits of `cookie`, `jwt`, `log`, and `notifications` must retain and revalidate their direct Macroable dependencies. The later `database`, `support`, and `testing` audits must retain the completed static reset boundaries and centralized subscriber ownership. The later `http` audit must retain the completed inherited-state reset under shared finding `http-01` and separately judge whether the inherited public mutators need explicit boot-lifetime guidance.
+- **Completeness method:** Consumer/reset counts come from a whole-source trait-composition sweep, and documentation contradiction counts come from a whole-docs pattern sweep rather than an expected-file enumeration.
+- **Approved implementation boundary:** Keep the two magic dispatch paths explicit because their legal binding sequences differ. Add no helper or dynamic abstraction. Existing non-Closure callable dispatch is unchanged; ordinary closure macros still perform one binding operation. Suppressing the checked native warning adds a measured approximately 16 nanoseconds to closure-macro invocation; the owner approved that negligible opt-in cost after reviewing the more expensive or more complex alternatives. The additional binding attempt is confined to previously failing closure shapes. Static cleanup runs only between tests. Owner approval covers the callable behavior, eight additive public testing hooks, cross-package manifest corrections, and test-signature improvement.
+- **Implementation:** Macro dispatch now applies the legal instance/class and static/class binding sequence, suppresses only the native warnings whose nullable results are checked immediately, and retains already-valid first-class callables when PHP forbids rebinding. Three existing static resets now include macros; eight framework classes gained the standard static reset hook and central subscriber registration. Request's reset also restores the four mutable inherited Symfony configuration surfaces that remain live in Hypervel. Cookie, JWT, log, and notifications declare their direct Macroable dependency. Collections, HTTP-client, and response documentation now matches centralized framework cleanup. Macroable's own fixtures release their registries, and the earlier Testbench manifest regression now forces its restoration path with deterministic valid-PHP probe content instead of assuming a child rebuild must differ from the baseline.
+- **Regression tests:** Current Laravel's four static/non-static closure/call combinations are covered alongside protected class-scope preservation, closures from internal functions, bound instance-method and static-method first-class callables, and invokable objects. A real-subscriber regression registers macros on every previously omitted framework surface, including the inherited JsonApi entrypoint, and proves one authoritative reset clears them. A companion Request regression mutates every inherited mutable configuration surface Hypervel still consumes and proves the same reset restores Symfony's defaults. The Testbench remote-command test separately proves child recreation of a deleted manifest and exact teardown restoration after a deterministic mutation.
+- **Performance and complexity:** Ordinary methods and non-Closure callables are unchanged. The checked warning suppression adds a measured approximately 16 nanoseconds only to closure-macro calls; owner approval is recorded above. The Laravel-shaped exception fallback preserves the faster normal-closure path; an explicit null-branch rewrite measured slower on normal calls and substantially slower on static-closure calls. Test cleanup, manifest edges, test signatures, and documentation add no production cost. No lock, context slot, dynamic registry, reflection, callable cache, or compatibility path was added.
+- **Validation and review:** All focused Macroable, framework-reset, database-factory, HTTP, notification, and Testbench process tests pass. The four split manifests validate strictly, stale macro-cleanup documentation sweeps are clean, `git diff --check` passes, and the complete `composer fix` gate is green. Pre-implementation second-opinion consensus, owner approvals, focused unexpected-finding reviews, a fresh full-diff self-review, final independent code-review sign-off, and owner pre-commit approval are complete.
+- **Assessment:** Macroable remains a small boot-time static capability with lock-free runtime reads. The result is Laravel-compatible at the public API, supports the full existing callable contract, makes framework test cleanup exhaustive, and confines its only measured runtime cost to a negligible checked native boundary on opt-in closure macros without speculative machinery.
+
+### Shared finding `http-01`: inherited Request static-state reset
+
+- **Owner:** `http`, specifically mutable Symfony Request configuration inherited and consumed by `Hypervel\Http\Request`; `testing` owns the centralized framework reset invocation.
+- **Affected packages:** `macroable` introduced the Request reset while completing framework macro cleanup; `http` owns the underlying state and regression; `testing` invokes the reset.
+- **Failure:** Framework test teardown cleared Request macros but retained a custom MIME format, method-parameter override flag, allowed override list, and request factory for the rest of the PHPUnit worker. Later tests could therefore observe configuration established by an earlier test.
+- **Decision:** Restore only the four mutable inherited surfaces Hypervel still consumes to their installed Symfony defaults. Do not reset Symfony's trusted-proxy/host statics because Hypervel's complete trusted-request path uses coroutine-request instance state, and do not reset immutable response/status metadata or caches.
+- **Implementation and cleanup:** `Request::flushState()` now resets the lazy format table and both method-override settings directly, resets Symfony's private request-factory slot through its public setter, and then clears macros. No production path, inherited public mutator, trusted-request implementation, or immutable metadata changes.
+- **Validation:** A focused real-subscriber regression proves all four inherited values and their visible custom behavior disappear after framework cleanup. Focused HTTP/server coverage and the complete `composer fix` gate pass; final review sign-off and owner pre-commit approval are complete. The later full `http` and `testing` audits must retain and revalidate this boundary.
+- **Revalidation:** Full `http` and `testing` audits remain pending.
+
+### Correct Collections parity and iterable contracts
+
+- **Architecture and inspected risk surfaces:** Collections is a provider-free value and iterator package. Its only worker-lifetime state is the intentional Macroable registries on `Arr`, `Collection`, and `LazyCollection` plus the higher-order proxy registry shared by the concrete collections; all are already reset through the centralized test subscriber. The audit covered every package source file, split-package metadata, package-owned and Hypervel-specific tests, static-analysis fixtures, framework callers, public Collections and Arr documentation, current Laravel 13.x source/tests/docs, and each originating upstream change used to discover adjacent surfaces. No coroutine, container-lifetime, native-resource, timer, process, or cleanup owner exists in this package.
+
+| ID | Category | Severity | Confidence | Failure and owning boundary | Final decision |
+|---|---|---|---|---|---|
+| `collections-01` | Defect | Major | High | `LazyCollection::keyBy()` casts backed-enum keys to strings and crashes, while eager collections support them | Normalize enum and stringable object keys through the same object-only branch in both implementations |
+| `collections-02` | Defect | Major | High | `LazyCollection::has()` counts duplicate yielded keys as distinct requested keys and disagrees with eager collections for an empty key set | Track outstanding keys by identity, remove each once, and return vacuous truth before iteration |
+| `collections-03` | Defect | Major | High | `sum()` does not pass item keys to callbacks as Laravel's public behavior promises | Invoke the callback with value and key and correct its callable type |
+| `collections-04` | Improvement | Improvement | High | Hypervel lacks Laravel's `reduceInto()` API, tests, type inference, and documentation | Port the current contract and shared implementation plus focused tests, types, and both documentation indexes |
+| `collections-05` | Improvement | Improvement | High | `LazyCollection::random()` omits key preservation, while the shared contract cannot accurately describe the key type that both concrete implementations return when preservation is enabled | Add the optional argument and conditional key return to the contract and both implementations, with runtime and interface-level type coverage |
+| `collections-06` | Defect | Major | High | `Arr::last()`, `every()`, and `some()` advertise iterables but fail on Traversables; `first()` and the initial `last()` fix collapse duplicate iterator keys; and `push()` advertises an ArrayAccess mutation that cannot work or satisfy its array return | Retain native array fast paths, stream Traversables without losing occurrences, preserve reverse callback semantics for `last()`, and narrow only the impossible `push()` input to arrays with a focused source explanation |
+| `collections-07` | Improvement | Improvement | High | The deprecated `containsOneItem()` and `containsManyItems()` aliases remain after their replacements `hasSole()` and `hasMany()` are available | Remove aliases, stale tests, and public-guide entries; record the intentional omission in source/test markers and the package README |
+| `collections-08` | Defect | Major | High | The split package requires an unused PHP 8.6 polyfill but omits the PHP 8.5 polyfill that provides functions used on Hypervel's PHP 8.4 floor | Replace php86 with php85, add Laravel's VarDumper suggestion for opt-in dump methods, and normalize direct dependency order |
+| `collections-09` | Improvement | Improvement | High | Several public annotations and ArrayAccess parameter names are incomplete or wrong, including a default callable documented with an argument it never receives | Port only source-backed current annotations that improve Hypervel's public inference, correct two upstream-shared PHPDoc forms rejected by the installed PHPStan stack, fix named-argument compatibility, and add compact targeted type fixtures |
+| `collections-10` | Improvement | Improvement | High | One per-item lazy timing path uses Carbon's slow magic property and package-owned tests retain the wrong base class or missing required return types | Use the direct timestamp getter and bring the complete package test surface to repository standards |
+| `collections-11` | Defect | Minor | High | The concrete `sum()` annotation reports one callback result as the accumulated total, producing impossible literal return types for multi-item collections | Report `int\|float\|TReturnType` through both the implementation and `Enumerable` contract, and regress multi-item callback and selector inference |
+| `collections-12` | Defect | Major | High | `LazyCollection::combine()` and `zip()` advertise iterable inputs but their shared iterator builder rejects every plain `Iterator`, including generators, while its callable PHPDoc excludes a supported scalar-result fallback | Accept the complete explicit Iterator union at the shared builder, document iterable-returning callables precisely and arbitrary internal callable results conservatively, and regress both public callers with plain iterators and generators |
+| `collections-13` | Defect | Minor | High | `times()` without a callback always yields integers but reports an unresolved generic and infers `mixed` through the contract and both implementations | Use one variance-safe conditional return across all three declarations and regress omitted-callback and callback-result inference for eager and lazy collections |
+
+- **Important rejected concerns:** Do not add coroutine context, locks, scoped bindings, cloning, or cleanup around collection instances or lazy iterators; the package has no hidden request state or owned asynchronous lifecycle. Do not blanket-copy Laravel annotations or style-only rewrites, remove deliberate Hypervel behavior such as depth-aware dot flattening and subclass factory hooks, or claim that one mutable lazy iterator is safe for concurrent consumption. Keep array-native paths instead of materializing ordinary arrays merely to support Traversables.
+- **Cross-package implications:** None. The split manifest directly owns its corrected polyfill and optional dumper metadata. Later `support` and `testing` audits must retain the already-complete centralized macro/proxy resets but receive no new contract from this work.
+- **Approved implementation boundary:** Owner approved the additive Laravel APIs, the deprecated-alias removal, truthful `Arr::push()` narrowing, selective public type corrections, test improvements, and intentional-omission README. Owner separately approved extending `Enumerable::random()` with the optional key-preservation argument shared by both implementations, correcting its conditional key type instead of retaining Laravel's inaccurate interface annotation. Owner also approved correcting callback-based `sum()` inference through the shared contract: the result includes the integer identity, floating-point accumulation, and extension arithmetic objects instead of pretending the total is one callback result. Owner approved the measured correctness costs: approximately 3–4 nanoseconds per `sum()` item to forward keys and approximately 4 nanoseconds per ordinary `Arr::last()` call to preserve its iterable contract. Common `keyBy()` scalar work becomes slightly cheaper, array-native `every()`/`some()` paths remain, non-array materialization is confined to `last()` calls that actually receive a Traversable, and the timestamp path becomes faster. Documentation will additionally cover key-preserving random selection, keyed `sum()` callbacks, and iterable Arr helpers even where Laravel's guide is silent.
+- **Implementation:** Eager and lazy keying now normalize enum and stringable objects consistently; lazy key lookup tracks requested keys instead of counting yields; and keyed sums forward both callback arguments. The shared collection contract now includes `reduceInto()`, truthful key-preserving random results, numeric sum accumulation, and conditional integer results for callback-free `times()`. Arr keeps native array fast paths while correctly streaming Traversables for `first()`, `every()`, and `some()`; callback-free `last()` retains only the final value, while callback-based `last()` retains ordered key/value occurrences so it can preserve reverse callback order and short-circuiting without collapsing duplicate keys. The impossible ArrayAccess mutation was removed from `Arr::push()`. Lazy iterator normalization accepts both IteratorAggregate and plain Iterator sources, including generators, without changing scalar-returning callable runtime support. Deprecated aliases and their stale public docs/tests were removed with intentional-omission markers. Split-package metadata, named-argument parameter names, public annotations, test signatures, and user documentation now match the supported behavior.
+- **Regression tests:** Runtime coverage exercises backed-enum keying, duplicate and empty lazy key sets, keyed sums, mutable reduction, preserved random keys, every accepted Arr iterable shape and short-circuit rule, duplicate iterator keys, exact reverse `last()` callback order, ArrayAccess parameter names, and LazyCollection combine/zip with ArrayIterator and generators. Static fixtures cover Arr refinements; eager, lazy, and contract-level random/sum behavior; iterable-returning lazy factories; callback-free and callback-based `times()`; helper conditionals; and the new reduction API. Removal markers keep future parity work from silently restoring deprecated aliases.
+- **Performance and complexity:** Arrays retain their native PHP fast paths. `Arr::first()` improves Traversable behavior from full materialization to a short-circuiting scan; callback-free Traversable `last()` uses O(1) memory; only callback-based Traversable `last()` stores ordered pairs, which is required to preserve the array path's observable reverse callback and exception semantics. Lazy iterator normalization adds one `instanceof` only when constructing an iterator, not per item. The `times()` correction and other type/documentation changes execute no production code. The only measured hot-path costs are the owner-approved key forwarding in `sum()` and ordinary `Arr::last()` iterable guard; enum scalar work and lazy timing become cheaper. No lock, context state, registry, cache, compatibility layer, or speculative abstraction was added.
+- **Validation:** All affected Collections runtime tests, both real PHPStan configurations, strict split-package manifest validation, stale-reference sweeps, and `git diff --check` pass. The complete `composer fix` gate is green. Pre-implementation consensus, every focused unexpected-finding review, fresh self-review, final code-review sign-off, and owner pre-commit approval are complete.
+- **Assessment:** Collections remains a provider-free, lock-free value/iterator package. The changes correct verified parity, iterable, typing, metadata, and test-isolation defects at their existing boundaries, add only current general-purpose APIs with real upstream provenance, and avoid production lifecycle machinery the package does not need.
+
+### Shared finding `console-01`: preserve typed console contracts during Composer scripts
+
+- **Owner:** `console`, specifically the concrete application implementation of the typed `contracts` console boundary.
+- **Affected packages:** `console` and the completed `contracts` audit.
+- **Failure:** Composer can preload its bundled older Symfony Console `Application` before running Hypervel's post-autoload scripts. Its inherited `all()` and `run()` methods have no return types, so loading `Hypervel\Console\Application` fails when PHP checks them against Hypervel's accurately typed contract.
+- **Decision:** Keep the truthful contract and declare transparent typed `all()` and `run()` bridges on the concrete application. Do not change `addCommand()` or mark it with `#[Override]`, because Composer's older Symfony parent does not provide that method.
+- **Implementation and cleanup:** Added the two parent-delegating methods with a focused explanation of the non-obvious preload boundary. Added a deterministic legacy-parent fixture that reproduces Composer's relevant method surface without depending on an installed Composer version. Migrated every remaining raw Console PHPUnit test to the framework unit-test base so coroutine execution, Mockery verification, and framework teardown remain authoritative.
+- **Validation:** Reflection coverage pins both methods to the concrete class and their contract return types. An isolated subprocess loads the literal Hypervel class against the legacy parent shape, the exact installed Composer PHAR preload succeeds, focused console and corrected-base tests pass, and the complete `composer fix` gate is green. Fresh self-review and independent code-review sign-off are complete.
+- **Revalidation:** The strengthened console contract remains unchanged and valid. The later full `console` audit must retain this class-load boundary.
diff --git a/docs/plans/2026-07-12-framework-coroutine-state-lifecycle-audit.md b/docs/plans/2026-07-12-framework-coroutine-state-lifecycle-audit.md
index fc4c8f322..35ac90e68 100644
--- a/docs/plans/2026-07-12-framework-coroutine-state-lifecycle-audit.md
+++ b/docs/plans/2026-07-12-framework-coroutine-state-lifecycle-audit.md
@@ -857,11 +857,11 @@ A package checkbox means the entire cycle below is finished, not merely that fil
### Branch and authorization model
-This audit targets the repository's `0.4` integration branch. Each completed package or cross-package work unit uses a dedicated branch from the latest owner-approved `0.4` state and is reviewed as its own pull request. Name the branch for the work unit, such as `audit/contracts-coroutine-state-lifecycle`. Do not perform audit work directly on `0.4`.
+This audit targets the repository's `0.4` integration branch. Start an audit branch from the latest owner-approved `0.4` state and do not perform audit work directly on `0.4`. The owner decides pull-request boundaries: one audit branch may accumulate one or several completed packages or cross-package work units before the owner determines that it contains enough coherent work for a pull request.
-The owner has explicitly authorized coherent commits and pushes after each completed package or cross-package work unit for this audit. That authorization does not include opening, merging, or closing pull requests, and it does not automatically carry into a future audit run. Do not begin the next work unit until the preceding pull request has been integrated into `0.4` and the next branch includes that integrated state, unless the owner explicitly authorizes a stacked branch.
+The owner has explicitly authorized coherent commits after each completed package or cross-package work unit for this audit, following the owner pre-commit checkpoint below. Continue the next package on the same active audit branch after those commits unless the owner directs otherwise. Do not push, open, merge, or close a pull request until the owner explicitly requests it, and do not infer that a completed package should become its own pull request.
-A resumed session verifies the active branch, the last pushed package, and whether newer base-branch changes affect audited assumptions before editing. Never infer a different target branch from a hosting service's default branch.
+A resumed session verifies the active branch, the last completed package commits, and whether an owner-requested base update affects audited assumptions before editing. Never infer a different target branch from a hosting service's default branch.
### 1. Audit
@@ -936,7 +936,7 @@ Request an independent review of the complete diff and validation. Continue unti
### 9. Prepare final audit records
-Update the companion-ledger work-unit block with implemented changes, cross-package revalidation, tests/gates, and review sign-off. Its heading must match the pull-request title so the corresponding repository history is easy to locate without duplicating branch, pull-request, or commit references. Prepare the routing index, cross-package dependency index, and package-checklist changes in this plan. Remove wording that describes abandoned designs.
+Update the companion-ledger work-unit block with implemented changes, cross-package revalidation, tests/gates, and review sign-off. Give it a concise work-unit heading; multiple ledger work units may later be included in one owner-selected pull request. Prepare the routing index, cross-package dependency index, and package-checklist changes in this plan. Remove wording that describes abandoned designs and do not duplicate branch, pull-request, or commit references in the audit documents.
### 10. Owner pre-commit checkpoint
@@ -949,11 +949,11 @@ After every code change is complete, all gates are green, the fresh self-review
Do not create any source, test, documentation, ledger, or bookkeeping commit before that explicit approval. If the owner requests changes, implement them, rerun proportionate validation and review, update the summary, notify again, and wait for approval.
-### 11. Commit and push
+### 11. Commit
Commit source, tests, and documentation in as many coherent commits as useful, with detailed bodies. Make one final audit-bookkeeping commit containing the ledger entry and this plan's checklist/index updates. Do not duplicate branch, pull-request, commit, or merge references in the audit documents; repository history already owns that information. A clean audit with no executable or documentation correction has only this bookkeeping commit.
-Push the complete commit set only after the package is green and signed off. The checked box becomes authoritative when that push succeeds. If the push fails, do not begin the next package; repair the push or revert the unpushed completion bookkeeping so the branch does not claim externally completed work.
+The checked box becomes authoritative when the final bookkeeping commit succeeds. Continue on the same audit branch after the owner approves the next work unit. Push only when the owner requests it, normally when the owner decides the accumulated work is ready for a pull request.
## Cross-package work units
@@ -974,7 +974,7 @@ An exceptionally large shared work unit may receive its own linked detail plan w
This compact index routes the completed-work history that must be consulted with the full plan after compaction. Detailed history remains in the [companion ledger](2026-07-12-framework-coroutine-state-lifecycle-audit-ledger.md).
-- **Active package or work unit:** none; contracts work is complete and awaiting integration
+- **Active package or work unit:** `reflection`
- **Ledger entries required for the active work:** none
- **Pending revalidation carried into the active work:** none
@@ -990,6 +990,9 @@ Add one row only for a shared finding or changed lower-level assumption that ano
| `view-01` | `view` | `contracts`, `foundation`; later full `view` and `foundation` audits | `Harden framework contracts and request-scoped state`; shared finding `view-01` |
| `filesystem-01` | `filesystem` | `contracts`; later full `filesystem` audit | `Harden framework contracts and request-scoped state`; shared finding `filesystem-01` |
| `queue-01` | `queue` | `contracts`; later full `queue` audit | `Harden framework contracts and request-scoped state`; shared finding `queue-01` |
+| `testbench-01` | `testbench` | `foundation`; later full `testbench` and `foundation` audits | `Restore Conditionable proxy truthiness`; shared finding `testbench-01` |
+| `http-01` | `http` | `macroable`, `testing`; later full `http` and `testing` audits | `Complete Macroable callable and test-state handling`; shared finding `http-01` |
+| `console-01` | `console` | `contracts`; later full `console` audit | `Preserve typed console contracts during Composer scripts`; shared finding `console-01` |
## Package checklist
@@ -1013,9 +1016,9 @@ The order is lower-level first where practical. Hypervel has cross-cutting depen
### Core semantics and long-lived state
- [x] `contracts`
-- [ ] `conditionable`
-- [ ] `macroable`
-- [ ] `collections`
+- [x] `conditionable`
+- [x] `macroable`
+- [x] `collections`
- [ ] `reflection`
- [ ] `config`
- [ ] `container`
@@ -1106,7 +1109,7 @@ The order is lower-level first where practical. Hypervel has cross-cutting depen
### Before each package
-- confirm the previous work-unit pull request is integrated into `0.4`, then create the current work-unit branch from that latest integrated state unless the owner explicitly authorized stacking;
+- confirm the previous work unit is committed and the owner has authorized continuing on the active audit branch;
- set the active-package routing fields and list every exact ledger entry required for the work;
- read the current package's existing companion-ledger entry, if any, plus only the cross-referenced entries named by the routing/dependency indexes;
- check whether a completed lower-level package changed assumptions used here;
@@ -1128,7 +1131,7 @@ The order is lower-level first where practical. Hypervel has cross-cutting depen
- code review is signed off;
- every accepted hot-path regression, if any, received explicit owner approval before implementation;
- the owner reviewed the post-sign-off summary and explicitly approved committing;
-- commits were pushed;
+- the final bookkeeping commit succeeded;
- routing and dependency indexes reflect the next active work and every pending revalidation;
- any affected completed package was revalidated and its companion-ledger entry amended.
diff --git a/src/boost/docs/collections.md b/src/boost/docs/collections.md
index d375345b1..32be82c6e 100644
--- a/src/boost/docs/collections.md
+++ b/src/boost/docs/collections.md
@@ -64,7 +64,7 @@ $upper = $collection->toUpper();
Typically, you should declare collection macros in the `boot` method of a [service provider](/docs/{{version}}/providers).
-If you register a macro inside a test, flush the macro state before the test finishes. Macros are stored globally for the life of the PHP process.
+Macros are stored globally for the life of the PHP process. Hypervel automatically flushes framework-owned collection macros after every test. If your application or package defines its own macroable class, add it to your [test-state cleanup](/docs/{{version}}/testing#macro-state).
#### Macro Arguments
@@ -122,8 +122,6 @@ For the majority of the remaining collection documentation, we'll discuss each m
[combine](#method-combine)
[concat](#method-concat)
[contains](#method-contains)
-[containsManyItems](#method-containsmanyitems)
-[containsOneItem](#method-containsoneitem)
[containsStrict](#method-containsstrict)
[count](#method-count)
[countBy](#method-countBy)
@@ -209,6 +207,7 @@ For the majority of the remaining collection documentation, we'll discuss each m
[random](#method-random)
[range](#method-range)
[reduce](#method-reduce)
+[reduceInto](#method-reduce-into)
[reduceSpread](#method-reduce-spread)
[reduceWithKeys](#method-reduce-with-keys)
[reject](#method-reject)
@@ -605,68 +604,6 @@ The `contains` method uses "loose" comparisons when checking item values, meanin
For the inverse of `contains`, see the [doesntContain](#method-doesntcontain) method.
-
-#### `containsManyItems()` {.collection-method}
-
-The `containsManyItems` method determines whether the collection contains more than one item:
-
-```php
-collect([])->containsManyItems();
-
-// false
-
-collect(['first'])->containsManyItems();
-
-// false
-
-collect(['first', 'second'])->containsManyItems();
-
-// true
-```
-
-When using the `Collection` class, you may pass a closure to determine whether the collection contains more than one item matching a given truth test:
-
-```php
-$collection = collect(['ant', 'bear', 'cat', 'deer']);
-
-$collection->containsManyItems(function (string $value) {
- return strlen($value) === 4;
-});
-
-// true
-```
-
-
-#### `containsOneItem()` {.collection-method}
-
-The `containsOneItem` method determines whether the collection contains exactly one item:
-
-```php
-collect([])->containsOneItem();
-
-// false
-
-collect(['first'])->containsOneItem();
-
-// true
-
-collect(['first', 'second'])->containsOneItem();
-
-// false
-```
-
-You may pass a closure to determine whether the collection contains exactly one item matching a given truth test:
-
-```php
-$collection = collect(['ant', 'bear', 'cat']);
-
-$collection->containsOneItem(function (string $value) {
- return strlen($value) === 4;
-});
-
-// true
-```
-
#### `containsStrict()` {.collection-method}
@@ -2634,6 +2571,17 @@ $random->all();
// [2, 4, 5] - (retrieved randomly)
```
+Pass `true` as the second argument to preserve the original keys when retrieving multiple items:
+
+```php
+$random = collect(['desk' => 100, 'chair' => 50, 'lamp' => 25])
+ ->random(2, preserveKeys: true);
+
+$random->keys()->all();
+
+// ['desk', 'lamp'] - (retrieved randomly)
+```
+
If the collection instance has fewer items than requested, the `random` method will throw an `InvalidArgumentException`.
The `random` method also accepts a closure, which will receive the current collection instance:
@@ -2708,6 +2656,35 @@ $collection->reduce(function (int $carry, int $value, string $key) use ($ratio)
// 4264
```
+
+#### `reduceInto()` {.collection-method}
+
+The `reduceInto` method reduces the collection to a single value by mutating the given initial value. Unlike the `reduce` method, the given callback does not need to return the accumulated value:
+
+```php
+class OrderStats
+{
+ public int $total = 0;
+
+ public int $count = 0;
+}
+
+$orders = collect([
+ ['amount' => 100],
+ ['amount' => 250],
+ ['amount' => 50],
+]);
+
+$stats = $orders->reduceInto(new OrderStats, function (OrderStats $stats, array $order) {
+ $stats->total += $order['amount'];
+ $stats->count++;
+});
+
+$stats->total;
+
+// 400
+```
+
#### `reduceSpread()` {.collection-method}
@@ -3452,6 +3429,15 @@ $collection->sum(function (array $product) {
// 6
```
+The callback receives the item key as its second argument:
+
+```php
+$total = collect(['standard' => 100, 'priority' => 200])
+ ->sum(fn (int $price, string $type) => $type === 'priority' ? $price + 25 : $price);
+
+// 325
+```
+
#### `take()` {.collection-method}
@@ -4425,8 +4411,6 @@ Almost all methods available on the `Collection` class are also available on the
[combine](#method-combine)
[concat](#method-concat)
[contains](#method-contains)
-[containsManyItems](#method-containsmanyitems)
-[containsOneItem](#method-containsoneitem)
[containsStrict](#method-containsstrict)
[count](#method-count)
[countBy](#method-countBy)
@@ -4504,6 +4488,7 @@ Almost all methods available on the `Collection` class are also available on the
[random](#method-random)
[range](#method-range)
[reduce](#method-reduce)
+[reduceInto](#method-reduce-into)
[reduceSpread](#method-reduce-spread)
[reduceWithKeys](#method-reduce-with-keys)
[reject](#method-reject)
diff --git a/src/boost/docs/helpers.md b/src/boost/docs/helpers.md
index c02220017..6132a7ee2 100644
--- a/src/boost/docs/helpers.md
+++ b/src/boost/docs/helpers.md
@@ -402,7 +402,7 @@ $flattened = Arr::dot($array);
#### `Arr::every()` {.collection-method}
-The `Arr::every` method ensures that all values in the array pass a given truth test:
+The `Arr::every` method ensures that all values in an iterable pass a given truth test:
```php
use Hypervel\Support\Arr;
@@ -418,6 +418,20 @@ Arr::every($array, fn ($i) => $i > 2);
// false
```
+The method also accepts any iterable, including generators:
+
+```php
+$values = function () {
+ yield 1;
+ yield 2;
+ yield 3;
+};
+
+Arr::every($values(), fn (int $value) => $value > 0);
+
+// true
+```
+
#### `Arr::except()` {.collection-method}
@@ -482,7 +496,7 @@ $exists = Arr::exists($array, 'salary');
#### `Arr::first()` {.collection-method}
-The `Arr::first` method returns the first element of an array passing a given truth test:
+The `Arr::first` method returns the first element of an iterable passing a given truth test:
```php
use Hypervel\Support\Arr;
@@ -496,6 +510,8 @@ $first = Arr::first($array, function (int $value, int $key) {
// 200
```
+The first argument may be any iterable, including a generator.
+
A default value may also be passed as the third parameter to the method. This value will be returned if no value passes the truth test:
```php
@@ -754,7 +770,7 @@ $keyed = Arr::keyBy($array, 'product_id');
#### `Arr::last()` {.collection-method}
-The `Arr::last` method returns the last element of an array passing a given truth test:
+The `Arr::last` method returns the last element of an iterable passing a given truth test:
```php
use Hypervel\Support\Arr;
@@ -776,6 +792,8 @@ use Hypervel\Support\Arr;
$last = Arr::last($array, $callback, $default);
```
+The first argument may be any iterable, including a generator.
+
#### `Arr::map()` {.collection-method}
@@ -1164,7 +1182,7 @@ $value = Arr::sole($array, fn (string $value) => $value === 'Desk');
#### `Arr::some()` {.collection-method}
-The `Arr::some` method ensures that at least one of the values in the array passes a given truth test:
+The `Arr::some` method ensures that at least one of the values in an iterable passes a given truth test:
```php
use Hypervel\Support\Arr;
@@ -1176,6 +1194,8 @@ Arr::some($array, fn ($i) => $i > 2);
// true
```
+The first argument may be any iterable, including a generator.
+
#### `Arr::sort()` {.collection-method}
diff --git a/src/boost/docs/http-client.md b/src/boost/docs/http-client.md
index 66c7e962a..3385d09d4 100644
--- a/src/boost/docs/http-client.md
+++ b/src/boost/docs/http-client.md
@@ -893,7 +893,7 @@ Once your macro has been configured, you may invoke it from anywhere in your app
$response = Http::github()->get('/');
```
-Macros are stored globally for the life of the PHP process. If you register a macro inside a test, flush the macro state before the test finishes.
+Macros are stored globally for the life of the PHP process. Hypervel automatically flushes framework-owned HTTP client macros after every test. If your application or package defines its own macroable class, add it to your [test-state cleanup](/docs/{{version}}/testing#macro-state).
## Testing
diff --git a/src/boost/docs/responses.md b/src/boost/docs/responses.md
index 2b894bb00..b39d20199 100644
--- a/src/boost/docs/responses.md
+++ b/src/boost/docs/responses.md
@@ -1121,4 +1121,4 @@ return response()->caps('foo');
```
> [!NOTE]
-> Macros register on a static property and persist for the life of the Swoole worker. If you register a macro inside a test, call `Hypervel\Routing\ResponseFactory::flushState()` or `Response::flushMacros()` before the next test runs so the macro doesn't leak into other tests.
+> Macros register on a static property and persist for the life of the Swoole worker. Hypervel automatically flushes framework-owned response macros after every test. If your application or package defines its own macroable class, add it to your [test-state cleanup](/docs/{{version}}/testing#macro-state).
diff --git a/src/collections/README.md b/src/collections/README.md
new file mode 100644
index 000000000..a5d0b3370
--- /dev/null
+++ b/src/collections/README.md
@@ -0,0 +1,14 @@
+Collections for Hypervel
+===
+
+[](https://deepwiki.com/hypervel/collections)
+
+Ported from: https://github.com/laravel/framework/tree/13.x/src/Illuminate/Collections
+
+## Differences From Laravel
+
+Laravel's deprecated `containsOneItem()` and `containsManyItems()` aliases are intentionally not ported. Use `hasSole()` and `hasMany()` instead.
+
+`Enumerable::random()` exposes the optional `preserveKeys` argument supported by both concrete collection implementations and reports the preserved key type accurately. Laravel exposes this argument only on the concrete classes and always reports integer keys through the contract.
+
+`Arr::push()` accepts arrays only. Laravel also advertises `ArrayAccess`, but dot notation requires nested by-reference mutation that `ArrayAccess` cannot provide.
diff --git a/src/collections/composer.json b/src/collections/composer.json
index 4ee50c2b1..4f61b0bc6 100644
--- a/src/collections/composer.json
+++ b/src/collections/composer.json
@@ -35,12 +35,13 @@
"require": {
"php": "^8.4",
"hypervel/conditionable": "^0.4",
- "hypervel/macroable": "^0.4",
"hypervel/contracts": "^0.4",
- "symfony/polyfill-php86": "^1.36"
+ "hypervel/macroable": "^0.4",
+ "symfony/polyfill-php85": "^1.36"
},
"suggest": {
- "hypervel/http": "Required to convert collections to API resources (^0.4)."
+ "hypervel/http": "Required to convert collections to API resources (^0.4).",
+ "symfony/var-dumper": "Required to use the dump method (^7.4 || ^8.0)."
},
"config": {
"sort-packages": true
diff --git a/src/collections/src/Arr.php b/src/collections/src/Arr.php
index 7cdaaa011..0b503805a 100644
--- a/src/collections/src/Arr.php
+++ b/src/collections/src/Arr.php
@@ -31,6 +31,20 @@ public static function accessible(mixed $value): bool
/**
* Determine whether the given value is arrayable.
+ *
+ * @return ($value is array
+ * ? true
+ * : ($value is Arrayable
+ * ? true
+ * : ($value is Traversable
+ * ? true
+ * : ($value is Jsonable
+ * ? true
+ * : ($value is JsonSerializable ? true : false)
+ * )
+ * )
+ * )
+ * )
*/
public static function arrayable(mixed $value): bool
{
@@ -109,6 +123,11 @@ public static function collapse(iterable $array): array
/**
* Cross join the given arrays, returning all possible permutations.
+ *
+ * @template TValue
+ *
+ * @param iterable ...$arrays
+ * @return array>
*/
public static function crossJoin(iterable ...$arrays): array
{
@@ -133,6 +152,12 @@ public static function crossJoin(iterable ...$arrays): array
/**
* Divide an array into two arrays. One with keys and the other with values.
+ *
+ * @template TKey of array-key
+ * @template TValue
+ *
+ * @param array $array
+ * @return array{TKey[], TValue[]}
*/
public static function divide(array $array): array
{
@@ -252,7 +277,15 @@ public static function first(iterable $array, ?callable $callback = null, mixed
return value($default);
}
- $array = static::from($array);
+ if (! is_array($array)) {
+ foreach ($array as $key => $value) {
+ if ($callback($value, $key)) {
+ return $value;
+ }
+ }
+
+ return value($default);
+ }
$key = array_find_key($array, $callback);
@@ -260,7 +293,7 @@ public static function first(iterable $array, ?callable $callback = null, mixed
}
/**
- * Return the last element in an array passing a given truth test.
+ * Return the last element in an iterable passing a given truth test.
*
* @template TKey
* @template TValue
@@ -273,6 +306,37 @@ public static function first(iterable $array, ?callable $callback = null, mixed
*/
public static function last(iterable $array, ?callable $callback = null, mixed $default = null): mixed
{
+ if (! is_array($array)) {
+ if (is_null($callback)) {
+ $found = false;
+ $last = null;
+
+ foreach ($array as $value) {
+ $found = true;
+ $last = $value;
+ }
+
+ return $found ? $last : value($default);
+ }
+
+ // Preserve the array path's reverse callback order without collapsing duplicate iterator keys.
+ $items = [];
+
+ foreach ($array as $key => $value) {
+ $items[] = [$key, $value];
+ }
+
+ for ($index = count($items) - 1; $index >= 0; --$index) {
+ [$key, $value] = $items[$index];
+
+ if ($callback($value, $key)) {
+ return $value;
+ }
+ }
+
+ return value($default);
+ }
+
if (is_null($callback)) {
return empty($array) ? value($default) : array_last($array);
}
@@ -517,7 +581,17 @@ public static function hasAny(mixed $array, array|string|int|float|null $keys):
*/
public static function every(iterable $array, callable $callback): bool
{
- return array_all($array, $callback);
+ if (is_array($array)) {
+ return array_all($array, $callback);
+ }
+
+ foreach ($array as $key => $value) {
+ if (! $callback($value, $key)) {
+ return false;
+ }
+ }
+
+ return true;
}
/**
@@ -525,7 +599,17 @@ public static function every(iterable $array, callable $callback): bool
*/
public static function some(iterable $array, callable $callback): bool
{
- return array_any($array, $callback);
+ if (is_array($array)) {
+ return array_any($array, $callback);
+ }
+
+ foreach ($array as $key => $value) {
+ if ($callback($value, $key)) {
+ return true;
+ }
+ }
+
+ return false;
}
/**
@@ -550,6 +634,8 @@ public static function integer(ArrayAccess|array $array, string|int|null $key, ?
* Determines if an array is associative.
*
* An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
+ *
+ * @return ($array is list ? false : true)
*/
public static function isAssoc(array $array): bool
{
@@ -560,6 +646,8 @@ public static function isAssoc(array $array): bool
* Determines if an array is a list.
*
* An array is a "list" if all array keys are sequential integers starting from 0 with no gaps in between.
+ *
+ * @return ($array is list ? true : false)
*/
public static function isList(array $array): bool
{
@@ -797,6 +885,8 @@ public static function query(array $array): string
/**
* Get one or a specified number of random values from an array.
*
+ * @return ($number is null ? mixed : array)
+ *
* @throws InvalidArgumentException
*/
public static function random(array $array, int|string|null $number = null, bool $preserveKeys = false): mixed
@@ -881,8 +971,10 @@ public static function set(array &$array, string|int|float|null $key, mixed $val
/**
* Push an item into an array using "dot" notation.
+ *
+ * ArrayAccess cannot support the nested by-reference mutation required by dot notation.
*/
- public static function push(ArrayAccess|array &$array, string|int|null $key, mixed ...$values): array
+ public static function push(array &$array, string|int|null $key, mixed ...$values): array
{
$target = static::array($array, $key, []);
@@ -926,6 +1018,13 @@ public static function sole(array $array, ?callable $callback = null): mixed
/**
* Sort the array using the given callback or "dot" notation.
+ *
+ * @template TKey of array-key
+ * @template TValue
+ *
+ * @param iterable $array
+ * @param null|array|callable|int|string $callback
+ * @return array
*/
public static function sort(iterable $array, callable|array|int|string|null $callback = null): array
{
@@ -940,6 +1039,13 @@ public static function sort(iterable $array, callable|array|int|string|null $cal
/**
* Sort the array in descending order using the given callback or "dot" notation.
+ *
+ * @template TKey of array-key
+ * @template TValue
+ *
+ * @param iterable $array
+ * @param null|array|callable|int|string $callback
+ * @return array
*/
public static function sortDesc(iterable $array, callable|array|int|string|null $callback = null): array
{
@@ -954,6 +1060,13 @@ public static function sortDesc(iterable $array, callable|array|int|string|null
/**
* Recursively sort an array by keys and values.
+ *
+ * @template TKey of array-key
+ * @template TValue
+ *
+ * @param array $array
+ * @param int-mask-of $options
+ * @return array
*/
public static function sortRecursive(array $array, int $options = SORT_REGULAR, SortDirection|bool $descending = false): array
{
@@ -980,6 +1093,13 @@ public static function sortRecursive(array $array, int $options = SORT_REGULAR,
/**
* Recursively sort an array by keys and values in descending order.
+ *
+ * @template TKey of array-key
+ * @template TValue
+ *
+ * @param array $array
+ * @param int-mask-of $options
+ * @return array
*/
public static function sortRecursiveDesc(array $array, int $options = SORT_REGULAR): array
{
@@ -1006,6 +1126,9 @@ public static function string(ArrayAccess|array $array, string|int|null $key, ?s
/**
* Conditionally compile classes from an array into a CSS class list.
+ *
+ * @param array|array|string $array
+ * @return ($array is array ? '' : ($array is '' ? '' : ($array is array{} ? '' : non-empty-string)))
*/
public static function toCssClasses(array|string $array): string
{
@@ -1026,6 +1149,9 @@ public static function toCssClasses(array|string $array): string
/**
* Conditionally compile styles from an array into a style list.
+ *
+ * @param array|array|string $array
+ * @return ($array is array ? '' : ($array is '' ? '' : ($array is array{} ? '' : non-empty-string)))
*/
public static function toCssStyles(array|string $array): string
{
@@ -1046,6 +1172,13 @@ public static function toCssStyles(array|string $array): string
/**
* Filter the array using the given callback.
+ *
+ * @template TKey of array-key
+ * @template TValue
+ *
+ * @param array $array
+ * @param callable(TValue, TKey): bool $callback
+ * @return array
*/
public static function where(array $array, callable $callback): array
{
@@ -1054,6 +1187,13 @@ public static function where(array $array, callable $callback): array
/**
* Filter the array using the negation of the given callback.
+ *
+ * @template TKey of array-key
+ * @template TValue
+ *
+ * @param array $array
+ * @param callable(TValue, TKey): bool $callback
+ * @return array
*/
public static function reject(array $array, callable $callback): array
{
@@ -1088,6 +1228,12 @@ public static function partition(iterable $array, callable $callback): array
/**
* Filter items where the value is not null.
+ *
+ * @template TKey of array-key
+ * @template TValue
+ *
+ * @param array $array
+ * @return array
*/
public static function whereNotNull(array $array): array
{
@@ -1096,6 +1242,12 @@ public static function whereNotNull(array $array): array
/**
* If the given value is not an array and not null, wrap it in one.
+ *
+ * @template TKey of array-key = array-key
+ * @template TValue = mixed
+ *
+ * @param null|array|TValue $value
+ * @return ($value is null ? array{} : ($value is array ? array : array{TValue}))
*/
public static function wrap(mixed $value): array
{
diff --git a/src/collections/src/Collection.php b/src/collections/src/Collection.php
index 3995a381c..c75e3d87e 100644
--- a/src/collections/src/Collection.php
+++ b/src/collections/src/Collection.php
@@ -580,12 +580,10 @@ public function keyBy(callable|array|string $keyBy): static
foreach ($this->items as $key => $item) {
$resolvedKey = $keyBy($item, $key);
- if ($resolvedKey instanceof UnitEnum) {
- $resolvedKey = enum_value($resolvedKey);
- }
-
if (is_object($resolvedKey)) {
- $resolvedKey = (string) $resolvedKey;
+ $resolvedKey = $resolvedKey instanceof UnitEnum
+ ? enum_value($resolvedKey)
+ : (string) $resolvedKey;
}
$results[$resolvedKey] = $item;
@@ -711,25 +709,7 @@ public function isEmpty(): bool
return empty($this->items);
}
- /**
- * Determine if the collection contains exactly one item. If a callback is provided, determine if exactly one item matches the condition.
- *
- * @param null|(callable(TValue, TKey): bool) $callback
- */
- public function containsOneItem(?callable $callback = null): bool
- {
- return $this->hasSole($callback);
- }
-
- /**
- * Determine if the collection contains multiple items. If a callback is provided, determine if multiple items match the condition.
- *
- * @param null|(callable(TValue, TKey): bool) $callback
- */
- public function containsManyItems(?callable $callback = null): bool
- {
- return $this->hasMany($callback);
- }
+ // REMOVED: Laravel's deprecated containsOneItem() and containsManyItems(); use hasSole() and hasMany().
/**
* Join all items from the collection using a string. The final items can use a separate glue string.
@@ -921,6 +901,8 @@ public function union(mixed $items): static
/**
* Create a new collection consisting of every n-th element.
*
+ * @return ($step is positive-int ? static : never)
+ *
* @throws InvalidArgumentException
*/
public function nth(int $step, int $offset = 0): static
@@ -1108,7 +1090,7 @@ public function put(mixed $key, mixed $value): static
* Get one or a specified number of items randomly from the collection.
*
* @param null|(callable(self): int)|int|string $number
- * @return ($number is null ? TValue : static)
+ * @return ($number is null ? TValue : static<($preserveKeys is true ? TKey : int), TValue>)
*
* @throws InvalidArgumentException
*/
@@ -1323,7 +1305,7 @@ public function slice(int $offset, ?int $length = null): static
/**
* Split a collection into a certain number of groups.
*
- * @return static
+ * @return ($numberOfGroups is positive-int ? static : never)
*
* @throws InvalidArgumentException
*/
@@ -1365,7 +1347,7 @@ public function split(int $numberOfGroups): static
/**
* Split a collection into a certain number of groups, and fill the first groups completely.
*
- * @return static
+ * @return ($numberOfGroups is positive-int ? static : never)
*
* @throws InvalidArgumentException
*/
@@ -1880,47 +1862,47 @@ public function toBase(): Collection
/**
* Determine if an item exists at an offset.
*
- * @param TKey $key
+ * @param TKey $offset
*/
- public function offsetExists($key): bool
+ public function offsetExists($offset): bool
{
- return isset($this->items[$key]);
+ return isset($this->items[$offset]);
}
/**
* Get an item at a given offset.
*
- * @param TKey $key
+ * @param TKey $offset
* @return TValue
*/
- public function offsetGet($key): mixed
+ public function offsetGet($offset): mixed
{
- return $this->items[$key];
+ return $this->items[$offset];
}
/**
* Set the item at a given offset.
*
- * @param null|TKey $key
+ * @param null|TKey $offset
* @param TValue $value
*/
- public function offsetSet($key, $value): void
+ public function offsetSet($offset, $value): void
{
- if (is_null($key)) {
+ if (is_null($offset)) {
$this->items[] = $value;
} else {
- $this->items[$key] = $value;
+ $this->items[$offset] = $value;
}
}
/**
* Unset the item at a given offset.
*
- * @param TKey $key
+ * @param TKey $offset
*/
- public function offsetUnset($key): void
+ public function offsetUnset($offset): void
{
- unset($this->items[$key]);
+ unset($this->items[$offset]);
}
/**
diff --git a/src/collections/src/Enumerable.php b/src/collections/src/Enumerable.php
index e7e6a061f..7ccae30f5 100644
--- a/src/collections/src/Enumerable.php
+++ b/src/collections/src/Enumerable.php
@@ -40,11 +40,18 @@ public static function make(Arrayable|iterable|null $items = []): static;
/**
* Create a new instance by invoking the callback a given amount of times.
+ *
+ * @template TTimesValue
+ *
+ * @param null|(callable(int): TTimesValue) $callback
+ * @return ($callback is null ? static : static)
*/
public static function times(int $number, ?callable $callback = null): static;
/**
* Create a collection with the given range.
+ *
+ * @return static
*/
public static function range(int $from, int $to, int $step = 1): static;
@@ -70,6 +77,8 @@ public static function empty(): static;
/**
* Get all items in the enumerable.
+ *
+ * @return array
*/
public function all(): array;
@@ -395,6 +404,8 @@ public function firstWhere(callable|string $key, mixed $operator = null, mixed $
/**
* Get a flattened array of the items in the collection.
+ *
+ * @return static
*/
public function flatten(int|float $depth = INF);
@@ -503,15 +514,7 @@ public function isEmpty(): bool;
*/
public function isNotEmpty(): bool;
- /**
- * Determine if the collection contains a single item.
- */
- public function containsOneItem(): bool;
-
- /**
- * Determine if the collection contains multiple items.
- */
- public function containsManyItems(): bool;
+ // REMOVED: Laravel's deprecated containsOneItem() and containsManyItems(); use hasSole() and hasMany().
/**
* Determine if the collection contains a single item, optionally matching the given criteria.
@@ -669,14 +672,20 @@ public function union(mixed $items): static;
/**
* Get the min value of a given key.
*
- * @param null|(callable(TValue):mixed)|string $callback
+ * @template TMinResult = mixed
+ *
+ * @param null|(callable(TValue): TMinResult)|string $callback
+ * @return ($callback is callable ? ?TMinResult : ($callback is null ? ?TValue : mixed))
*/
public function min(callable|int|string|null $callback = null): mixed;
/**
* Get the max value of a given key.
*
- * @param null|(callable(TValue):mixed)|string $callback
+ * @template TMaxResult = mixed
+ *
+ * @param null|(callable(TValue): TMaxResult)|string $callback
+ * @return ($callback is callable ? ?TMaxResult : ($callback is null ? ?TValue : mixed))
*/
public function max(callable|int|string|null $callback = null): mixed;
@@ -719,11 +728,11 @@ public function concat(iterable $source): static;
/**
* Get one or a specified number of items randomly from the collection.
*
- * @return static|TValue
+ * @return ($number is null ? TValue : static<($preserveKeys is true ? TKey : int), TValue>)
*
* @throws InvalidArgumentException
*/
- public function random(callable|int|string|null $number = null): mixed;
+ public function random(callable|int|string|null $number = null, bool $preserveKeys = false): mixed;
/**
* Reduce the collection to a single value.
@@ -737,6 +746,17 @@ public function random(callable|int|string|null $number = null): mixed;
*/
public function reduce(callable $callback, mixed $initial = null): mixed;
+ /**
+ * Reduce the collection to a single value by mutating an initial value.
+ *
+ * @template TReduceIntoInitial
+ *
+ * @param TReduceIntoInitial $initial
+ * @param callable(TReduceIntoInitial, TValue, TKey): void $callback
+ * @return TReduceIntoInitial
+ */
+ public function reduceInto(mixed $initial, callable $callback): mixed;
+
/**
* Reduce the collection to multiple aggregate values.
*
@@ -882,6 +902,8 @@ public function sort(callable|int|null $callback = null): static;
/**
* Sort items in descending order.
+ *
+ * @param int-mask-of $options
*/
public function sortDesc(int $options = SORT_REGULAR): static;
@@ -889,6 +911,7 @@ public function sortDesc(int $options = SORT_REGULAR): static;
* Sort the collection using the given callback.
*
* @param array|(callable(TValue, TKey): mixed)|int|string $callback
+ * @param int-mask-of $options
*/
public function sortBy(array|callable|int|string $callback, int $options = SORT_REGULAR, SortDirection|bool $descending = false): static;
@@ -896,16 +919,21 @@ public function sortBy(array|callable|int|string $callback, int $options = SORT_
* Sort the collection in descending order using the given callback.
*
* @param array|(callable(TValue, TKey): mixed)|int|string $callback
+ * @param int-mask-of $options
*/
public function sortByDesc(array|callable|int|string $callback, int $options = SORT_REGULAR): static;
/**
* Sort the collection keys.
+ *
+ * @param int-mask-of $options
*/
public function sortKeys(int $options = SORT_REGULAR, SortDirection|bool $descending = false): static;
/**
* Sort the collection keys in descending order.
+ *
+ * @param int-mask-of $options
*/
public function sortKeysDesc(int $options = SORT_REGULAR): static;
@@ -919,7 +947,10 @@ public function sortKeysUsing(callable $callback): static;
/**
* Get the sum of the given values.
*
- * @param null|(callable(TValue): mixed)|string $callback
+ * @template TReturnType
+ *
+ * @param null|(callable(TValue, TKey): TReturnType)|string $callback
+ * @return ($callback is callable ? float|int|TReturnType : mixed)
*/
public function sum(callable|int|string|null $callback = null): mixed;
diff --git a/src/collections/src/LazyCollection.php b/src/collections/src/LazyCollection.php
index 259fe0103..865a36d9a 100644
--- a/src/collections/src/LazyCollection.php
+++ b/src/collections/src/LazyCollection.php
@@ -43,14 +43,16 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
/**
* The source from which to generate items.
*
- * @var array|(Closure(): Generator)|static
+ * @var array|(Closure(): iterable)|static
*/
public Closure|self|array $source;
/**
* Create a new lazy collection instance.
*
- * @param null|array|Arrayable|(Closure(): Generator)|iterable|self $source
+ * @param null|array|Arrayable|(Closure(): iterable)|iterable|self $source
+ *
+ * @throws InvalidArgumentException
*/
public function __construct(mixed $source = null)
{
@@ -70,10 +72,10 @@ public function __construct(mixed $source = null)
/**
* Create a new instance of the collection.
*
- * @template TNewKey of array-key
- * @template TNewValue
+ * @template TNewKey of array-key = int
+ * @template TNewValue = mixed
*
- * @param null|array|Arrayable|(Closure(): Generator)|iterable|self $items
+ * @param null|array|Arrayable|(Closure(): iterable)|iterable|self $items
* @return static
*/
protected function newInstance(mixed $items = []): static
@@ -84,10 +86,10 @@ protected function newInstance(mixed $items = []): static
/**
* Create a new collection instance if the value isn't one already.
*
- * @template TMakeKey of array-key
- * @template TMakeValue
+ * @template TMakeKey of array-key = int
+ * @template TMakeValue = mixed
*
- * @param null|array|Arrayable|(Closure(): Generator)|iterable|self $items
+ * @param null|array|Arrayable|(Closure(): iterable)|iterable|self $items
* @return static
*/
public static function make(mixed $items = [], mixed ...$args): static
@@ -98,11 +100,13 @@ public static function make(mixed $items = [], mixed ...$args): static
/**
* Create a collection with the given range.
*
- * @return static
+ * @return ($step is 0 ? never : static)
+ *
+ * @throws InvalidArgumentException
*/
public static function range(int $from, int $to, int $step = 1, mixed ...$args): static
{
- if ($step == 0) {
+ if ($step === 0) {
throw new InvalidArgumentException('Step value cannot be zero.');
}
@@ -125,7 +129,7 @@ public static function range(int $from, int $to, int $step = 1, mixed ...$args):
* @template TTimesValue
*
* @param null|(callable(int): TTimesValue) $callback
- * @return static
+ * @return ($callback is null ? static : static)
*/
public static function times(int|float $number, ?callable $callback = null, mixed ...$args): static
{
@@ -577,7 +581,9 @@ public function keyBy(callable|array|string $keyBy): static
$resolvedKey = $keyBy($item, $key);
if (is_object($resolvedKey)) {
- $resolvedKey = (string) $resolvedKey;
+ $resolvedKey = $resolvedKey instanceof UnitEnum
+ ? enum_value($resolvedKey)
+ : (string) $resolvedKey;
}
yield $resolvedKey => $item;
@@ -591,10 +597,15 @@ public function keyBy(callable|array|string $keyBy): static
public function has(mixed $key): bool
{
$keys = array_flip(is_array($key) ? $key : func_get_args());
- $count = count($keys);
+
+ if ($keys === []) {
+ return true;
+ }
foreach ($this as $key => $value) {
- if (array_key_exists($key, $keys) && --$count == 0) {
+ unset($keys[$key]);
+
+ if ($keys === []) {
return true;
}
}
@@ -666,21 +677,7 @@ public function isEmpty(): bool
return ! $this->getIterator()->valid();
}
- /**
- * Determine if the collection contains a single item.
- */
- public function containsOneItem(?callable $callback = null): bool
- {
- return $this->hasSole($callback);
- }
-
- /**
- * Determine if the collection contains multiple items.
- */
- public function containsManyItems(): bool
- {
- return $this->hasMany();
- }
+ // REMOVED: Laravel's deprecated containsOneItem() and containsManyItems(); use hasSole() and hasMany().
/**
* Join all items from the collection using a string. The final items can use a separate glue string.
@@ -828,9 +825,9 @@ public function multiply(int $multiplier): static
/**
* Create a collection by using this collection for keys and another for its values.
*
- * @template TCombineValue
+ * @template TCombineValue = mixed
*
- * @param Arrayable|(callable(): Generator)|iterable $values
+ * @param Arrayable|(callable(): iterable)|iterable $values
* @return static
* @phpstan-ignore generics.notSubtype (TValue becomes key - only valid when TValue is array-key, but can't express this constraint)
*/
@@ -872,6 +869,8 @@ public function union(mixed $items): static
/**
* Create a new collection consisting of every n-th element.
*
+ * @return ($step is positive-int ? static : never)
+ *
* @throws InvalidArgumentException
*/
public function nth(int $step, int $offset = 0): static
@@ -985,13 +984,13 @@ public function concat(iterable $source): static
/**
* Get one or a specified number of items randomly from the collection.
*
- * @return static|TValue
+ * @return ($number is null ? TValue : static<($preserveKeys is true ? TKey : int), TValue>)
*
* @throws InvalidArgumentException
*/
- public function random(callable|int|string|null $number = null): mixed
+ public function random(callable|int|string|null $number = null, bool $preserveKeys = false): mixed
{
- $result = $this->collect()->random(...func_get_args());
+ $result = $this->collect()->random($number, $preserveKeys);
return is_null($number) ? $result : $this->newInstance($result);
}
@@ -1359,7 +1358,7 @@ public function chunk(int $size, bool $preserveKeys = true): static
/**
* Split a collection into a certain number of groups, and fill the first groups completely.
*
- * @return static
+ * @return ($numberOfGroups is positive-int ? static : never)
*
* @throws InvalidArgumentException
*/
@@ -1768,10 +1767,10 @@ public function count(): int
* @template TIteratorKey of array-key
* @template TIteratorValue
*
- * @param array|(callable(): Generator)|IteratorAggregate $source
+ * @param array|(callable(): mixed)|Iterator|IteratorAggregate $source
* @return Iterator
*/
- protected function makeIterator(IteratorAggregate|array|callable $source): Iterator
+ protected function makeIterator(IteratorAggregate|Iterator|array|callable $source): Iterator
{
if ($source instanceof IteratorAggregate) {
$iterator = $source->getIterator();
@@ -1783,6 +1782,10 @@ protected function makeIterator(IteratorAggregate|array|callable $source): Itera
return new ArrayIterator($source);
}
+ if ($source instanceof Iterator) {
+ return $source;
+ }
+
// Only callable remains at this point
$maybeTraversable = $source();
@@ -1828,7 +1831,7 @@ protected function passthru(string $method, array $params): static
protected function now(): int
{
return class_exists(Carbon::class)
- ? Carbon::now()->timestamp
+ ? Carbon::now()->getTimestamp()
: time();
}
diff --git a/src/collections/src/Traits/EnumeratesValues.php b/src/collections/src/Traits/EnumeratesValues.php
index 760f7c303..ee1548d0b 100644
--- a/src/collections/src/Traits/EnumeratesValues.php
+++ b/src/collections/src/Traits/EnumeratesValues.php
@@ -170,7 +170,7 @@ public static function empty(mixed ...$args): static
* @template TTimesValue
*
* @param null|(callable(int): TTimesValue) $callback
- * @return static
+ * @return ($callback is null ? static : static)
*/
public static function times(int $number, ?callable $callback = null, mixed ...$args): static
{
@@ -465,7 +465,10 @@ public function mapInto(string $class)
/**
* Get the min value of a given key.
*
- * @param null|(callable(TValue):mixed)|string $callback
+ * @template TMinResult = mixed
+ *
+ * @param null|(callable(TValue): TMinResult)|string $callback
+ * @return ($callback is callable ? ?TMinResult : ($callback is null ? ?TValue : mixed))
*/
public function min(callable|int|string|null $callback = null): mixed
{
@@ -479,7 +482,10 @@ public function min(callable|int|string|null $callback = null): mixed
/**
* Get the max value of a given key.
*
- * @param null|(callable(TValue):mixed)|string $callback
+ * @template TMaxResult = mixed
+ *
+ * @param null|(callable(TValue): TMaxResult)|string $callback
+ * @return ($callback is callable ? ?TMaxResult : ($callback is null ? ?TValue : mixed))
*/
public function max(callable|int|string|null $callback = null): mixed
{
@@ -542,8 +548,8 @@ public function percentage(callable $callback, int $precision = 2): ?float
*
* @template TReturnType
*
- * @param null|(callable(TValue): TReturnType)|string $callback
- * @return ($callback is callable ? TReturnType : mixed)
+ * @param null|(callable(TValue, TKey): TReturnType)|string $callback
+ * @return ($callback is callable ? float|int|TReturnType : mixed)
*/
public function sum(callable|int|string|null $callback = null): mixed
{
@@ -551,7 +557,7 @@ public function sum(callable|int|string|null $callback = null): mixed
? $this->identity()
: $this->valueRetriever($callback);
- return $this->reduce(fn ($result, $item) => $result + $callback($item), 0);
+ return $this->reduce(fn ($result, $item, $key) => $result + $callback($item, $key), 0);
}
/**
@@ -769,7 +775,7 @@ public function pipeThrough(array $callbacks): mixed
*
* @param callable(TReduceInitial|TReduceReturnType, TValue, TKey): TReduceReturnType $callback
* @param TReduceInitial $initial
- * @return TReduceReturnType
+ * @return TReduceInitial|TReduceReturnType
*/
public function reduce(callable $callback, mixed $initial = null): mixed
{
@@ -782,6 +788,24 @@ public function reduce(callable $callback, mixed $initial = null): mixed
return $result;
}
+ /**
+ * Reduce the collection to a single value by mutating an initial value.
+ *
+ * @template TReduceIntoInitial
+ *
+ * @param TReduceIntoInitial $initial
+ * @param callable(TReduceIntoInitial, TValue, TKey): void $callback
+ * @return TReduceIntoInitial
+ */
+ public function reduceInto(mixed $initial, callable $callback): mixed
+ {
+ foreach ($this as $key => $value) {
+ $callback($initial, $value, $key);
+ }
+
+ return $initial;
+ }
+
/**
* Reduce the collection to multiple aggregate values.
*
@@ -814,7 +838,7 @@ class_basename(static::class),
*
* @param callable(TReduceWithKeysInitial|TReduceWithKeysReturnType, TValue, TKey): TReduceWithKeysReturnType $callback
* @param TReduceWithKeysInitial $initial
- * @return TReduceWithKeysReturnType
+ * @return TReduceWithKeysInitial|TReduceWithKeysReturnType
*/
public function reduceWithKeys(callable $callback, mixed $initial = null): mixed
{
diff --git a/src/collections/src/functions.php b/src/collections/src/functions.php
index 896c51af0..341c3a112 100644
--- a/src/collections/src/functions.php
+++ b/src/collections/src/functions.php
@@ -16,7 +16,7 @@
* @template TDefault
*
* @param TValue $value
- * @param callable(TValue): TDefault|TDefault $default
+ * @param (callable(): TDefault)|TDefault $default
* @return ($value is empty ? TDefault : mixed)
*/
function enum_value(mixed $value, mixed $default = null): mixed
diff --git a/src/collections/src/helpers.php b/src/collections/src/helpers.php
index 6bfcb5a57..6d1fc6c5e 100644
--- a/src/collections/src/helpers.php
+++ b/src/collections/src/helpers.php
@@ -258,7 +258,7 @@ function last($array)
* @template TValue
* @template TArgs
*
- * @param \Closure(TArgs): TValue|TValue $value
+ * @param (\Closure(TArgs): TValue)|TValue $value
* @param TArgs ...$args
* @return TValue
*/
@@ -272,10 +272,14 @@ function value($value, ...$args)
/**
* Return a value if the given condition is true.
*
+ * @template TValue
+ * @template TArgs
+ * @template TDefault
+ *
* @param mixed $condition
- * @param \Closure|mixed $value
- * @param \Closure|mixed $default
- * @return mixed
+ * @param (\Closure(TArgs): TValue)|TValue $value
+ * @param (\Closure(): TDefault)|TDefault $default
+ * @return ($condition is non-empty-array|non-falsy-string|positive-int|true ? TValue : ($condition is callable ? TDefault|TValue : TDefault))
*/
function when($condition, $value, $default = null)
{
diff --git a/src/conditionable/src/HigherOrderWhenProxy.php b/src/conditionable/src/HigherOrderWhenProxy.php
index 1fb3fa7c0..ba43176f6 100644
--- a/src/conditionable/src/HigherOrderWhenProxy.php
+++ b/src/conditionable/src/HigherOrderWhenProxy.php
@@ -32,9 +32,9 @@ public function __construct(
/**
* Set the condition on the proxy.
*/
- public function condition(bool $condition): static
+ public function condition(mixed $condition): static
{
- [$this->condition, $this->hasCondition] = [$condition, true];
+ [$this->condition, $this->hasCondition] = [(bool) $condition, true];
return $this;
}
diff --git a/src/console/src/Application.php b/src/console/src/Application.php
index 36e6da087..826280aaf 100644
--- a/src/console/src/Application.php
+++ b/src/console/src/Application.php
@@ -73,6 +73,28 @@ public function __construct(
$this->bootstrap();
}
+ // Composer can preload an older, untyped Symfony Console application before
+ // running Hypervel scripts. Keep these contract methods declared locally so
+ // their return types do not depend on the Symfony version already loaded.
+
+ /**
+ * Get all commands registered with the application.
+ */
+ #[Override]
+ public function all(?string $namespace = null): array
+ {
+ return parent::all($namespace);
+ }
+
+ /**
+ * Run the console application.
+ */
+ #[Override]
+ public function run(?InputInterface $input = null, ?OutputInterface $output = null): int
+ {
+ return parent::run($input, $output);
+ }
+
/**
* Determine the proper PHP executable.
*/
diff --git a/src/cookie/composer.json b/src/cookie/composer.json
index 29710e3be..087caf03c 100644
--- a/src/cookie/composer.json
+++ b/src/cookie/composer.json
@@ -34,6 +34,7 @@
"hypervel/context": "^0.4",
"hypervel/contracts": "^0.4",
"hypervel/http": "^0.4",
+ "hypervel/macroable": "^0.4",
"hypervel/support": "^0.4"
},
"config": {
@@ -49,4 +50,4 @@
"dev-main": "0.4-dev"
}
}
-}
\ No newline at end of file
+}
diff --git a/src/database/src/Eloquent/Factories/Factory.php b/src/database/src/Eloquent/Factories/Factory.php
index cec5fb487..aa5e55a23 100644
--- a/src/database/src/Eloquent/Factories/Factory.php
+++ b/src/database/src/Eloquent/Factories/Factory.php
@@ -997,6 +997,7 @@ public static function flushState(): void
static::$namespace = 'Database\Factories\\';
static::$expandRelationshipsByDefault = true;
static::$cachedModelAttributes = [];
+ static::flushMacros();
}
/**
diff --git a/src/http/src/Client/Factory.php b/src/http/src/Client/Factory.php
index c956c77d9..b464415bd 100644
--- a/src/http/src/Client/Factory.php
+++ b/src/http/src/Client/Factory.php
@@ -656,6 +656,14 @@ protected function validateConnectionConfig(array $config): void
ReservedOptions::reject($config, true, 'registered connection configuration');
}
+ /**
+ * Flush all static state.
+ */
+ public static function flushState(): void
+ {
+ static::flushMacros();
+ }
+
/**
* Execute a method against a new pending request instance.
*/
diff --git a/src/http/src/Client/PendingRequest.php b/src/http/src/Client/PendingRequest.php
index 6224668e4..7fd5f0dbf 100644
--- a/src/http/src/Client/PendingRequest.php
+++ b/src/http/src/Client/PendingRequest.php
@@ -1854,4 +1854,12 @@ protected function validateRequestOptions(array $options, string $source): void
{
ReservedOptions::reject($options, false, $source);
}
+
+ /**
+ * Flush all static state.
+ */
+ public static function flushState(): void
+ {
+ static::flushMacros();
+ }
}
diff --git a/src/http/src/Client/Response.php b/src/http/src/Client/Response.php
index 58774e19c..d298195e9 100644
--- a/src/http/src/Client/Response.php
+++ b/src/http/src/Client/Response.php
@@ -543,6 +543,7 @@ public function offsetUnset($offset): void
public static function flushState(): void
{
self::$defaultJsonDecodingFlags = 0;
+ static::flushMacros();
}
/**
diff --git a/src/http/src/JsonResponse.php b/src/http/src/JsonResponse.php
index cdb1064ea..33b527b1b 100755
--- a/src/http/src/JsonResponse.php
+++ b/src/http/src/JsonResponse.php
@@ -115,4 +115,12 @@ public function hasEncodingOption(int $option): bool
{
return (bool) ($this->encodingOptions & $option);
}
+
+ /**
+ * Flush all static state.
+ */
+ public static function flushState(): void
+ {
+ static::flushMacros();
+ }
}
diff --git a/src/http/src/RedirectResponse.php b/src/http/src/RedirectResponse.php
index e7f02df11..0ac07b90d 100755
--- a/src/http/src/RedirectResponse.php
+++ b/src/http/src/RedirectResponse.php
@@ -219,6 +219,14 @@ public function setSession(SessionStore $session): static
return $this;
}
+ /**
+ * Flush all static state.
+ */
+ public static function flushState(): void
+ {
+ static::flushMacros();
+ }
+
/**
* Dynamically bind flash data in the session.
*
diff --git a/src/http/src/Request.php b/src/http/src/Request.php
index 1e68c65bb..8953219f5 100644
--- a/src/http/src/Request.php
+++ b/src/http/src/Request.php
@@ -1180,6 +1180,20 @@ public function offsetUnset(mixed $offset): void
$this->getInputSource()->remove($offset);
}
+ /**
+ * Flush all static state.
+ */
+ public static function flushState(): void
+ {
+ static::$formats = null;
+ static::$httpMethodParameterOverride = false;
+ static::$allowedHttpMethodOverride = null;
+
+ // Symfony keeps the factory slot private, so reset it through the inherited setter.
+ static::setFactory(null);
+ static::flushMacros();
+ }
+
/**
* Check if an input element is set on the request.
*/
diff --git a/src/http/src/Resources/Json/JsonResource.php b/src/http/src/Resources/Json/JsonResource.php
index 0a05a58df..02109aa9d 100644
--- a/src/http/src/Resources/Json/JsonResource.php
+++ b/src/http/src/Resources/Json/JsonResource.php
@@ -271,5 +271,6 @@ public static function flushState(): void
{
static::$wrap = 'data';
static::$forceWrapping = false;
+ static::flushMacros();
}
}
diff --git a/src/http/src/Response.php b/src/http/src/Response.php
index d4a764fe5..f58c49f99 100755
--- a/src/http/src/Response.php
+++ b/src/http/src/Response.php
@@ -324,4 +324,12 @@ public function send(bool $flush = true): static
{
throw new RuntimeException('Response::send() is not supported in Hypervel. Responses are emitted through Swoole\'s response API.');
}
+
+ /**
+ * Flush all static state.
+ */
+ public static function flushState(): void
+ {
+ static::flushMacros();
+ }
}
diff --git a/src/http/src/UploadedFile.php b/src/http/src/UploadedFile.php
index cc932cb54..0997d7c59 100644
--- a/src/http/src/UploadedFile.php
+++ b/src/http/src/UploadedFile.php
@@ -129,4 +129,12 @@ protected function parseOptions(array|string $options): array
return $options;
}
+
+ /**
+ * Flush all static state.
+ */
+ public static function flushState(): void
+ {
+ static::flushMacros();
+ }
}
diff --git a/src/jwt/composer.json b/src/jwt/composer.json
index cdd636e43..59dbc7332 100644
--- a/src/jwt/composer.json
+++ b/src/jwt/composer.json
@@ -35,6 +35,7 @@
"hypervel/context": "^0.4",
"hypervel/contracts": "^0.4",
"hypervel/http": "^0.4",
+ "hypervel/macroable": "^0.4",
"hypervel/support": "^0.4"
},
"autoload": {
diff --git a/src/log/composer.json b/src/log/composer.json
index 8678888ab..5f5222286 100644
--- a/src/log/composer.json
+++ b/src/log/composer.json
@@ -36,9 +36,11 @@
"monolog/monolog": "^3.1",
"psr/log": "^3.0",
"hypervel/collections": "^0.4",
+ "hypervel/conditionable": "^0.4",
"hypervel/config": "^0.4",
"hypervel/context": "^0.4",
"hypervel/contracts": "^0.4",
+ "hypervel/macroable": "^0.4",
"hypervel/queue": "^0.4",
"hypervel/support": "^0.4"
},
diff --git a/src/macroable/src/Traits/Macroable.php b/src/macroable/src/Traits/Macroable.php
index c0c47a6a4..3a1736e1e 100644
--- a/src/macroable/src/Traits/Macroable.php
+++ b/src/macroable/src/Traits/Macroable.php
@@ -52,7 +52,7 @@ public static function mixin(object $mixin, bool $replace = true): void
}
/**
- * Checks if macro is registered.
+ * Check if macro is registered.
*/
public static function hasMacro(string $name): bool
{
@@ -88,7 +88,8 @@ public static function __callStatic(string $method, array $parameters): mixed
$macro = static::$macros[$method];
if ($macro instanceof Closure) {
- $macro = $macro->bindTo(null, static::class);
+ // PHP warns when a valid first-class callable cannot be rebound; retain the original callable.
+ $macro = @$macro->bindTo(null, static::class) ?? $macro;
}
return $macro(...$parameters);
@@ -112,7 +113,10 @@ public function __call(string $method, array $parameters): mixed
$macro = static::$macros[$method];
if ($macro instanceof Closure) {
- $macro = $macro->bindTo($this, static::class);
+ // PHP warns when a valid callable cannot use a binding form; select the first form it accepts.
+ $macro = @$macro->bindTo($this, static::class)
+ ?? @$macro->bindTo(null, static::class)
+ ?? $macro;
}
return $macro(...$parameters);
diff --git a/src/notifications/composer.json b/src/notifications/composer.json
index cc70b57ca..e70239382 100644
--- a/src/notifications/composer.json
+++ b/src/notifications/composer.json
@@ -44,6 +44,7 @@
"hypervel/contracts": "^0.4",
"hypervel/database": "^0.4",
"hypervel/filesystem": "^0.4",
+ "hypervel/macroable": "^0.4",
"hypervel/mail": "^0.4",
"hypervel/object-pool": "^0.4",
"hypervel/queue": "^0.4",
@@ -62,4 +63,4 @@
"dev-main": "0.4-dev"
}
}
-}
\ No newline at end of file
+}
diff --git a/src/support/src/Testing/Fakes/NotificationFake.php b/src/support/src/Testing/Fakes/NotificationFake.php
index a1326372d..814f3d1b4 100644
--- a/src/support/src/Testing/Fakes/NotificationFake.php
+++ b/src/support/src/Testing/Fakes/NotificationFake.php
@@ -334,4 +334,12 @@ public function sentNotifications(): array
{
return $this->notifications;
}
+
+ /**
+ * Flush all static state.
+ */
+ public static function flushState(): void
+ {
+ static::flushMacros();
+ }
}
diff --git a/src/testbench/src/TestCase.php b/src/testbench/src/TestCase.php
index 91a1c8715..a8fa5ce7b 100644
--- a/src/testbench/src/TestCase.php
+++ b/src/testbench/src/TestCase.php
@@ -6,11 +6,13 @@
use Hypervel\Coordinator\Constants;
use Hypervel\Coordinator\CoordinatorManager;
+use Hypervel\Filesystem\Filesystem;
use Hypervel\Foundation\Testing\DatabaseMigrations;
use Hypervel\Foundation\Testing\DatabaseTransactions;
use Hypervel\Foundation\Testing\RefreshDatabase;
use Hypervel\Foundation\Testing\TestCase as BaseTestCase;
use Hypervel\Testbench\Pest\WithPest;
+use RuntimeException;
use Swoole\Timer;
/**
@@ -70,6 +72,8 @@ protected function setUp(): void
parent::setUp();
+ $this->preservePackageManifestCache();
+
$this->baseUrl = config('app.url', 'http://localhost');
// Execute BeforeEach attributes INSIDE coroutine context
@@ -77,6 +81,35 @@ protected function setUp(): void
$this->runInCoroutine(fn () => $this->setUpTheTestEnvironmentUsingTestCase());
}
+ /**
+ * Preserve the package manifest cache for the duration of the test.
+ */
+ protected function preservePackageManifestCache(): void
+ {
+ $files = new Filesystem;
+ $path = $this->app->getCachedPackagesPath();
+ $existed = $files->isFile($path);
+ $contents = $existed ? $files->get($path) : '';
+
+ $this->beforeApplicationDestroyed(static function () use ($files, $path, $existed, $contents): void {
+ $exists = $files->isFile($path);
+
+ if (! $existed) {
+ if ($exists && ! $files->delete($path) && $files->isFile($path)) {
+ throw new RuntimeException("Unable to delete the test-owned package manifest cache [{$path}].");
+ }
+
+ return;
+ }
+
+ if ($exists && $files->get($path) === $contents) {
+ return;
+ }
+
+ $files->replace($path, $contents);
+ });
+ }
+
/**
* Set up database-related testing traits.
*
diff --git a/src/testing/src/PHPUnit/AfterEachTestSubscriber.php b/src/testing/src/PHPUnit/AfterEachTestSubscriber.php
index c0ce773a4..4f5d3730f 100644
--- a/src/testing/src/PHPUnit/AfterEachTestSubscriber.php
+++ b/src/testing/src/PHPUnit/AfterEachTestSubscriber.php
@@ -162,15 +162,22 @@ protected function flushFrameworkState(): void
\Hypervel\Foundation\Support\Providers\RouteServiceProvider::flushState();
\Hypervel\Foundation\Vite::flush();
\Hypervel\Foundation\WorkerCachedMaintenanceMode::flushCache();
+ \Hypervel\Http\Client\Factory::flushState();
+ \Hypervel\Http\Client\PendingRequest::flushState();
\Hypervel\Http\Client\Request::flushState();
\Hypervel\Http\Client\RequestException::flushState();
\Hypervel\Http\Client\Response::flushState();
\Hypervel\Http\Client\ResponseSequence::flushState();
+ \Hypervel\Http\JsonResponse::flushState();
\Hypervel\Http\Middleware\HandleCors::flushState();
\Hypervel\Http\Middleware\TrustHosts::flushState();
\Hypervel\Http\Middleware\TrustProxies::flushState();
+ \Hypervel\Http\RedirectResponse::flushState();
+ \Hypervel\Http\Request::flushState();
\Hypervel\Http\Resources\Json\JsonResource::flushState();
\Hypervel\Http\Resources\JsonApi\JsonApiResource::flushState();
+ \Hypervel\Http\Response::flushState();
+ \Hypervel\Http\UploadedFile::flushState();
\Hypervel\Jwt\ClaimFactory::flushState();
\Hypervel\Jwt\JwtGuard::flushState();
\Hypervel\Log\Context\Repository::flushState();
@@ -238,6 +245,7 @@ protected function flushFrameworkState(): void
\Hypervel\Support\Str::flushState();
\Hypervel\Support\StrCache::flushState();
\Hypervel\Support\Stringable::flushState();
+ \Hypervel\Support\Testing\Fakes\NotificationFake::flushState();
\Hypervel\Support\Uri::flushState();
\Hypervel\Testing\Fluent\AssertableJson::flushState();
\Hypervel\Testing\ParallelRunner::flushState();
diff --git a/tests/Conditionable/ConditionableTest.php b/tests/Conditionable/ConditionableTest.php
index 971c5cfc8..20026a827 100644
--- a/tests/Conditionable/ConditionableTest.php
+++ b/tests/Conditionable/ConditionableTest.php
@@ -27,7 +27,7 @@ protected function setUp(): void
$db->setAsGlobal();
}
- public function testWhen()
+ public function testWhen(): void
{
$this->assertInstanceOf(HigherOrderWhenProxy::class, TestConditionableModel::query()->when(true));
$this->assertInstanceOf(HigherOrderWhenProxy::class, TestConditionableModel::query()->when(false));
@@ -37,7 +37,7 @@ public function testWhen()
}));
}
- public function testUnless()
+ public function testUnless(): void
{
$this->assertInstanceOf(HigherOrderWhenProxy::class, TestConditionableModel::query()->unless(true));
$this->assertInstanceOf(HigherOrderWhenProxy::class, TestConditionableModel::query()->unless(false));
diff --git a/tests/Console/ConsoleApplicationCompatibilityTest.php b/tests/Console/ConsoleApplicationCompatibilityTest.php
new file mode 100644
index 000000000..407543aaf
--- /dev/null
+++ b/tests/Console/ConsoleApplicationCompatibilityTest.php
@@ -0,0 +1,49 @@
+assertSame(Application::class, $all->getDeclaringClass()->getName());
+ $this->assertSame('array', (string) $all->getReturnType());
+ $this->assertSame(Application::class, $run->getDeclaringClass()->getName());
+ $this->assertSame('int', (string) $run->getReturnType());
+ }
+
+ public function testApplicationLoadsWhenComposerPreloadsAnOlderSymfonyConsoleVersion(): void
+ {
+ $process = new PhpProcess(<<<'PHP'
+run();
+
+ $this->assertTrue(
+ $process->isSuccessful(),
+ $process->getErrorOutput() ?: $process->getOutput(),
+ );
+ }
+}
diff --git a/tests/Console/ContainerCommandLoaderTest.php b/tests/Console/ContainerCommandLoaderTest.php
index 4365e98df..176ba580a 100644
--- a/tests/Console/ContainerCommandLoaderTest.php
+++ b/tests/Console/ContainerCommandLoaderTest.php
@@ -6,7 +6,7 @@
use Hypervel\Console\ContainerCommandLoader;
use Hypervel\Contracts\Container\Container;
-use PHPUnit\Framework\TestCase;
+use Hypervel\Tests\TestCase;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\CommandNotFoundException;
diff --git a/tests/Console/Fixtures/LegacySymfonyApplication.php b/tests/Console/Fixtures/LegacySymfonyApplication.php
new file mode 100644
index 000000000..3b0d7044c
--- /dev/null
+++ b/tests/Console/Fixtures/LegacySymfonyApplication.php
@@ -0,0 +1,44 @@
+event = new Event(
m::mock(EventMutex::class),
'php foo'
diff --git a/tests/Integration/Foundation/Console/RouteCacheCommandTest.php b/tests/Integration/Foundation/Console/RouteCacheCommandTest.php
index b9d1696f9..0a21d4308 100644
--- a/tests/Integration/Foundation/Console/RouteCacheCommandTest.php
+++ b/tests/Integration/Foundation/Console/RouteCacheCommandTest.php
@@ -298,5 +298,32 @@ protected function assertCleanTestbenchRouteSources(): void
$routeFiles,
'Unexpected Testbench runtime route files found: ' . implode(', ', $routeFiles),
);
+
+ $manifestPath = $this->app->getCachedPackagesPath();
+
+ if ($this->files->isFile($manifestPath)) {
+ $manifest = $this->files->getRequire($manifestPath);
+
+ $this->assertIsArray(
+ $manifest,
+ "Testbench package manifest [{$manifestPath}] did not return an array.",
+ );
+
+ $providers = [];
+
+ foreach ($manifest as $configuration) {
+ if (is_array($configuration)) {
+ $providers = [...$providers, ...(array) ($configuration['providers'] ?? [])];
+ }
+ }
+
+ $providers = array_values(array_unique(array_filter($providers, is_string(...))));
+
+ $this->assertSame(
+ [],
+ $providers,
+ 'Unexpected Testbench package providers found: ' . implode(', ', $providers),
+ );
+ }
}
}
diff --git a/tests/Support/CollectionStaticStateTest.php b/tests/Support/CollectionStaticStateTest.php
index eade4267f..9bd99a3e4 100644
--- a/tests/Support/CollectionStaticStateTest.php
+++ b/tests/Support/CollectionStaticStateTest.php
@@ -13,7 +13,7 @@
class CollectionStaticStateTest extends TestCase
{
#[DataProvider('collectionClassProvider')]
- public function testFlushStateClearsMacrosAndProxies(string $collection)
+ public function testFlushStateClearsMacrosAndProxies(string $collection): void
{
$collection::macro('adults', function (callable $callback) {
return $this->filter(fn (array $item): bool => $callback($item) >= 18);
diff --git a/tests/Support/CollectionTest.php b/tests/Support/CollectionTest.php
index fb0ba4b9a..5dd71be77 100644
--- a/tests/Support/CollectionTest.php
+++ b/tests/Support/CollectionTest.php
@@ -5,7 +5,7 @@
namespace Hypervel\Tests\Support;
use Hypervel\Support\Collection;
-use PHPUnit\Framework\TestCase;
+use Hypervel\Tests\TestCase;
use Stringable;
class CollectionTest extends TestCase
diff --git a/tests/Support/HigherOrderProxyTest.php b/tests/Support/HigherOrderProxyTest.php
index 5bf6b899c..4ddcfd11b 100644
--- a/tests/Support/HigherOrderProxyTest.php
+++ b/tests/Support/HigherOrderProxyTest.php
@@ -11,7 +11,7 @@
class HigherOrderProxyTest extends TestCase
{
- public function testGetProxiesPropertyAccessToItems()
+ public function testGetProxiesPropertyAccessToItems(): void
{
$items = new Collection([
(object) ['name' => 'Alice'],
@@ -25,7 +25,7 @@ public function testGetProxiesPropertyAccessToItems()
$this->assertEquals(['Alice', 'Bob'], $proxy->name->all());
}
- public function testCallProxiesMethodCallToItems()
+ public function testCallProxiesMethodCallToItems(): void
{
$items = new Collection([
new class {
@@ -49,7 +49,7 @@ public function shout($s)
$this->assertEquals(['HEY', 'HEY!'], $result->all());
}
- public function testCallForwardsAndReturnsTarget()
+ public function testCallForwardsAndReturnsTarget(): void
{
$target = new class {
public $count = 0;
diff --git a/tests/Support/SupportArrTest.php b/tests/Support/SupportArrTest.php
index dbda395ba..84dfd14f1 100644
--- a/tests/Support/SupportArrTest.php
+++ b/tests/Support/SupportArrTest.php
@@ -14,6 +14,8 @@
use Hypervel\Tests\TestCase;
use InvalidArgumentException;
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
+use ReflectionMethod;
+use RuntimeException;
use SortDirection;
use stdClass;
use WeakMap;
@@ -60,7 +62,7 @@ public function testArrayable(): void
$this->assertFalse(Arr::arrayable(static fn () => null));
}
- public function testAdd()
+ public function testAdd(): void
{
$array = Arr::add(['name' => 'Desk'], 'price', 100);
$this->assertEquals(['name' => 'Desk', 'price' => 100], $array);
@@ -75,7 +77,7 @@ public function testAdd()
$this->assertEquals(['category' => ['type' => 'Table']], Arr::add(['category' => ['type' => 'Table']], 'category.type', 'Chair'));
}
- public function testPush()
+ public function testPush(): void
{
$array = [];
@@ -100,7 +102,15 @@ public function testPush()
Arr::push($array, 'foo.bar', 'baz');
}
- public function testCollapse()
+ public function testPushTruthfullyDeclaresItsArrayOnlyMutationBoundary(): void
+ {
+ // Laravel declares ArrayAccess here, but dot notation requires nested array references.
+ $parameter = (new ReflectionMethod(Arr::class, 'push'))->getParameters()[0];
+
+ $this->assertSame('array', (string) $parameter->getType());
+ }
+
+ public function testCollapse(): void
{
// Normal case: a two-dimensional array with different elements
$data = [['foo', 'bar'], ['baz']];
@@ -124,7 +134,7 @@ public function testCollapse()
$this->assertEquals([1, 2, 3, 'foo', 'bar', 'baz', 'boom'], Arr::collapse($mixedArray));
}
- public function testCrossJoin()
+ public function testCrossJoin(): void
{
// Single dimension
$this->assertSame(
@@ -213,7 +223,7 @@ public function testDivide(): void
$this->assertEquals([['one' => 1, 2 => 'second'], 'one'], $values);
}
- public function testDot()
+ public function testDot(): void
{
$array = Arr::dot(['foo' => ['bar' => 'baz']]);
$this->assertSame(['foo.bar' => 'baz'], $array);
@@ -297,7 +307,7 @@ public function testDotWithDepth(): void
$this->assertSame(['prefix.user.name' => 'Taylor'], $array);
}
- public function testUndot()
+ public function testUndot(): void
{
$array = Arr::undot([
'user.name' => 'Taylor',
@@ -321,7 +331,7 @@ public function testUndot()
$this->assertEquals(['foo', 'foo' => ['bar' => 'baz', 'baz' => ['a' => 'b']]], $array);
}
- public function testExcept()
+ public function testExcept(): void
{
$array = ['name' => 'taylor', 'age' => 26];
$this->assertEquals(['age' => 26], Arr::except($array, ['name']));
@@ -337,7 +347,7 @@ public function testExcept()
$this->assertEquals([1 => 'hAz', 2 => [12 => 'baz']], Arr::except($array, 2.5));
}
- public function testExceptValues()
+ public function testExceptValues(): void
{
$array = ['name' => 'taylor', 'age' => 26, 'city' => 'austin'];
$this->assertEquals(['name' => 'taylor', 'city' => 'austin'], Arr::exceptValues($array, [26]));
@@ -365,7 +375,7 @@ public function testExceptValues()
$this->assertEquals([], Arr::exceptValues($array, [1, 0]));
}
- public function testExists()
+ public function testExists(): void
{
$this->assertTrue(Arr::exists([1], 0));
$this->assertTrue(Arr::exists([null], 0));
@@ -397,7 +407,7 @@ public function testWhereNotNull(): void
$this->assertEquals([1, 'string', 0.0, false, [], $class, $function], $array);
}
- public function testFirst()
+ public function testFirst(): void
{
$array = [100, 200, 300];
@@ -445,7 +455,7 @@ public function testFirst()
$this->assertNull(Arr::first($cursor));
}
- public function testFirstWorksWithArrayObject()
+ public function testFirstWorksWithArrayObject(): void
{
$arrayObject = new ArrayObject([0, 10, 20]);
@@ -454,7 +464,26 @@ public function testFirstWorksWithArrayObject()
$this->assertSame(0, $result);
}
- public function testJoin()
+ public function testFirstPreservesDuplicateIteratorKeysAndStopsAtTheFirstMatch(): void
+ {
+ $values = static function (): iterable {
+ yield 'duplicate' => 1;
+ yield 'other' => 2;
+ yield 'duplicate' => 3;
+ };
+
+ $this->assertSame(1, Arr::first($values(), static fn (int $value): bool => $value === 1));
+
+ $shortCircuit = static function (): iterable {
+ yield 'first' => 1;
+
+ throw new RuntimeException('The iterator should not advance beyond the first match.');
+ };
+
+ $this->assertSame(1, Arr::first($shortCircuit(), static fn (int $value): bool => $value === 1));
+ }
+
+ public function testJoin(): void
{
$this->assertSame('a, b, c', Arr::join(['a', 'b', 'c'], ', '));
@@ -467,7 +496,7 @@ public function testJoin()
$this->assertSame('', Arr::join([], ', ', ' and '));
}
- public function testLast()
+ public function testLast(): void
{
$array = [100, 200, 300];
@@ -508,7 +537,52 @@ public function testLast()
$this->assertEquals(200, $value5);
}
- public function testFlatten()
+ public function testLastAcceptsTraversableValuesWithAndWithoutACallback(): void
+ {
+ $values = static function (): iterable {
+ yield 'first' => 100;
+ yield 'second' => 200;
+ yield 'third' => 300;
+ };
+
+ $this->assertSame(300, Arr::last($values()));
+ $this->assertSame(200, Arr::last(
+ $values(),
+ static fn (int $value, string $key): bool => $value < 250 && $key !== 'first',
+ ));
+ $this->assertSame('fallback', Arr::last(
+ new ArrayObject,
+ static fn (): bool => true,
+ 'fallback',
+ ));
+ }
+
+ public function testLastPreservesDuplicateIteratorKeysAndReverseCallbackOrder(): void
+ {
+ $values = static function (): iterable {
+ yield 'duplicate' => 1;
+ yield 'other' => 2;
+ yield 'duplicate' => 3;
+ };
+
+ $this->assertSame(3, Arr::last($values()));
+
+ $visited = [];
+
+ $result = Arr::last($values(), static function (int $value, string $key) use (&$visited): bool {
+ $visited[] = [$key, $value];
+
+ return $value === 2;
+ });
+
+ $this->assertSame(2, $result);
+ $this->assertSame([
+ ['duplicate', 3],
+ ['other', 2],
+ ], $visited);
+ }
+
+ public function testFlatten(): void
{
// Flat arrays are unaffected
$array = ['#foo', '#bar', '#baz'];
@@ -547,7 +621,7 @@ public function testFlatten()
$this->assertEquals(['#foo', '#bar', '#zap', '#baz'], Arr::flatten($array));
}
- public function testFlattenWithDepth()
+ public function testFlattenWithDepth(): void
{
// No depth flattens recursively
$array = [['#foo', ['#bar', ['#baz']]], '#zap'];
@@ -561,7 +635,7 @@ public function testFlattenWithDepth()
$this->assertEquals(['#foo', '#bar', ['#baz'], '#zap'], Arr::flatten($array, 2));
}
- public function testGet()
+ public function testGet(): void
{
$array = ['products.desk' => ['price' => 100]];
$this->assertEquals(['price' => 100], Arr::get($array, 'products.desk'));
@@ -649,7 +723,7 @@ public function testGet()
$this->assertSame('bar', Arr::get(['' => ['' => 'bar']], '.'));
}
- public function testItGetsAString()
+ public function testItGetsAString(): void
{
$test_array = ['string' => 'foo bar', 'integer' => 1234];
@@ -671,7 +745,7 @@ public function testItGetsAString()
Arr::string($test_array, 'integer');
}
- public function testItGetsAnInteger()
+ public function testItGetsAnInteger(): void
{
$test_array = ['string' => 'foo bar', 'integer' => 1234];
@@ -693,7 +767,7 @@ public function testItGetsAnInteger()
Arr::integer($test_array, 'string');
}
- public function testItGetsAFloat()
+ public function testItGetsAFloat(): void
{
$test_array = ['string' => 'foo bar', 'float' => 12.34];
@@ -715,7 +789,7 @@ public function testItGetsAFloat()
Arr::float($test_array, 'string');
}
- public function testItGetsABoolean()
+ public function testItGetsABoolean(): void
{
$test_array = ['string' => 'foo bar', 'boolean' => true];
@@ -737,7 +811,7 @@ public function testItGetsABoolean()
Arr::boolean($test_array, 'string');
}
- public function testItGetsAnArray()
+ public function testItGetsAnArray(): void
{
$test_array = ['string' => 'foo bar', 'array' => ['foo', 'bar']];
@@ -759,7 +833,7 @@ public function testItGetsAnArray()
Arr::array($test_array, 'string');
}
- public function testHas()
+ public function testHas(): void
{
$array = ['products.desk' => ['price' => 100]];
$this->assertTrue(Arr::has($array, 'products.desk'));
@@ -822,7 +896,7 @@ public function testHas()
$this->assertFalse(Arr::has([], ['']));
}
- public function testHasAllMethod()
+ public function testHasAllMethod(): void
{
$array = ['name' => 'Taylor', 'age' => '', 'city' => null];
$this->assertTrue(Arr::hasAll($array, 'name'));
@@ -845,7 +919,7 @@ public function testHasAllMethod()
$this->assertFalse(Arr::hasAll($array, ['foo', 'bar', 'baz', 'bar']));
}
- public function testHasAnyMethod()
+ public function testHasAnyMethod(): void
{
$array = ['name' => 'Taylor', 'age' => '', 'city' => null];
$this->assertTrue(Arr::hasAny($array, 'name'));
@@ -867,21 +941,57 @@ public function testHasAnyMethod()
$this->assertTrue(Arr::hasAny($array, ['foo.bax', 'foo.baz']));
}
- public function testEvery()
+ public function testEvery(): void
{
$this->assertFalse(Arr::every([1, 2], fn ($value, $key) => is_string($value)));
$this->assertFalse(Arr::every(['foo', 2], fn ($value, $key) => is_string($value)));
$this->assertTrue(Arr::every(['foo', 'bar'], fn ($value, $key) => is_string($value)));
}
- public function testSome()
+ public function testEveryAcceptsTraversableValuesAndStopsAtTheFirstFailure(): void
+ {
+ $visited = [];
+ $values = static function (): iterable {
+ yield 'first' => 1;
+ yield 'second' => 2;
+ yield 'third' => 3;
+ };
+
+ $this->assertFalse(Arr::every($values(), function (int $value, string $key) use (&$visited): bool {
+ $visited[] = $key;
+
+ return $value < 2;
+ }));
+ $this->assertSame(['first', 'second'], $visited);
+ $this->assertTrue(Arr::every(new ArrayObject(['first' => 1, 'second' => 2]), static fn (int $value): bool => $value > 0));
+ }
+
+ public function testSome(): void
{
$this->assertFalse(Arr::some([1, 2], fn ($value, $key) => is_string($value)));
$this->assertTrue(Arr::some(['foo', 2], fn ($value, $key) => is_string($value)));
$this->assertTrue(Arr::some(['foo', 'bar'], fn ($value, $key) => is_string($value)));
}
- public function testIsAssoc()
+ public function testSomeAcceptsTraversableValuesAndStopsAtTheFirstMatch(): void
+ {
+ $visited = [];
+ $values = static function (): iterable {
+ yield 'first' => 1;
+ yield 'second' => 2;
+ yield 'third' => 3;
+ };
+
+ $this->assertTrue(Arr::some($values(), function (int $value, string $key) use (&$visited): bool {
+ $visited[] = $key;
+
+ return $value === 2;
+ }));
+ $this->assertSame(['first', 'second'], $visited);
+ $this->assertFalse(Arr::some(new ArrayObject(['first' => 1, 'second' => 2]), static fn (int $value): bool => $value > 2));
+ }
+
+ public function testIsAssoc(): void
{
$this->assertTrue(Arr::isAssoc(['a' => 'a', 0 => 'b']));
$this->assertTrue(Arr::isAssoc([1 => 'a', 0 => 'b']));
@@ -900,7 +1010,7 @@ public function testIsAssoc()
$this->assertTrue(Arr::isAssoc(['foo' => 'bar', 'baz' => 'qux']));
}
- public function testIsList()
+ public function testIsList(): void
{
$this->assertTrue(Arr::isList([]));
$this->assertTrue(Arr::isList([1, 2, 3]));
@@ -918,7 +1028,7 @@ public function testIsList()
$this->assertFalse(Arr::isList(['foo' => 'bar', 'baz' => 'qux']));
}
- public function testOnly()
+ public function testOnly(): void
{
$array = ['name' => 'Desk', 'price' => 100, 'orders' => 10];
$array = Arr::only($array, ['name', 'price']);
@@ -937,7 +1047,7 @@ public function testOnly()
$this->assertEquals(['bar' => 'baz'], Arr::only(['foo', 'bar' => 'baz'], 'bar'));
}
- public function testOnlyValues()
+ public function testOnlyValues(): void
{
$array = ['name' => 'taylor', 'age' => 26, 'city' => 'austin'];
$this->assertEquals(['age' => 26], Arr::onlyValues($array, [26]));
@@ -965,7 +1075,7 @@ public function testOnlyValues()
$this->assertEquals(['a' => true, 'b' => false, 'c' => 1, 'd' => 0], Arr::onlyValues($array, [1, 0]));
}
- public function testPluck()
+ public function testPluck(): void
{
$data = [
'post-1' => [
@@ -1011,7 +1121,7 @@ public function testPluck()
$this->assertEquals(['Taylor', 'Abigail'], $array);
}
- public function testPluckWithArrayValue()
+ public function testPluckWithArrayValue(): void
{
$array = [
['developer' => ['name' => 'Taylor']],
@@ -1021,7 +1131,7 @@ public function testPluckWithArrayValue()
$this->assertEquals(['Taylor', 'Abigail'], $array);
}
- public function testPluckWithKeys()
+ public function testPluckWithKeys(): void
{
$array = [
['name' => 'Taylor', 'role' => 'developer'],
@@ -1042,7 +1152,7 @@ public function testPluckWithKeys()
], $test2);
}
- public function testPluckWithCarbonKeys()
+ public function testPluckWithCarbonKeys(): void
{
$array = [
['start' => new Carbon('2017-07-25 00:00:00'), 'end' => new Carbon('2017-07-30 00:00:00')],
@@ -1051,14 +1161,14 @@ public function testPluckWithCarbonKeys()
$this->assertEquals(['2017-07-25 00:00:00' => '2017-07-30 00:00:00'], $array);
}
- public function testArrayPluckWithArrayAndObjectValues()
+ public function testArrayPluckWithArrayAndObjectValues(): void
{
$array = [(object) ['name' => 'taylor', 'email' => 'foo'], ['name' => 'dayle', 'email' => 'bar']];
$this->assertEquals(['taylor', 'dayle'], Arr::pluck($array, 'name'));
$this->assertEquals(['taylor' => 'foo', 'dayle' => 'bar'], Arr::pluck($array, 'email', 'name'));
}
- public function testArrayPluckWithNestedKeys()
+ public function testArrayPluckWithNestedKeys(): void
{
$array = [['user' => ['taylor', 'otwell']], ['user' => ['dayle', 'rees']]];
$this->assertEquals(['taylor', 'dayle'], Arr::pluck($array, 'user.0'));
@@ -1067,7 +1177,7 @@ public function testArrayPluckWithNestedKeys()
$this->assertEquals(['taylor' => 'otwell', 'dayle' => 'rees'], Arr::pluck($array, ['user', 1], ['user', 0]));
}
- public function testArrayPluckWithNestedArrays()
+ public function testArrayPluckWithNestedArrays(): void
{
$array = [
[
@@ -1090,7 +1200,7 @@ public function testArrayPluckWithNestedArrays()
$this->assertEquals([['taylorotwell@gmail.com'], [null, null]], Arr::pluck($array, 'users.*.email'));
}
- public function testMap()
+ public function testMap(): void
{
$data = ['first' => 'taylor', 'last' => 'otwell'];
$mapped = Arr::map($data, function ($value, $key) {
@@ -1100,7 +1210,7 @@ public function testMap()
$this->assertEquals(['first' => 'taylor', 'last' => 'otwell'], $data);
}
- public function testMapWithEmptyArray()
+ public function testMapWithEmptyArray(): void
{
$mapped = Arr::map([], static function ($value, $key) {
return $key . '-' . $value;
@@ -1108,7 +1218,7 @@ public function testMapWithEmptyArray()
$this->assertEquals([], $mapped);
}
- public function testMapNullValues()
+ public function testMapNullValues(): void
{
$data = ['first' => 'taylor', 'last' => null];
$mapped = Arr::map($data, static function ($value, $key) {
@@ -1117,7 +1227,7 @@ public function testMapNullValues()
$this->assertEquals(['first' => 'first-taylor', 'last' => 'last-'], $mapped);
}
- public function testMapWithKeys()
+ public function testMapWithKeys(): void
{
$data = [
['name' => 'Blastoise', 'type' => 'Water', 'idx' => 9],
@@ -1135,7 +1245,7 @@ public function testMapWithKeys()
);
}
- public function testMapByReference()
+ public function testMapByReference(): void
{
$data = ['first' => 'taylor', 'last' => 'otwell'];
$mapped = Arr::map($data, 'strrev');
@@ -1144,7 +1254,7 @@ public function testMapByReference()
$this->assertEquals(['first' => 'taylor', 'last' => 'otwell'], $data);
}
- public function testMapSpread()
+ public function testMapSpread(): void
{
$c = [[1, 'a'], [2, 'b']];
@@ -1160,7 +1270,7 @@ public function testMapSpread()
}
#[IgnoreDeprecations]
- public function testPrepend()
+ public function testPrepend(): void
{
$array = Arr::prepend(['one', 'two', 'three', 'four'], 'zero');
$this->assertEquals(['zero', 'one', 'two', 'three', 'four'], $array);
@@ -1202,7 +1312,7 @@ public function testPrepend()
$this->assertEquals(['one', 'two', null => ['zero']], $array);
}
- public function testPull()
+ public function testPull(): void
{
$array = ['name' => 'Desk', 'price' => 100];
$name = Arr::pull($array, 'name');
@@ -1228,7 +1338,7 @@ public function testPull()
$this->assertSame([1 => 'Second'], $array);
}
- public function testQuery()
+ public function testQuery(): void
{
$this->assertSame('', Arr::query([]));
$this->assertSame('foo=bar', Arr::query(['foo' => 'bar']));
@@ -1238,7 +1348,7 @@ public function testQuery()
$this->assertSame('foo=bar&bar=', Arr::query(['foo' => 'bar', 'bar' => '']));
}
- public function testRandom()
+ public function testRandom(): void
{
$random = Arr::random(['foo', 'bar', 'baz']);
$this->assertContains($random, ['foo', 'bar', 'baz']);
@@ -1280,13 +1390,13 @@ public function testRandom()
$this->assertCount(2, array_intersect_assoc(['one' => 'foo', 'two' => 'bar', 'three' => 'baz'], $random));
}
- public function testRandomNotIncrementingKeys()
+ public function testRandomNotIncrementingKeys(): void
{
$random = Arr::random(['foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz']);
$this->assertContains($random, ['foo', 'bar', 'baz']);
}
- public function testRandomOnEmptyArray()
+ public function testRandomOnEmptyArray(): void
{
$random = Arr::random([], 0);
$this->assertIsArray($random);
@@ -1297,7 +1407,7 @@ public function testRandomOnEmptyArray()
$this->assertCount(0, $random);
}
- public function testRandomThrowsAnErrorWhenRequestingMoreItemsThanAreAvailable()
+ public function testRandomThrowsAnErrorWhenRequestingMoreItemsThanAreAvailable(): void
{
$exceptions = 0;
@@ -1322,7 +1432,7 @@ public function testRandomThrowsAnErrorWhenRequestingMoreItemsThanAreAvailable()
$this->assertSame(3, $exceptions);
}
- public function testSet()
+ public function testSet(): void
{
$array = ['products' => ['desk' => ['price' => 100]]];
Arr::set($array, 'products.desk.price', 200);
@@ -1364,7 +1474,7 @@ public function testSet()
$this->assertEquals([1 => 'hAz'], Arr::set($array, 1, 'hAz'));
}
- public function testShuffleProducesDifferentShuffles()
+ public function testShuffleProducesDifferentShuffles(): void
{
$input = range('a', 'z');
@@ -1374,7 +1484,7 @@ public function testShuffleProducesDifferentShuffles()
);
}
- public function testShuffleActuallyShuffles()
+ public function testShuffleActuallyShuffles(): void
{
$input = range('a', 'z');
@@ -1384,7 +1494,7 @@ public function testShuffleActuallyShuffles()
);
}
- public function testShuffleKeepsSameValues()
+ public function testShuffleKeepsSameValues(): void
{
$input = range('a', 'z');
$shuffled = Arr::shuffle($input);
@@ -1393,7 +1503,7 @@ public function testShuffleKeepsSameValues()
$this->assertEquals($input, $shuffled);
}
- public function testSoleReturnsFirstItemInCollectionIfOnlyOneExists()
+ public function testSoleReturnsFirstItemInCollectionIfOnlyOneExists(): void
{
$this->assertSame('foo', Arr::sole(['foo']));
@@ -1408,21 +1518,21 @@ public function testSoleReturnsFirstItemInCollectionIfOnlyOneExists()
);
}
- public function testSoleThrowsExceptionIfNoItemsExist()
+ public function testSoleThrowsExceptionIfNoItemsExist(): void
{
$this->expectException(ItemNotFoundException::class);
Arr::sole(['foo'], fn (string $value) => $value === 'baz');
}
- public function testSoleThrowsExceptionIfMoreThanOneItemExists()
+ public function testSoleThrowsExceptionIfMoreThanOneItemExists(): void
{
$this->expectExceptionObject(new MultipleItemsFoundException(2));
Arr::sole(['baz', 'foo', 'baz'], fn (string $value) => $value === 'baz');
}
- public function testEmptyShuffle()
+ public function testEmptyShuffle(): void
{
$this->assertEquals([], Arr::shuffle([]));
}
@@ -1487,7 +1597,7 @@ public function testSortDesc(): void
$this->assertEquals([['Desk', 2], ['Chair', 1]], $sortedWithIntegerKey);
}
- public function testSortRecursive()
+ public function testSortRecursive(): void
{
$array = [
'users' => [
@@ -1601,7 +1711,7 @@ public function testSortRecursiveDesc(): void
$this->assertEquals($expect, Arr::sortRecursive($array, SORT_REGULAR, SortDirection::Descending));
}
- public function testToCssClasses()
+ public function testToCssClasses(): void
{
$classes = Arr::toCssClasses([
'font-bold',
@@ -1620,7 +1730,7 @@ public function testToCssClasses()
$this->assertSame('font-bold mt-4 ml-2', $classes);
}
- public function testToCssStyles()
+ public function testToCssStyles(): void
{
$styles = Arr::toCssStyles([
'font-weight: bold',
@@ -1639,7 +1749,7 @@ public function testToCssStyles()
$this->assertSame('font-weight: bold; margin-top: 4px; margin-left: 2px;', $styles);
}
- public function testWhere()
+ public function testWhere(): void
{
$array = [100, '200', 300, '400', 500];
@@ -1650,7 +1760,7 @@ public function testWhere()
$this->assertEquals([1 => '200', 3 => '400'], $array);
}
- public function testWhereKey()
+ public function testWhereKey(): void
{
$array = ['10' => 1, 'foo' => 3, 20 => 2];
@@ -1661,7 +1771,7 @@ public function testWhereKey()
$this->assertEquals(['10' => 1, 20 => 2], $array);
}
- public function testForget()
+ public function testForget(): void
{
$array = ['products' => ['desk' => ['price' => 100]]];
Arr::forget($array, null);
@@ -1718,7 +1828,7 @@ public function testForget()
$this->assertEquals([2 => [1 => 'products']], $array);
}
- public function testFrom()
+ public function testFrom(): void
{
$this->assertSame(['foo' => 'bar'], Arr::from(['foo' => 'bar']));
$this->assertSame(['foo' => 'bar'], Arr::from((object) ['foo' => 'bar']));
@@ -1744,7 +1854,7 @@ public function testFrom()
Arr::from(123);
}
- public function testWrap()
+ public function testWrap(): void
{
$string = 'a';
$array = ['a'];
@@ -1769,7 +1879,7 @@ public function testWrap()
$this->assertSame($obj, Arr::wrap($obj)[0]);
}
- public function testSortByMany()
+ public function testSortByMany(): void
{
$unsorted = [
['name' => 'John', 'age' => 8, 'meta' => ['key' => 3]],
@@ -1822,7 +1932,7 @@ function ($a, $b) {
], $sortedWithCallable);
}
- public function testKeyBy()
+ public function testKeyBy(): void
{
$array = [
['id' => '123', 'data' => 'abc'],
@@ -1837,7 +1947,7 @@ public function testKeyBy()
], Arr::keyBy($array, 'id'));
}
- public function testPrependKeysWith()
+ public function testPrependKeysWith(): void
{
$array = [
'id' => '123',
@@ -1878,7 +1988,7 @@ public function testTake(): void
$this->assertEquals([1, 2, 3, 4, 5, 6], Arr::take($array, -10));
}
- public function testSelect()
+ public function testSelect(): void
{
$array = [
[
@@ -1924,7 +2034,7 @@ public function testSelect()
], Arr::select($array, null));
}
- public function testReject()
+ public function testReject(): void
{
$array = [1, 2, 3, 4, 5, 6];
@@ -1952,7 +2062,7 @@ public function testReject()
], $result);
}
- public function testPartition()
+ public function testPartition(): void
{
$array = ['John', 'Jane', 'Greg'];
diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php
index afa443b4f..7b61e03b4 100644
--- a/tests/Support/SupportCollectionTest.php
+++ b/tests/Support/SupportCollectionTest.php
@@ -39,14 +39,14 @@
class SupportCollectionTest extends TestCase
{
#[DataProvider('collectionClassProvider')]
- public function testFirstReturnsFirstItemInCollection($collection)
+ public function testFirstReturnsFirstItemInCollection($collection): void
{
$c = new $collection(['foo', 'bar']);
$this->assertSame('foo', $c->first());
}
#[DataProvider('collectionClassProvider')]
- public function testFirstWithCallback($collection)
+ public function testFirstWithCallback($collection): void
{
$data = new $collection(['foo', 'bar', 'baz']);
$result = $data->first(function ($value) {
@@ -56,7 +56,7 @@ public function testFirstWithCallback($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFirstWithCallbackAndDefault($collection)
+ public function testFirstWithCallbackAndDefault($collection): void
{
$data = new $collection(['foo', 'bar']);
$result = $data->first(function ($value) {
@@ -66,7 +66,7 @@ public function testFirstWithCallbackAndDefault($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFirstWithDefaultAndWithoutCallback($collection)
+ public function testFirstWithDefaultAndWithoutCallback($collection): void
{
$data = new $collection;
$result = $data->first(null, 'default');
@@ -78,7 +78,7 @@ public function testFirstWithDefaultAndWithoutCallback($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSoleReturnsFirstItemInCollectionIfOnlyOneExists($collection)
+ public function testSoleReturnsFirstItemInCollectionIfOnlyOneExists($collection): void
{
$collection = new $collection([
['name' => 'foo'],
@@ -91,7 +91,7 @@ public function testSoleReturnsFirstItemInCollectionIfOnlyOneExists($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSoleThrowsExceptionIfNoItemsExist($collection)
+ public function testSoleThrowsExceptionIfNoItemsExist($collection): void
{
$this->expectException(ItemNotFoundException::class);
@@ -104,7 +104,7 @@ public function testSoleThrowsExceptionIfNoItemsExist($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSoleThrowsExceptionIfMoreThanOneItemExists($collection)
+ public function testSoleThrowsExceptionIfMoreThanOneItemExists($collection): void
{
$this->expectExceptionObject(new MultipleItemsFoundException(2));
@@ -118,7 +118,7 @@ public function testSoleThrowsExceptionIfMoreThanOneItemExists($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSoleReturnsFirstItemInCollectionIfOnlyOneExistsWithCallback($collection)
+ public function testSoleReturnsFirstItemInCollectionIfOnlyOneExistsWithCallback($collection): void
{
$data = new $collection(['foo', 'bar', 'baz']);
$result = $data->sole(function ($value) {
@@ -128,7 +128,7 @@ public function testSoleReturnsFirstItemInCollectionIfOnlyOneExistsWithCallback(
}
#[DataProvider('collectionClassProvider')]
- public function testSoleThrowsExceptionIfNoItemsExistWithCallback($collection)
+ public function testSoleThrowsExceptionIfNoItemsExistWithCallback($collection): void
{
$this->expectException(ItemNotFoundException::class);
@@ -140,7 +140,7 @@ public function testSoleThrowsExceptionIfNoItemsExistWithCallback($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSoleThrowsExceptionIfMoreThanOneItemExistsWithCallback($collection)
+ public function testSoleThrowsExceptionIfMoreThanOneItemExistsWithCallback($collection): void
{
$this->expectExceptionObject(new MultipleItemsFoundException(2));
@@ -152,7 +152,7 @@ public function testSoleThrowsExceptionIfMoreThanOneItemExistsWithCallback($coll
}
#[DataProvider('collectionClassProvider')]
- public function testHasSole($collection)
+ public function testHasSole($collection): void
{
$collection = new $collection([
['age' => 2],
@@ -180,7 +180,7 @@ public function testHasSole($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHasMany($collection)
+ public function testHasMany($collection): void
{
$collection = new $collection([
['age' => 2],
@@ -208,7 +208,7 @@ public function testHasMany($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFirstOrFailReturnsFirstItemInCollection($collection)
+ public function testFirstOrFailReturnsFirstItemInCollection($collection): void
{
$collection = new $collection([
['name' => 'foo'],
@@ -221,7 +221,7 @@ public function testFirstOrFailReturnsFirstItemInCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFirstOrFailThrowsExceptionIfNoItemsExist($collection)
+ public function testFirstOrFailThrowsExceptionIfNoItemsExist($collection): void
{
$this->expectException(ItemNotFoundException::class);
@@ -234,7 +234,7 @@ public function testFirstOrFailThrowsExceptionIfNoItemsExist($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFirstOrFailDoesntThrowExceptionIfMoreThanOneItemExists($collection)
+ public function testFirstOrFailDoesntThrowExceptionIfMoreThanOneItemExists($collection): void
{
$collection = new $collection([
['name' => 'foo'],
@@ -246,7 +246,7 @@ public function testFirstOrFailDoesntThrowExceptionIfMoreThanOneItemExists($coll
}
#[DataProvider('collectionClassProvider')]
- public function testFirstOrFailReturnsFirstItemInCollectionIfOnlyOneExistsWithCallback($collection)
+ public function testFirstOrFailReturnsFirstItemInCollectionIfOnlyOneExistsWithCallback($collection): void
{
$data = new $collection(['foo', 'bar', 'baz']);
$result = $data->firstOrFail(function ($value) {
@@ -256,7 +256,7 @@ public function testFirstOrFailReturnsFirstItemInCollectionIfOnlyOneExistsWithCa
}
#[DataProvider('collectionClassProvider')]
- public function testFirstOrFailThrowsExceptionIfNoItemsExistWithCallback($collection)
+ public function testFirstOrFailThrowsExceptionIfNoItemsExistWithCallback($collection): void
{
$this->expectException(ItemNotFoundException::class);
@@ -268,7 +268,7 @@ public function testFirstOrFailThrowsExceptionIfNoItemsExistWithCallback($collec
}
#[DataProvider('collectionClassProvider')]
- public function testFirstOrFailDoesntThrowExceptionIfMoreThanOneItemExistsWithCallback($collection)
+ public function testFirstOrFailDoesntThrowExceptionIfMoreThanOneItemExistsWithCallback($collection): void
{
$data = new $collection(['foo', 'bar', 'bar']);
@@ -281,7 +281,7 @@ public function testFirstOrFailDoesntThrowExceptionIfMoreThanOneItemExistsWithCa
}
#[DataProvider('collectionClassProvider')]
- public function testFirstOrFailStopsIteratingAtFirstMatch($collection)
+ public function testFirstOrFailStopsIteratingAtFirstMatch($collection): void
{
$data = new $collection([
function () {
@@ -301,7 +301,7 @@ function () {
}
#[DataProvider('collectionClassProvider')]
- public function testFirstWhere($collection)
+ public function testFirstWhere($collection): void
{
$data = new $collection([
['material' => 'paper', 'type' => 'book'],
@@ -320,7 +320,7 @@ public function testFirstWhere($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFirstWhereUsingEnum($collection)
+ public function testFirstWhereUsingEnum($collection): void
{
$data = new $collection([
['id' => 1, 'name' => StaffEnum::Taylor],
@@ -334,7 +334,7 @@ public function testFirstWhereUsingEnum($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testLastReturnsLastItemInCollection($collection)
+ public function testLastReturnsLastItemInCollection($collection): void
{
$c = new $collection(['foo', 'bar']);
$this->assertSame('bar', $c->last());
@@ -344,7 +344,7 @@ public function testLastReturnsLastItemInCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testLastWithCallback($collection)
+ public function testLastWithCallback($collection): void
{
$data = new $collection([100, 200, 300]);
$result = $data->last(function ($value) {
@@ -364,7 +364,7 @@ public function testLastWithCallback($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testLastWithCallbackAndDefault($collection)
+ public function testLastWithCallbackAndDefault($collection): void
{
$data = new $collection(['foo', 'bar']);
$result = $data->last(function ($value) {
@@ -380,14 +380,14 @@ public function testLastWithCallbackAndDefault($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testLastWithDefaultAndWithoutCallback($collection)
+ public function testLastWithDefaultAndWithoutCallback($collection): void
{
$data = new $collection;
$result = $data->last(null, 'default');
$this->assertSame('default', $result);
}
- public function testPopReturnsAndRemovesLastItemInCollection()
+ public function testPopReturnsAndRemovesLastItemInCollection(): void
{
$c = new Collection(['foo', 'bar']);
@@ -395,7 +395,7 @@ public function testPopReturnsAndRemovesLastItemInCollection()
$this->assertSame('foo', $c->first());
}
- public function testPopReturnsAndRemovesLastXItemsInCollection()
+ public function testPopReturnsAndRemovesLastXItemsInCollection(): void
{
$c = new Collection(['foo', 'bar', 'baz']);
@@ -405,7 +405,7 @@ public function testPopReturnsAndRemovesLastXItemsInCollection()
$this->assertEquals(new Collection(['baz', 'bar', 'foo']), (new Collection(['foo', 'bar', 'baz']))->pop(6));
}
- public function testShiftReturnsAndRemovesFirstItemInCollection()
+ public function testShiftReturnsAndRemovesFirstItemInCollection(): void
{
$data = new Collection(['Taylor', 'Otwell']);
@@ -415,7 +415,7 @@ public function testShiftReturnsAndRemovesFirstItemInCollection()
$this->assertNull($data->first());
}
- public function testShiftReturnsAndRemovesFirstXItemsInCollection()
+ public function testShiftReturnsAndRemovesFirstXItemsInCollection(): void
{
$data = new Collection(['foo', 'bar', 'baz']);
@@ -436,7 +436,7 @@ public function testShiftReturnsAndRemovesFirstXItemsInCollection()
(new Collection(['foo', 'bar', 'baz']))->shift(-2);
}
- public function testShiftReturnsNullOnEmptyCollection()
+ public function testShiftReturnsNullOnEmptyCollection(): void
{
$itemFoo = new stdClass;
$itemFoo->text = 'f';
@@ -454,7 +454,7 @@ public function testShiftReturnsNullOnEmptyCollection()
}
#[DataProvider('collectionClassProvider')]
- public function testSliding($collection)
+ public function testSliding($collection): void
{
// Default parameters: $size = 2, $step = 1
$this->assertSame([], $collection::times(0)->sliding()->toArray());
@@ -543,7 +543,7 @@ public function testSliding($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testEmptyCollectionIsEmpty($collection)
+ public function testEmptyCollectionIsEmpty($collection): void
{
$c = new $collection;
@@ -551,7 +551,7 @@ public function testEmptyCollectionIsEmpty($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testEmptyCollectionIsNotEmpty($collection)
+ public function testEmptyCollectionIsNotEmpty($collection): void
{
$c = new $collection(['foo', 'bar']);
@@ -560,7 +560,7 @@ public function testEmptyCollectionIsNotEmpty($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCollectionIsConstructed($collection)
+ public function testCollectionIsConstructed($collection): void
{
$data = new $collection('foo');
$this->assertSame(['foo'], $data->all());
@@ -579,7 +579,7 @@ public function testCollectionIsConstructed($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSkipMethod($collection)
+ public function testSkipMethod($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6]);
@@ -591,7 +591,7 @@ public function testSkipMethod($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSkipUntil($collection)
+ public function testSkipUntil($collection): void
{
$data = new $collection([1, 1, 2, 2, 3, 3, 4, 4]);
@@ -627,7 +627,7 @@ public function testSkipUntil($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSkipWhile($collection)
+ public function testSkipWhile($collection): void
{
$data = new $collection([1, 1, 2, 2, 3, 3, 4, 4]);
@@ -663,7 +663,7 @@ public function testSkipWhile($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGetArrayableItems($collection)
+ public function testGetArrayableItems($collection): void
{
$data = new $collection;
@@ -701,7 +701,7 @@ public function testGetArrayableItems($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testToArrayCallsToArrayOnEachItemInCollection($collection)
+ public function testToArrayCallsToArrayOnEachItemInCollection($collection): void
{
$item1 = m::mock(Arrayable::class);
$item1->shouldReceive('toArray')->once()->andReturn(['foo.array']);
@@ -713,7 +713,7 @@ public function testToArrayCallsToArrayOnEachItemInCollection($collection)
$this->assertEquals([['foo.array'], ['bar.array']], $results);
}
- public function testLazyReturnsLazyCollection()
+ public function testLazyReturnsLazyCollection(): void
{
$data = new Collection([1, 2, 3, 4, 5]);
@@ -726,7 +726,7 @@ public function testLazyReturnsLazyCollection()
}
#[DataProvider('collectionClassProvider')]
- public function testJsonSerializeCallsToArrayOrJsonSerializeOnEachItemInCollection($collection)
+ public function testJsonSerializeCallsToArrayOrJsonSerializeOnEachItemInCollection($collection): void
{
$item1 = m::mock(JsonSerializable::class);
$item1->shouldReceive('jsonSerialize')->once()->andReturn('foo.json');
@@ -739,7 +739,7 @@ public function testJsonSerializeCallsToArrayOrJsonSerializeOnEachItemInCollecti
}
#[DataProvider('collectionClassProvider')]
- public function testToJsonEncodesTheJsonSerializeResult($collection)
+ public function testToJsonEncodesTheJsonSerializeResult($collection): void
{
$c = $this->getMockBuilder($collection)->onlyMethods(['jsonSerialize'])->getMock();
$c->expects($this->once())->method('jsonSerialize')->willReturn(['foo']);
@@ -748,7 +748,7 @@ public function testToJsonEncodesTheJsonSerializeResult($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testToPrettyJsonEncodesTheJsonSerializeResult($collection)
+ public function testToPrettyJsonEncodesTheJsonSerializeResult($collection): void
{
$c = $this->getMockBuilder($collection)->onlyMethods(['jsonSerialize'])->getMock();
$c->expects($this->once())->method('jsonSerialize')->willReturn(['foo' => 'bar', 'baz' => 'qux']);
@@ -761,7 +761,7 @@ public function testToPrettyJsonEncodesTheJsonSerializeResult($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCastingToStringJsonEncodesTheToArrayResult($collection)
+ public function testCastingToStringJsonEncodesTheToArrayResult($collection): void
{
$c = $this->getMockBuilder($collection)->onlyMethods(['jsonSerialize'])->getMock();
$c->expects($this->once())->method('jsonSerialize')->willReturn(['foo']);
@@ -769,7 +769,7 @@ public function testCastingToStringJsonEncodesTheToArrayResult($collection)
$this->assertJsonStringEqualsJsonString(json_encode(['foo']), (string) $c);
}
- public function testOffsetAccess()
+ public function testOffsetAccess(): void
{
$c = new Collection(['name' => 'taylor']);
$this->assertSame('taylor', $c['name']);
@@ -782,7 +782,7 @@ public function testOffsetAccess()
$this->assertSame('jason', $c[0]);
}
- public function testArrayAccessOffsetExists()
+ public function testArrayAccessOffsetExists(): void
{
$c = new Collection(['foo', 'bar', null]);
$this->assertTrue($c->offsetExists(0));
@@ -790,7 +790,7 @@ public function testArrayAccessOffsetExists()
$this->assertFalse($c->offsetExists(2));
}
- public function testBehavesLikeAnArrayWithArrayAccess()
+ public function testBehavesLikeAnArrayWithArrayAccess(): void
{
// indexed array
$input = ['foo', null];
@@ -811,14 +811,14 @@ public function testBehavesLikeAnArrayWithArrayAccess()
$this->assertEquals($input['k2'], $c['k2']);
}
- public function testArrayAccessOffsetGet()
+ public function testArrayAccessOffsetGet(): void
{
$c = new Collection(['foo', 'bar']);
$this->assertSame('foo', $c->offsetGet(0));
$this->assertSame('bar', $c->offsetGet(1));
}
- public function testArrayAccessOffsetSet()
+ public function testArrayAccessOffsetSet(): void
{
$c = new Collection(['foo', 'foo']);
@@ -829,7 +829,7 @@ public function testArrayAccessOffsetSet()
$this->assertSame('qux', $c[2]);
}
- public function testArrayAccessOffsetUnset()
+ public function testArrayAccessOffsetUnset(): void
{
$c = new Collection(['foo', 'bar']);
@@ -837,7 +837,21 @@ public function testArrayAccessOffsetUnset()
$this->assertFalse(isset($c[1]));
}
- public function testForgetSingleKey()
+ public function testArrayAccessMethodsUseTheInterfaceParameterNames(): void
+ {
+ $collection = new Collection(['name' => 'Taylor']);
+
+ $this->assertTrue($collection->offsetExists(offset: 'name'));
+ $this->assertSame('Taylor', $collection->offsetGet(offset: 'name'));
+
+ $collection->offsetSet(offset: 'framework', value: 'Hypervel');
+ $this->assertSame('Hypervel', $collection->get('framework'));
+
+ $collection->offsetUnset(offset: 'name');
+ $this->assertFalse($collection->has('name'));
+ }
+
+ public function testForgetSingleKey(): void
{
$c = new Collection(['foo', 'bar']);
$c = $c->forget(0)->all();
@@ -851,7 +865,7 @@ public function testForgetSingleKey()
$this->assertTrue(isset($c['baz']));
}
- public function testForgetArrayOfKeys()
+ public function testForgetArrayOfKeys(): void
{
$c = new Collection(['foo', 'bar', 'baz']);
$c = $c->forget([0, 2])->all();
@@ -866,7 +880,7 @@ public function testForgetArrayOfKeys()
$this->assertTrue(isset($c['name']));
}
- public function testForgetCollectionOfKeys()
+ public function testForgetCollectionOfKeys(): void
{
$c = new Collection(['foo', 'bar', 'baz']);
$c = $c->forget(collect([0, 2]))->all();
@@ -882,14 +896,14 @@ public function testForgetCollectionOfKeys()
}
#[DataProvider('collectionClassProvider')]
- public function testCountable($collection)
+ public function testCountable($collection): void
{
$c = new $collection(['foo', 'bar']);
$this->assertCount(2, $c);
}
#[DataProvider('collectionClassProvider')]
- public function testCountByStandalone($collection)
+ public function testCountByStandalone($collection): void
{
$c = new $collection(['foo', 'foo', 'foo', 'bar', 'bar', 'foobar']);
$this->assertEquals(['foo' => 3, 'bar' => 2, 'foobar' => 1], $c->countBy()->all());
@@ -905,7 +919,7 @@ public function testCountByStandalone($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCountByWithKey($collection)
+ public function testCountByWithKey($collection): void
{
$c = new $collection([
['key' => 'a'], ['key' => 'a'], ['key' => 'a'], ['key' => 'a'],
@@ -921,7 +935,7 @@ public function testCountByWithKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCountableByWithCallback($collection)
+ public function testCountableByWithCallback($collection): void
{
$c = new $collection(['alice', 'aaron', 'bob', 'carla']);
$this->assertEquals(['a' => 2, 'b' => 1, 'c' => 1], $c->countBy(function ($name) {
@@ -937,7 +951,7 @@ public function testCountableByWithCallback($collection)
$this->assertEquals(['A' => 3, 'B' => 1], $c->countBy(static fn ($i) => TestStringBackedEnum::from($i))->all());
}
- public function testAdd()
+ public function testAdd(): void
{
$c = new Collection([]);
$this->assertEquals([1], $c->add(1)->values()->all());
@@ -949,33 +963,9 @@ public function testAdd()
$this->assertEquals([1, 2, '', null, false, [], 'name'], $c->add('name')->values()->all());
}
- #[DataProvider('collectionClassProvider')]
- public function testContainsOneItem($collection)
- {
- $this->assertFalse((new $collection([]))->containsOneItem());
- $this->assertTrue((new $collection([1]))->containsOneItem());
- $this->assertFalse((new $collection([1, 2]))->containsOneItem());
-
- $this->assertFalse(collect([1, 2, 2])->containsOneItem(fn ($number) => $number === 2));
- $this->assertTrue(collect(['ant', 'bear', 'cat'])->containsOneItem(fn ($word) => strlen($word) === 4));
- $this->assertFalse(collect(['ant', 'bear', 'cat'])->containsOneItem(fn ($word) => strlen($word) > 4));
- }
+ // REMOVED: Tests for Laravel's deprecated containsOneItem() and containsManyItems(); use hasSole() and hasMany().
- #[DataProvider('collectionClassProvider')]
- public function testContainsManyItems($collection)
- {
- $this->assertFalse((new $collection([]))->containsManyItems());
- $this->assertFalse((new $collection([1]))->containsManyItems());
- $this->assertTrue((new $collection([1, 2]))->containsManyItems());
- $this->assertTrue((new $collection([1, 2, 3]))->containsManyItems());
-
- $this->assertTrue(collect([1, 2, 2])->containsManyItems(fn ($number) => $number === 2));
- $this->assertFalse(collect(['ant', 'bear', 'cat'])->containsManyItems(fn ($word) => strlen($word) === 4));
- $this->assertFalse(collect(['ant', 'bear', 'cat'])->containsManyItems(fn ($word) => strlen($word) > 4));
- $this->assertTrue(collect(['ant', 'bear', 'cat'])->containsManyItems(fn ($word) => strlen($word) === 3));
- }
-
- public function testIterable()
+ public function testIterable(): void
{
$c = new Collection(['foo']);
$this->assertInstanceOf(ArrayIterator::class, $c->getIterator());
@@ -983,14 +973,14 @@ public function testIterable()
}
#[DataProvider('collectionClassProvider')]
- public function testCachingIterator($collection)
+ public function testCachingIterator($collection): void
{
$c = new $collection(['foo']);
$this->assertInstanceOf(CachingIterator::class, $c->getCachingIterator());
}
#[DataProvider('collectionClassProvider')]
- public function testFilter($collection)
+ public function testFilter($collection): void
{
$c = new $collection([['id' => 1, 'name' => 'Hello'], ['id' => 2, 'name' => 'World']]);
$this->assertEquals([1 => ['id' => 2, 'name' => 'World']], $c->filter(function ($item) {
@@ -1010,7 +1000,7 @@ public function testFilter($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHigherOrderKeyBy($collection)
+ public function testHigherOrderKeyBy($collection): void
{
$c = new $collection([
['id' => 'id1', 'name' => 'first'],
@@ -1021,7 +1011,7 @@ public function testHigherOrderKeyBy($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHigherOrderUnique($collection)
+ public function testHigherOrderUnique($collection): void
{
$c = new $collection([
['id' => '1', 'name' => 'first'],
@@ -1032,7 +1022,7 @@ public function testHigherOrderUnique($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHigherOrderFilter($collection)
+ public function testHigherOrderFilter($collection): void
{
$c = new $collection([
new class {
@@ -1057,7 +1047,7 @@ public function active()
}
#[DataProvider('collectionClassProvider')]
- public function testWhere($collection)
+ public function testWhere($collection): void
{
$c = new $collection([['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3'], ['v' => 4]]);
@@ -1195,7 +1185,7 @@ public function testWhere($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhereStrict($collection)
+ public function testWhereStrict($collection): void
{
$c = new $collection([['v' => 3], ['v' => '3']]);
@@ -1206,7 +1196,7 @@ public function testWhereStrict($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhereInstanceOf($collection)
+ public function testWhereInstanceOf($collection): void
{
$c = new $collection([new stdClass, new stdClass, new $collection, new stdClass, new Str]);
$this->assertCount(3, $c->whereInstanceOf(stdClass::class));
@@ -1215,7 +1205,7 @@ public function testWhereInstanceOf($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhereIn($collection)
+ public function testWhereIn($collection): void
{
$c = new $collection([['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3'], ['v' => 4]]);
$this->assertEquals([['v' => 1], ['v' => 3], ['v' => '3']], $c->whereIn('v', [1, 3])->values()->all());
@@ -1224,14 +1214,14 @@ public function testWhereIn($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhereInStrict($collection)
+ public function testWhereInStrict($collection): void
{
$c = new $collection([['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3'], ['v' => 4]]);
$this->assertEquals([['v' => 1], ['v' => 3]], $c->whereInStrict('v', [1, 3])->values()->all());
}
#[DataProvider('collectionClassProvider')]
- public function testWhereNotIn($collection)
+ public function testWhereNotIn($collection): void
{
$c = new $collection([['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3'], ['v' => 4]]);
$this->assertEquals([['v' => 2], ['v' => 4]], $c->whereNotIn('v', [1, 3])->values()->all());
@@ -1239,14 +1229,14 @@ public function testWhereNotIn($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhereNotInStrict($collection)
+ public function testWhereNotInStrict($collection): void
{
$c = new $collection([['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3'], ['v' => 4]]);
$this->assertEquals([['v' => 2], ['v' => '3'], ['v' => 4]], $c->whereNotInStrict('v', [1, 3])->values()->all());
}
#[DataProvider('collectionClassProvider')]
- public function testValues($collection)
+ public function testValues($collection): void
{
$c = new $collection([['id' => 1, 'name' => 'Hello'], ['id' => 2, 'name' => 'World']]);
$this->assertEquals([['id' => 2, 'name' => 'World']], $c->filter(function ($item) {
@@ -1255,14 +1245,14 @@ public function testValues($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testValuesResetKey($collection)
+ public function testValuesResetKey($collection): void
{
$data = new $collection([1 => 'a', 2 => 'b', 3 => 'c']);
$this->assertEquals([0 => 'a', 1 => 'b', 2 => 'c'], $data->values()->all());
}
#[DataProvider('collectionClassProvider')]
- public function testValue($collection)
+ public function testValue($collection): void
{
$c = new $collection([['id' => 1, 'name' => 'Hello'], ['id' => 2, 'name' => 'World']]);
@@ -1280,7 +1270,7 @@ public function testValue($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testValueUsingEnum($collection)
+ public function testValueUsingEnum($collection): void
{
$c = new $collection([['id' => 1, 'name' => StaffEnum::Taylor], ['id' => 2, 'name' => StaffEnum::Joe]]);
@@ -1289,7 +1279,7 @@ public function testValueUsingEnum($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testValueWithNegativeValue($collection)
+ public function testValueWithNegativeValue($collection): void
{
$c = new $collection([['id' => 1, 'balance' => 0], ['id' => 2, 'balance' => 200]]);
@@ -1313,7 +1303,7 @@ public function testValueWithNegativeValue($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testValueWithObjects($collection)
+ public function testValueWithObjects($collection): void
{
$c = new $collection([
literal(id: 1),
@@ -1333,7 +1323,7 @@ public function testValueWithObjects($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testBetween($collection)
+ public function testBetween($collection): void
{
$c = new $collection([['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3'], ['v' => 4]]);
@@ -1346,7 +1336,7 @@ public function testBetween($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhereNotBetween($collection)
+ public function testWhereNotBetween($collection): void
{
$c = new $collection([['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3'], ['v' => 4]]);
@@ -1356,7 +1346,7 @@ public function testWhereNotBetween($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFlatten($collection)
+ public function testFlatten($collection): void
{
// Flat arrays are unaffected
$c = new $collection(['#foo', '#bar', '#baz']);
@@ -1392,7 +1382,7 @@ public function testFlatten($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFlattenWithDepth($collection)
+ public function testFlattenWithDepth($collection): void
{
// No depth flattens recursively
$c = new $collection([['#foo', ['#bar', ['#baz']]], '#zap']);
@@ -1407,7 +1397,7 @@ public function testFlattenWithDepth($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFlattenIgnoresKeys($collection)
+ public function testFlattenIgnoresKeys($collection): void
{
// No depth ignores keys
$c = new $collection(['#foo', ['key' => '#bar'], ['key' => '#baz'], 'key' => '#zap']);
@@ -1419,42 +1409,42 @@ public function testFlattenIgnoresKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMergeNull($collection)
+ public function testMergeNull($collection): void
{
$c = new $collection(['name' => 'Hello']);
$this->assertEquals(['name' => 'Hello'], $c->merge(null)->all());
}
#[DataProvider('collectionClassProvider')]
- public function testMergeArray($collection)
+ public function testMergeArray($collection): void
{
$c = new $collection(['name' => 'Hello']);
$this->assertEquals(['name' => 'Hello', 'id' => 1], $c->merge(['id' => 1])->all());
}
#[DataProvider('collectionClassProvider')]
- public function testMergeCollection($collection)
+ public function testMergeCollection($collection): void
{
$c = new $collection(['name' => 'Hello']);
$this->assertEquals(['name' => 'World', 'id' => 1], $c->merge(new $collection(['name' => 'World', 'id' => 1]))->all());
}
#[DataProvider('collectionClassProvider')]
- public function testMergeRecursiveNull($collection)
+ public function testMergeRecursiveNull($collection): void
{
$c = new $collection(['name' => 'Hello']);
$this->assertEquals(['name' => 'Hello'], $c->mergeRecursive(null)->all());
}
#[DataProvider('collectionClassProvider')]
- public function testMergeRecursiveArray($collection)
+ public function testMergeRecursiveArray($collection): void
{
$c = new $collection(['name' => 'Hello', 'id' => 1]);
$this->assertEquals(['name' => 'Hello', 'id' => [1, 2]], $c->mergeRecursive(['id' => 2])->all());
}
#[DataProvider('collectionClassProvider')]
- public function testMergeRecursiveCollection($collection)
+ public function testMergeRecursiveCollection($collection): void
{
$c = new $collection(['name' => 'Hello', 'id' => 1, 'meta' => ['tags' => ['a', 'b'], 'roles' => 'admin']]);
$this->assertEquals(
@@ -1464,7 +1454,7 @@ public function testMergeRecursiveCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMultiplyCollection($collection)
+ public function testMultiplyCollection($collection): void
{
$c = new $collection(['Hello', 1, ['tags' => ['a', 'b'], 'admin']]);
@@ -1483,14 +1473,14 @@ public function testMultiplyCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testReplaceNull($collection)
+ public function testReplaceNull($collection): void
{
$c = new $collection(['a', 'b', 'c']);
$this->assertEquals(['a', 'b', 'c'], $c->replace(null)->all());
}
#[DataProvider('collectionClassProvider')]
- public function testReplaceArray($collection)
+ public function testReplaceArray($collection): void
{
$c = new $collection(['a', 'b', 'c']);
$this->assertEquals(['a', 'd', 'e'], $c->replace([1 => 'd', 2 => 'e'])->all());
@@ -1503,7 +1493,7 @@ public function testReplaceArray($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testReplaceCollection($collection)
+ public function testReplaceCollection($collection): void
{
$c = new $collection(['a', 'b', 'c']);
$this->assertEquals(
@@ -1525,14 +1515,14 @@ public function testReplaceCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testReplaceRecursiveNull($collection)
+ public function testReplaceRecursiveNull($collection): void
{
$c = new $collection(['a', 'b', ['c', 'd']]);
$this->assertEquals(['a', 'b', ['c', 'd']], $c->replaceRecursive(null)->all());
}
#[DataProvider('collectionClassProvider')]
- public function testReplaceRecursiveArray($collection)
+ public function testReplaceRecursiveArray($collection): void
{
$c = new $collection(['a', 'b', ['c', 'd']]);
$this->assertEquals(['z', 'b', ['c', 'e']], $c->replaceRecursive(['z', 2 => [1 => 'e']])->all());
@@ -1542,7 +1532,7 @@ public function testReplaceRecursiveArray($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testReplaceRecursiveCollection($collection)
+ public function testReplaceRecursiveCollection($collection): void
{
$c = new $collection(['a', 'b', ['c', 'd']]);
$this->assertEquals(
@@ -1552,35 +1542,35 @@ public function testReplaceRecursiveCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUnionNull($collection)
+ public function testUnionNull($collection): void
{
$c = new $collection(['name' => 'Hello']);
$this->assertEquals(['name' => 'Hello'], $c->union(null)->all());
}
#[DataProvider('collectionClassProvider')]
- public function testUnionArray($collection)
+ public function testUnionArray($collection): void
{
$c = new $collection(['name' => 'Hello']);
$this->assertEquals(['name' => 'Hello', 'id' => 1], $c->union(['id' => 1])->all());
}
#[DataProvider('collectionClassProvider')]
- public function testUnionCollection($collection)
+ public function testUnionCollection($collection): void
{
$c = new $collection(['name' => 'Hello']);
$this->assertEquals(['name' => 'Hello', 'id' => 1], $c->union(new $collection(['name' => 'World', 'id' => 1]))->all());
}
#[DataProvider('collectionClassProvider')]
- public function testDiffCollection($collection)
+ public function testDiffCollection($collection): void
{
$c = new $collection(['id' => 1, 'first_word' => 'Hello']);
$this->assertEquals(['id' => 1], $c->diff(new $collection(['first_word' => 'Hello', 'last_word' => 'World']))->all());
}
#[DataProvider('collectionClassProvider')]
- public function testDiffUsingWithCollection($collection)
+ public function testDiffUsingWithCollection($collection): void
{
$c = new $collection(['en_GB', 'fr', 'HR']);
// demonstrate that diff won't support case insensitivity
@@ -1590,21 +1580,21 @@ public function testDiffUsingWithCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDiffUsingWithNull($collection)
+ public function testDiffUsingWithNull($collection): void
{
$c = new $collection(['en_GB', 'fr', 'HR']);
$this->assertEquals(['en_GB', 'fr', 'HR'], $c->diffUsing(null, 'strcasecmp')->values()->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testDiffNull($collection)
+ public function testDiffNull($collection): void
{
$c = new $collection(['id' => 1, 'first_word' => 'Hello']);
$this->assertEquals(['id' => 1, 'first_word' => 'Hello'], $c->diff(null)->all());
}
#[DataProvider('collectionClassProvider')]
- public function testDiffKeys($collection)
+ public function testDiffKeys($collection): void
{
$c1 = new $collection(['id' => 1, 'first_word' => 'Hello']);
$c2 = new $collection(['id' => 123, 'foo_bar' => 'Hello']);
@@ -1612,7 +1602,7 @@ public function testDiffKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDiffKeysUsing($collection)
+ public function testDiffKeysUsing($collection): void
{
$c1 = new $collection(['id' => 1, 'first_word' => 'Hello']);
$c2 = new $collection(['ID' => 123, 'foo_bar' => 'Hello']);
@@ -1623,7 +1613,7 @@ public function testDiffKeysUsing($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDiffAssoc($collection)
+ public function testDiffAssoc($collection): void
{
$c1 = new $collection(['id' => 1, 'first_word' => 'Hello', 'not_affected' => 'value']);
$c2 = new $collection(['id' => 123, 'foo_bar' => 'Hello', 'not_affected' => 'value']);
@@ -1631,7 +1621,7 @@ public function testDiffAssoc($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDiffAssocUsing($collection)
+ public function testDiffAssocUsing($collection): void
{
$c1 = new $collection(['a' => 'green', 'b' => 'brown', 'c' => 'blue', 'red']);
$c2 = new $collection(['A' => 'green', 'yellow', 'red']);
@@ -1642,7 +1632,7 @@ public function testDiffAssocUsing($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDuplicates($collection)
+ public function testDuplicates($collection): void
{
$duplicates = $collection::make([1, 2, 1, 'laravel', null, 'laravel', 'php', null])->duplicates()->all();
$this->assertSame([2 => 1, 5 => 'laravel', 7 => null], $duplicates);
@@ -1662,7 +1652,7 @@ public function testDuplicates($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDuplicatesWithKey($collection)
+ public function testDuplicatesWithKey($collection): void
{
$items = [['framework' => 'vue'], ['framework' => 'laravel'], ['framework' => 'laravel']];
$duplicates = $collection::make($items)->duplicates('framework')->all();
@@ -1675,7 +1665,7 @@ public function testDuplicatesWithKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDuplicatesWithCallback($collection)
+ public function testDuplicatesWithCallback($collection): void
{
$items = [['framework' => 'vue'], ['framework' => 'laravel'], ['framework' => 'laravel']];
$duplicates = $collection::make($items)->duplicates(function ($item) {
@@ -1685,7 +1675,7 @@ public function testDuplicatesWithCallback($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDuplicatesWithStrict($collection)
+ public function testDuplicatesWithStrict($collection): void
{
$duplicates = $collection::make([1, 2, 1, 'laravel', null, 'laravel', 'php', null])->duplicatesStrict()->all();
$this->assertSame([2 => 1, 5 => 'laravel', 7 => null], $duplicates);
@@ -1705,7 +1695,7 @@ public function testDuplicatesWithStrict($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testEach($collection)
+ public function testEach($collection): void
{
$c = new $collection($original = [1, 2, 'foo' => 'bar', 'bam' => 'baz']);
@@ -1726,7 +1716,7 @@ public function testEach($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testEachSpread($collection)
+ public function testEachSpread($collection): void
{
$c = new $collection([[1, 'a'], [2, 'b']]);
@@ -1759,21 +1749,21 @@ public function testEachSpread($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testIntersectNull($collection)
+ public function testIntersectNull($collection): void
{
$c = new $collection(['id' => 1, 'first_word' => 'Hello']);
$this->assertEquals([], $c->intersect(null)->all());
}
#[DataProvider('collectionClassProvider')]
- public function testIntersectCollection($collection)
+ public function testIntersectCollection($collection): void
{
$c = new $collection(['id' => 1, 'first_word' => 'Hello']);
$this->assertEquals(['first_word' => 'Hello'], $c->intersect(new $collection(['first_world' => 'Hello', 'last_word' => 'World']))->all());
}
#[DataProvider('collectionClassProvider')]
- public function testIntersectUsingWithNull($collection)
+ public function testIntersectUsingWithNull($collection): void
{
$collect = new $collection(['green', 'brown', 'blue']);
@@ -1781,7 +1771,7 @@ public function testIntersectUsingWithNull($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testIntersectUsingCollection($collection)
+ public function testIntersectUsingCollection($collection): void
{
$collect = new $collection(['green', 'brown', 'blue']);
@@ -1789,7 +1779,7 @@ public function testIntersectUsingCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testIntersectAssocWithNull($collection)
+ public function testIntersectAssocWithNull($collection): void
{
$array1 = new $collection(['a' => 'green', 'b' => 'brown', 'c' => 'blue', 'red']);
@@ -1797,7 +1787,7 @@ public function testIntersectAssocWithNull($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testIntersectAssocCollection($collection)
+ public function testIntersectAssocCollection($collection): void
{
$array1 = new $collection(['a' => 'green', 'b' => 'brown', 'c' => 'blue', 'red']);
$array2 = new $collection(['a' => 'green', 'b' => 'yellow', 'blue', 'red']);
@@ -1806,7 +1796,7 @@ public function testIntersectAssocCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testIntersectAssocUsingWithNull($collection)
+ public function testIntersectAssocUsingWithNull($collection): void
{
$array1 = new $collection(['a' => 'green', 'b' => 'brown', 'c' => 'blue', 'red']);
@@ -1814,7 +1804,7 @@ public function testIntersectAssocUsingWithNull($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testIntersectAssocUsingCollection($collection)
+ public function testIntersectAssocUsingCollection($collection): void
{
$array1 = new $collection(['a' => 'green', 'b' => 'brown', 'c' => 'blue', 'red']);
$array2 = new $collection(['a' => 'GREEN', 'B' => 'brown', 'yellow', 'red']);
@@ -1823,14 +1813,14 @@ public function testIntersectAssocUsingCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testIntersectByKeysNull($collection)
+ public function testIntersectByKeysNull($collection): void
{
$c = new $collection(['name' => 'Mateus', 'age' => 18]);
$this->assertEquals([], $c->intersectByKeys(null)->all());
}
#[DataProvider('collectionClassProvider')]
- public function testIntersectByKeys($collection)
+ public function testIntersectByKeys($collection): void
{
$c = new $collection(['name' => 'Mateus', 'age' => 18]);
$this->assertEquals(['name' => 'Mateus'], $c->intersectByKeys(new $collection(['name' => 'Mateus', 'surname' => 'Guimaraes']))->all());
@@ -1840,7 +1830,7 @@ public function testIntersectByKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUnique($collection)
+ public function testUnique($collection): void
{
$c = new $collection(['Hello', 'World', 'World']);
$this->assertEquals(['Hello', 'World'], $c->unique()->all());
@@ -1850,7 +1840,7 @@ public function testUnique($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUniqueWithCallback($collection)
+ public function testUniqueWithCallback($collection): void
{
$c = new $collection([
1 => ['id' => 1, 'first' => 'Taylor', 'last' => 'Otwell'],
@@ -1883,7 +1873,7 @@ public function testUniqueWithCallback($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUniqueStrict($collection)
+ public function testUniqueStrict($collection): void
{
$c = new $collection([
[
@@ -1913,7 +1903,7 @@ public function testUniqueStrict($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCollapse($collection)
+ public function testCollapse($collection): void
{
// Normal case: a two-dimensional array with different elements
$data = new $collection([[$object1 = new stdClass], [$object2 = new stdClass]]);
@@ -1938,14 +1928,14 @@ public function testCollapse($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCollapseWithNestedCollections($collection)
+ public function testCollapseWithNestedCollections($collection): void
{
$data = new $collection([new $collection([1, 2, 3]), new $collection([4, 5, 6])]);
$this->assertEquals([1, 2, 3, 4, 5, 6], $data->collapse()->all());
}
#[DataProvider('collectionClassProvider')]
- public function testCollapseWithKeys($collection)
+ public function testCollapseWithKeys($collection): void
{
$data = new $collection([[1 => 'a'], [3 => 'c'], [2 => 'b'], 'drop']);
$this->assertEquals([1 => 'a', 3 => 'c', 2 => 'b'], $data->collapseWithKeys()->all());
@@ -1956,14 +1946,14 @@ public function testCollapseWithKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCollapseWithKeysOnNestedCollections($collection)
+ public function testCollapseWithKeysOnNestedCollections($collection): void
{
$data = new $collection([new $collection(['a' => '1a', 'b' => '1b']), new $collection(['b' => '2b', 'c' => '2c']), 'drop']);
$this->assertEquals(['a' => '1a', 'b' => '2b', 'c' => '2c'], $data->collapseWithKeys()->all());
}
#[DataProvider('collectionClassProvider')]
- public function testJoin($collection)
+ public function testJoin($collection): void
{
$this->assertSame('a, b, c', (new $collection(['a', 'b', 'c']))->join(', '));
@@ -1977,7 +1967,7 @@ public function testJoin($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCrossJoin($collection)
+ public function testCrossJoin($collection): void
{
// Cross join with an array
$this->assertEquals(
@@ -2007,7 +1997,7 @@ public function testCrossJoin($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSort($collection)
+ public function testSort($collection): void
{
$data = (new $collection([5, 3, 1, 2, 4]))->sort();
$this->assertEquals([1, 2, 3, 4, 5], $data->values()->all());
@@ -2026,7 +2016,7 @@ public function testSort($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSortDesc($collection)
+ public function testSortDesc($collection): void
{
$data = (new $collection([5, 3, 1, 2, 4]))->sortDesc();
$this->assertEquals([5, 4, 3, 2, 1], $data->values()->all());
@@ -2045,7 +2035,7 @@ public function testSortDesc($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSortWithCallback($collection)
+ public function testSortWithCallback($collection): void
{
$data = (new $collection([5, 3, 1, 2, 4]))->sort(function ($a, $b) {
if ($a === $b) {
@@ -2088,7 +2078,7 @@ function ($x) {
}
#[DataProvider('collectionClassProvider')]
- public function testSortByString($collection)
+ public function testSortByString($collection): void
{
$data = new $collection([['name' => 'taylor'], ['name' => 'dayle']]);
$data = $data->sortBy('name', SORT_STRING);
@@ -2111,7 +2101,7 @@ public function testSortByIntegerKey($collection): void
}
#[DataProvider('collectionClassProvider')]
- public function testSortByCallableString($collection)
+ public function testSortByCallableString($collection): void
{
$data = new $collection([['sort' => 2], ['sort' => 1]]);
$data = $data->sortBy([['sort', 'asc']]);
@@ -2120,7 +2110,7 @@ public function testSortByCallableString($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSortByCallableStringDesc($collection)
+ public function testSortByCallableStringDesc($collection): void
{
$data = new $collection([['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']]);
$data = $data->sortByDesc(['id']);
@@ -2135,7 +2125,7 @@ public function testSortByCallableStringDesc($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSortByAlwaysReturnsAssoc($collection)
+ public function testSortByAlwaysReturnsAssoc($collection): void
{
$data = new $collection(['a' => 'taylor', 'b' => 'dayle']);
$data = $data->sortBy(function ($x) {
@@ -2278,7 +2268,7 @@ public function testSortByMany($collection): void
}
#[DataProvider('collectionClassProvider')]
- public function testNaturalSortByManyWithNull($collection)
+ public function testNaturalSortByManyWithNull($collection): void
{
$itemFoo = new stdClass;
$itemFoo->first = 'f';
@@ -2307,7 +2297,7 @@ public function testSortKeys($collection): void
}
#[DataProvider('collectionClassProvider')]
- public function testSortKeysDesc($collection)
+ public function testSortKeysDesc($collection): void
{
$data = new $collection(['a' => 'taylor', 'b' => 'dayle']);
@@ -2315,7 +2305,7 @@ public function testSortKeysDesc($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSortKeysUsing($collection)
+ public function testSortKeysUsing($collection): void
{
$data = new $collection(['B' => 'dayle', 'a' => 'taylor']);
@@ -2323,7 +2313,7 @@ public function testSortKeysUsing($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testReverse($collection)
+ public function testReverse($collection): void
{
$data = new $collection(['zaeed', 'alan']);
$reversed = $data->reverse();
@@ -2337,14 +2327,14 @@ public function testReverse($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFlip($collection)
+ public function testFlip($collection): void
{
$data = new $collection(['name' => 'taylor', 'framework' => 'laravel']);
$this->assertEquals(['taylor' => 'name', 'laravel' => 'framework'], $data->flip()->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testChunk($collection)
+ public function testChunk($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
$data = $data->chunk(3);
@@ -2357,7 +2347,7 @@ public function testChunk($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testChunkWhenGivenZeroAsSize($collection)
+ public function testChunkWhenGivenZeroAsSize($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
@@ -2368,7 +2358,7 @@ public function testChunkWhenGivenZeroAsSize($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testChunkWhenGivenLessThanZero($collection)
+ public function testChunkWhenGivenLessThanZero($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
@@ -2379,7 +2369,7 @@ public function testChunkWhenGivenLessThanZero($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testChunkPreservingKeys($collection)
+ public function testChunkPreservingKeys($collection): void
{
$data = new $collection(['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5]);
@@ -2397,7 +2387,7 @@ public function testChunkPreservingKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitIn($collection)
+ public function testSplitIn($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
$data = $data->splitIn(3);
@@ -2411,7 +2401,7 @@ public function testSplitIn($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testChunkWhileOnEqualElements($collection)
+ public function testChunkWhileOnEqualElements($collection): void
{
$data = (new $collection(['A', 'A', 'B', 'B', 'C', 'C', 'C']))
->chunkWhile(function ($current, $key, $chunk) {
@@ -2426,7 +2416,7 @@ public function testChunkWhileOnEqualElements($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testChunkWhileOnContiguouslyIncreasingIntegers($collection)
+ public function testChunkWhileOnContiguouslyIncreasingIntegers($collection): void
{
$data = (new $collection([1, 4, 9, 10, 11, 12, 15, 16, 19, 20, 21]))
->chunkWhile(function ($current, $key, $chunk) {
@@ -2443,7 +2433,7 @@ public function testChunkWhileOnContiguouslyIncreasingIntegers($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testChunkWhilePreservingStringKeys($collection)
+ public function testChunkWhilePreservingStringKeys($collection): void
{
$data = (new $collection(['a' => 1, 'b' => 1, 'c' => 2, 'd' => 2, 'e' => 3, 'f' => 3, 'g' => 3]))
->chunkWhile(function ($current, $key, $chunk) {
@@ -2458,7 +2448,7 @@ public function testChunkWhilePreservingStringKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testEvery($collection)
+ public function testEvery($collection): void
{
$c = new $collection([]);
$this->assertTrue($c->every('key', 'value'));
@@ -2488,7 +2478,7 @@ public function testEvery($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testExcept($collection)
+ public function testExcept($collection): void
{
$data = new $collection(['first' => 'Taylor', 'last' => 'Otwell', 'email' => 'taylorotwell@gmail.com']);
@@ -2503,14 +2493,14 @@ public function testExcept($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testExceptSelf($collection)
+ public function testExceptSelf($collection): void
{
$data = new $collection(['first' => 'Taylor', 'last' => 'Otwell']);
$this->assertEquals(['first' => 'Taylor', 'last' => 'Otwell'], $data->except($data)->all());
}
#[DataProvider('collectionClassProvider')]
- public function testPluckWithArrayAndObjectValues($collection)
+ public function testPluckWithArrayAndObjectValues($collection): void
{
$data = new $collection([(object) ['name' => 'taylor', 'email' => 'foo'], ['name' => 'dayle', 'email' => 'bar']]);
$this->assertEquals(['taylor' => 'foo', 'dayle' => 'bar'], $data->pluck('email', 'name')->all());
@@ -2518,7 +2508,7 @@ public function testPluckWithArrayAndObjectValues($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPluckWithArrayAccessValues($collection)
+ public function testPluckWithArrayAccessValues($collection): void
{
$data = new $collection([
new TestArrayAccessImplementation(['name' => 'taylor', 'email' => 'foo']),
@@ -2530,7 +2520,7 @@ public function testPluckWithArrayAccessValues($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPluckWithDotNotation($collection)
+ public function testPluckWithDotNotation($collection): void
{
$data = new $collection([
[
@@ -2551,7 +2541,7 @@ public function testPluckWithDotNotation($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPluckWithClosure($collection)
+ public function testPluckWithClosure($collection): void
{
$data = new $collection([
[
@@ -2573,7 +2563,7 @@ public function testPluckWithClosure($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPluckDuplicateKeysExist($collection)
+ public function testPluckDuplicateKeysExist($collection): void
{
$data = new $collection([
['brand' => 'Tesla', 'color' => 'red'],
@@ -2586,7 +2576,7 @@ public function testPluckDuplicateKeysExist($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHas($collection)
+ public function testHas($collection): void
{
$data = new $collection(['id' => 1, 'first' => 'Hello', 'second' => 'World']);
$this->assertTrue($data->has('first'));
@@ -2597,7 +2587,7 @@ public function testHas($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHasAny($collection)
+ public function testHasAny($collection): void
{
$data = new $collection(['id' => 1, 'first' => 'Hello', 'second' => 'World']);
@@ -2611,7 +2601,7 @@ public function testHasAny($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testImplode($collection)
+ public function testImplode($collection): void
{
$data = new $collection([['name' => 'taylor', 'email' => 'foo'], ['name' => 'dayle', 'email' => 'bar']]);
$this->assertSame('foobar', $data->implode('email'));
@@ -2639,7 +2629,7 @@ public function testImplode($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testImplodeModels($collection)
+ public function testImplodeModels($collection): void
{
$model = new class extends Model {
};
@@ -2654,14 +2644,14 @@ public function testImplodeModels($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTake($collection)
+ public function testTake($collection): void
{
$data = new $collection(['taylor', 'dayle', 'shawn']);
$data = $data->take(2);
$this->assertEquals(['taylor', 'dayle'], $data->all());
}
- public function testGetOrPut()
+ public function testGetOrPut(): void
{
$data = new Collection(['name' => 'taylor', 'email' => 'foo']);
@@ -2692,7 +2682,7 @@ public function testGetOrPut()
$this->assertSame('male', $data->get('gender'));
}
- public function testGetOrPutWithNoKey()
+ public function testGetOrPutWithNoKey(): void
{
$data = new Collection(['taylor', 'shawn']);
$this->assertSame('dayle', $data->getOrPut(null, 'dayle'));
@@ -2704,14 +2694,14 @@ public function testGetOrPutWithNoKey()
$this->assertSame(['taylor', '' => 'shawn'], $data->all());
}
- public function testPut()
+ public function testPut(): void
{
$data = new Collection(['name' => 'taylor', 'email' => 'foo']);
$data = $data->put('name', 'dayle');
$this->assertEquals(['name' => 'dayle', 'email' => 'foo'], $data->all());
}
- public function testPutWithNoKey()
+ public function testPutWithNoKey(): void
{
$data = new Collection(['taylor', 'shawn']);
$data = $data->put(null, 'dayle');
@@ -2719,7 +2709,7 @@ public function testPutWithNoKey()
}
#[DataProvider('collectionClassProvider')]
- public function testRandom($collection)
+ public function testRandom($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6]);
@@ -2767,7 +2757,7 @@ public function testRandom($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testRandomOnEmptyCollection($collection)
+ public function testRandomOnEmptyCollection($collection): void
{
$data = new $collection;
@@ -2781,7 +2771,7 @@ public function testRandomOnEmptyCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTakeLast($collection)
+ public function testTakeLast($collection): void
{
$data = new $collection(['taylor', 'dayle', 'shawn']);
$data = $data->take(-2);
@@ -2789,7 +2779,7 @@ public function testTakeLast($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTakeUntilUsingValue($collection)
+ public function testTakeUntilUsingValue($collection): void
{
$data = new $collection([1, 2, 3, 4]);
@@ -2799,7 +2789,7 @@ public function testTakeUntilUsingValue($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTakeUntilUsingCallback($collection)
+ public function testTakeUntilUsingCallback($collection): void
{
$data = new $collection([1, 2, 3, 4]);
@@ -2811,7 +2801,7 @@ public function testTakeUntilUsingCallback($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTakeUntilReturnsAllItemsForUnmetValue($collection)
+ public function testTakeUntilReturnsAllItemsForUnmetValue($collection): void
{
$data = new $collection([1, 2, 3, 4]);
@@ -2827,7 +2817,7 @@ public function testTakeUntilReturnsAllItemsForUnmetValue($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTakeUntilCanBeProxied($collection)
+ public function testTakeUntilCanBeProxied($collection): void
{
$data = new $collection([
new TestSupportCollectionHigherOrderItem('Adam'),
@@ -2843,7 +2833,7 @@ public function testTakeUntilCanBeProxied($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTakeWhileUsingValue($collection)
+ public function testTakeWhileUsingValue($collection): void
{
$data = new $collection([1, 1, 2, 2, 3, 3]);
@@ -2853,7 +2843,7 @@ public function testTakeWhileUsingValue($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTakeWhileUsingCallback($collection)
+ public function testTakeWhileUsingCallback($collection): void
{
$data = new $collection([1, 2, 3, 4]);
@@ -2865,7 +2855,7 @@ public function testTakeWhileUsingCallback($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTakeWhileReturnsNoItemsForUnmetValue($collection)
+ public function testTakeWhileReturnsNoItemsForUnmetValue($collection): void
{
$data = new $collection([1, 2, 3, 4]);
@@ -2881,7 +2871,7 @@ public function testTakeWhileReturnsNoItemsForUnmetValue($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTakeWhileCanBeProxied($collection)
+ public function testTakeWhileCanBeProxied($collection): void
{
$data = new $collection([
new TestSupportCollectionHigherOrderItem('Adam'),
@@ -2898,7 +2888,7 @@ public function testTakeWhileCanBeProxied($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMacroable($collection)
+ public function testMacroable($collection): void
{
// Foo() macro : unique values starting with A
$collection::macro('foo', function () {
@@ -2915,7 +2905,7 @@ public function testMacroable($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCanAddMethodsToProxy($collection)
+ public function testCanAddMethodsToProxy($collection): void
{
$collection::macro('adults', function ($callback) {
return $this->filter(function ($item) use ($callback) {
@@ -2931,14 +2921,14 @@ public function testCanAddMethodsToProxy($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMakeMethod($collection)
+ public function testMakeMethod($collection): void
{
$data = $collection::make('foo');
$this->assertEquals(['foo'], $data->all());
}
#[DataProvider('collectionClassProvider')]
- public function testMakeMethodFromNull($collection)
+ public function testMakeMethodFromNull($collection): void
{
$data = $collection::make(null);
$this->assertEquals([], $data->all());
@@ -2948,7 +2938,7 @@ public function testMakeMethodFromNull($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMakeMethodFromCollection($collection)
+ public function testMakeMethodFromCollection($collection): void
{
$firstCollection = $collection::make(['foo' => 'bar']);
$secondCollection = $collection::make($firstCollection);
@@ -2956,56 +2946,56 @@ public function testMakeMethodFromCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMakeMethodFromArray($collection)
+ public function testMakeMethodFromArray($collection): void
{
$data = $collection::make(['foo' => 'bar']);
$this->assertEquals(['foo' => 'bar'], $data->all());
}
#[DataProvider('collectionClassProvider')]
- public function testWrapWithScalar($collection)
+ public function testWrapWithScalar($collection): void
{
$data = $collection::wrap('foo');
$this->assertEquals(['foo'], $data->all());
}
#[DataProvider('collectionClassProvider')]
- public function testWrapWithArray($collection)
+ public function testWrapWithArray($collection): void
{
$data = $collection::wrap(['foo']);
$this->assertEquals(['foo'], $data->all());
}
#[DataProvider('collectionClassProvider')]
- public function testWrapWithArrayable($collection)
+ public function testWrapWithArrayable($collection): void
{
$data = $collection::wrap($o = new TestArrayableObject);
$this->assertEquals([$o], $data->all());
}
#[DataProvider('collectionClassProvider')]
- public function testWrapWithJsonable($collection)
+ public function testWrapWithJsonable($collection): void
{
$data = $collection::wrap($o = new TestJsonableObject);
$this->assertEquals([$o], $data->all());
}
#[DataProvider('collectionClassProvider')]
- public function testWrapWithJsonSerialize($collection)
+ public function testWrapWithJsonSerialize($collection): void
{
$data = $collection::wrap($o = new TestJsonSerializeObject);
$this->assertEquals([$o], $data->all());
}
#[DataProvider('collectionClassProvider')]
- public function testWrapWithCollectionClass($collection)
+ public function testWrapWithCollectionClass($collection): void
{
$data = $collection::wrap($collection::make(['foo']));
$this->assertEquals(['foo'], $data->all());
}
#[DataProvider('collectionClassProvider')]
- public function testWrapWithCollectionSubclass($collection)
+ public function testWrapWithCollectionSubclass($collection): void
{
$data = TestCollectionSubclass::wrap($collection::make(['foo']));
$this->assertEquals(['foo'], $data->all());
@@ -3013,26 +3003,26 @@ public function testWrapWithCollectionSubclass($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUnwrapCollection($collection)
+ public function testUnwrapCollection($collection): void
{
$data = new $collection(['foo']);
$this->assertEquals(['foo'], $collection::unwrap($data));
}
#[DataProvider('collectionClassProvider')]
- public function testUnwrapCollectionWithArray($collection)
+ public function testUnwrapCollectionWithArray($collection): void
{
$this->assertEquals(['foo'], $collection::unwrap(['foo']));
}
#[DataProvider('collectionClassProvider')]
- public function testUnwrapCollectionWithScalar($collection)
+ public function testUnwrapCollectionWithScalar($collection): void
{
$this->assertSame('foo', $collection::unwrap('foo'));
}
#[DataProvider('collectionClassProvider')]
- public function testEmptyMethod($collection)
+ public function testEmptyMethod($collection): void
{
$collection = $collection::empty();
@@ -3040,7 +3030,7 @@ public function testEmptyMethod($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTimesMethod($collection)
+ public function testTimesMethod($collection): void
{
$two = $collection::times(2, function ($number) {
return 'slug-' . $number;
@@ -3063,7 +3053,7 @@ public function testTimesMethod($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testRangeMethod($collection)
+ public function testRangeMethod($collection): void
{
$this->assertSame(
[1, 2, 3, 4, 5],
@@ -3097,7 +3087,7 @@ public function testRangeMethod($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFromJson($collection)
+ public function testFromJson($collection): void
{
$json = json_encode($array = ['foo' => 'bar', 'baz' => 'quz']);
@@ -3107,7 +3097,7 @@ public function testFromJson($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFromJsonWithDepth($collection)
+ public function testFromJsonWithDepth($collection): void
{
$json = json_encode(['foo' => ['baz' => ['quz']], 'bar' => 'baz']);
@@ -3118,7 +3108,7 @@ public function testFromJsonWithDepth($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFromJsonWithFlags($collection)
+ public function testFromJsonWithFlags($collection): void
{
$instance = $collection::fromJson('{"int":99999999999999999999999}', 512, JSON_BIGINT_AS_STRING);
@@ -3126,7 +3116,7 @@ public function testFromJsonWithFlags($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testConstructMakeFromObject($collection)
+ public function testConstructMakeFromObject($collection): void
{
$object = new stdClass;
$object->foo = 'bar';
@@ -3135,14 +3125,14 @@ public function testConstructMakeFromObject($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testConstructMethod($collection)
+ public function testConstructMethod($collection): void
{
$data = new $collection('foo');
$this->assertEquals(['foo'], $data->all());
}
#[DataProvider('collectionClassProvider')]
- public function testConstructMethodFromNull($collection)
+ public function testConstructMethodFromNull($collection): void
{
$data = new $collection(null);
$this->assertEquals([], $data->all());
@@ -3152,7 +3142,7 @@ public function testConstructMethodFromNull($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testConstructMethodFromCollection($collection)
+ public function testConstructMethodFromCollection($collection): void
{
$firstCollection = new $collection(['foo' => 'bar']);
$secondCollection = new $collection($firstCollection);
@@ -3160,14 +3150,14 @@ public function testConstructMethodFromCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testConstructMethodFromArray($collection)
+ public function testConstructMethodFromArray($collection): void
{
$data = new $collection(['foo' => 'bar']);
$this->assertEquals(['foo' => 'bar'], $data->all());
}
#[DataProvider('collectionClassProvider')]
- public function testConstructMethodFromObject($collection)
+ public function testConstructMethodFromObject($collection): void
{
$object = new stdClass;
$object->foo = 'bar';
@@ -3176,7 +3166,7 @@ public function testConstructMethodFromObject($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testConstructMethodFromWeakMap($collection)
+ public function testConstructMethodFromWeakMap($collection): void
{
$map = new WeakMap;
$object = new stdClass;
@@ -3186,7 +3176,7 @@ public function testConstructMethodFromWeakMap($collection)
$this->assertEquals([3], $data->all());
}
- public function testSplice()
+ public function testSplice(): void
{
$data = new Collection(['foo', 'baz']);
$data->splice(1);
@@ -3215,7 +3205,7 @@ public function testSplice()
}
#[DataProvider('collectionClassProvider')]
- public function testGetPluckValueWithAccessors($collection)
+ public function testGetPluckValueWithAccessors($collection): void
{
$model = new TestAccessorEloquentTestStub(['some' => 'foo']);
$modelTwo = new TestAccessorEloquentTestStub(['some' => 'bar']);
@@ -3225,7 +3215,7 @@ public function testGetPluckValueWithAccessors($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMap($collection)
+ public function testMap($collection): void
{
$data = new $collection([1, 2, 3]);
$mapped = $data->map(function ($item, $key) {
@@ -3242,7 +3232,7 @@ public function testMap($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapSpread($collection)
+ public function testMapSpread($collection): void
{
$c = new $collection([[1, 'a'], [2, 'b']]);
@@ -3264,7 +3254,7 @@ public function testMapSpread($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testFlatMap($collection)
+ public function testFlatMap($collection): void
{
$data = new $collection([
['name' => 'taylor', 'hobbies' => ['programming', 'basketball']],
@@ -3277,7 +3267,7 @@ public function testFlatMap($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapToDictionary($collection)
+ public function testMapToDictionary($collection): void
{
$data = new $collection([
['id' => 1, 'name' => 'A'],
@@ -3296,7 +3286,7 @@ public function testMapToDictionary($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapToDictionaryWithNumericKeys($collection)
+ public function testMapToDictionaryWithNumericKeys($collection): void
{
$data = new $collection([1, 2, 3, 2, 1]);
@@ -3308,7 +3298,7 @@ public function testMapToDictionaryWithNumericKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapToGroups($collection)
+ public function testMapToGroups($collection): void
{
$data = new $collection([
['id' => 1, 'name' => 'A'],
@@ -3327,7 +3317,7 @@ public function testMapToGroups($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapToGroupsWithNumericKeys($collection)
+ public function testMapToGroupsWithNumericKeys($collection): void
{
$data = new $collection([1, 2, 3, 2, 1]);
@@ -3340,7 +3330,7 @@ public function testMapToGroupsWithNumericKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapWithKeys($collection)
+ public function testMapWithKeys($collection): void
{
$data = new $collection([
['name' => 'Blastoise', 'type' => 'Water', 'idx' => 9],
@@ -3357,7 +3347,7 @@ public function testMapWithKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapWithKeysIntegerKeys($collection)
+ public function testMapWithKeysIntegerKeys($collection): void
{
$data = new $collection([
['id' => 1, 'name' => 'A'],
@@ -3374,7 +3364,7 @@ public function testMapWithKeysIntegerKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapWithKeysMultipleRows($collection)
+ public function testMapWithKeysMultipleRows($collection): void
{
$data = new $collection([
['id' => 1, 'name' => 'A'],
@@ -3398,7 +3388,7 @@ public function testMapWithKeysMultipleRows($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapWithKeysCallbackKey($collection)
+ public function testMapWithKeysCallbackKey($collection): void
{
$data = new $collection([
3 => ['id' => 1, 'name' => 'A'],
@@ -3415,7 +3405,7 @@ public function testMapWithKeysCallbackKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapInto($collection)
+ public function testMapInto($collection): void
{
$data = new $collection([
'first', 'second',
@@ -3428,7 +3418,7 @@ public function testMapInto($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapIntoWithIntBackedEnums($collection)
+ public function testMapIntoWithIntBackedEnums($collection): void
{
$data = new $collection([
1, 2,
@@ -3441,7 +3431,7 @@ public function testMapIntoWithIntBackedEnums($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapIntoWithStringBackedEnums($collection)
+ public function testMapIntoWithStringBackedEnums($collection): void
{
$data = new $collection([
'A', 'B',
@@ -3454,7 +3444,7 @@ public function testMapIntoWithStringBackedEnums($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testNth($collection)
+ public function testNth($collection): void
{
$data = new $collection([
6 => 'a',
@@ -3479,7 +3469,7 @@ public function testNth($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testNthThrowsExceptionForInvalidStep($collection)
+ public function testNthThrowsExceptionForInvalidStep($collection): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Step value must be at least 1.');
@@ -3488,7 +3478,7 @@ public function testNthThrowsExceptionForInvalidStep($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testNthThrowsExceptionForNegativeStep($collection)
+ public function testNthThrowsExceptionForNegativeStep($collection): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Step value must be at least 1.');
@@ -3497,7 +3487,7 @@ public function testNthThrowsExceptionForNegativeStep($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitThrowsExceptionForInvalidNumberOfGroups($collection)
+ public function testSplitThrowsExceptionForInvalidNumberOfGroups($collection): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Number of groups must be at least 1.');
@@ -3506,7 +3496,7 @@ public function testSplitThrowsExceptionForInvalidNumberOfGroups($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitThrowsExceptionForNegativeNumberOfGroups($collection)
+ public function testSplitThrowsExceptionForNegativeNumberOfGroups($collection): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Number of groups must be at least 1.');
@@ -3515,7 +3505,7 @@ public function testSplitThrowsExceptionForNegativeNumberOfGroups($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitInThrowsExceptionForInvalidNumberOfGroups($collection)
+ public function testSplitInThrowsExceptionForInvalidNumberOfGroups($collection): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Number of groups must be at least 1.');
@@ -3524,7 +3514,7 @@ public function testSplitInThrowsExceptionForInvalidNumberOfGroups($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitInThrowsExceptionForNegativeNumberOfGroups($collection)
+ public function testSplitInThrowsExceptionForNegativeNumberOfGroups($collection): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Number of groups must be at least 1.');
@@ -3533,7 +3523,7 @@ public function testSplitInThrowsExceptionForNegativeNumberOfGroups($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMapWithKeysOverwritingKeys($collection)
+ public function testMapWithKeysOverwritingKeys($collection): void
{
$data = new $collection([
['id' => 1, 'name' => 'A'],
@@ -3552,7 +3542,7 @@ public function testMapWithKeysOverwritingKeys($collection)
);
}
- public function testTransform()
+ public function testTransform(): void
{
$data = new Collection(['first' => 'taylor', 'last' => 'otwell']);
$data->transform(function ($item, $key) {
@@ -3562,7 +3552,7 @@ public function testTransform()
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByAttribute($collection)
+ public function testGroupByAttribute($collection): void
{
$data = new $collection([['rating' => 1, 'url' => '1'], ['rating' => 1, 'url' => '1'], ['rating' => 2, 'url' => '2']]);
@@ -3574,7 +3564,7 @@ public function testGroupByAttribute($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByAttributeWithStringableKey($collection)
+ public function testGroupByAttributeWithStringableKey($collection): void
{
$data = new $collection($payload = [
['name' => new Stringable('Laravel'), 'url' => '1'],
@@ -3595,7 +3585,7 @@ public function __toString()
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByAttributeWithEnumKey($collection)
+ public function testGroupByAttributeWithEnumKey($collection): void
{
$data = new $collection($payload = [
['name' => TestEnum::A, 'url' => '1'],
@@ -3611,7 +3601,7 @@ public function testGroupByAttributeWithEnumKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByCallable($collection)
+ public function testGroupByCallable($collection): void
{
$data = new $collection([['rating' => 1, 'url' => '1'], ['rating' => 1, 'url' => '1'], ['rating' => 2, 'url' => '2']]);
@@ -3622,18 +3612,18 @@ public function testGroupByCallable($collection)
$this->assertEquals([1 => [['rating' => 1, 'url' => '1'], ['rating' => 1, 'url' => '1']], 2 => [['rating' => 2, 'url' => '2']]], $result->toArray());
}
- public function sortByRating(array $value)
+ public function sortByRating(array $value): int
{
return $value['rating'];
}
- public function sortByUrl(array $value)
+ public function sortByUrl(array $value): string
{
return $value['url'];
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByAttributeWithBackedEnumKey($collection)
+ public function testGroupByAttributeWithBackedEnumKey($collection): void
{
$data = new $collection([
['rating' => TestBackedEnum::A, 'url' => '1'],
@@ -3645,7 +3635,7 @@ public function testGroupByAttributeWithBackedEnumKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByAttributePreservingKeys($collection)
+ public function testGroupByAttributePreservingKeys($collection): void
{
$data = new $collection([10 => ['rating' => 1, 'url' => '1'], 20 => ['rating' => 1, 'url' => '1'], 30 => ['rating' => 2, 'url' => '2']]);
@@ -3660,7 +3650,7 @@ public function testGroupByAttributePreservingKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByClosureWhereItemsHaveSingleGroup($collection)
+ public function testGroupByClosureWhereItemsHaveSingleGroup($collection): void
{
$data = new $collection([['rating' => 1, 'url' => '1'], ['rating' => 1, 'url' => '1'], ['rating' => 2, 'url' => '2']]);
@@ -3672,7 +3662,7 @@ public function testGroupByClosureWhereItemsHaveSingleGroup($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByClosureWhereItemsHaveSingleGroupPreservingKeys($collection)
+ public function testGroupByClosureWhereItemsHaveSingleGroupPreservingKeys($collection): void
{
$data = new $collection([10 => ['rating' => 1, 'url' => '1'], 20 => ['rating' => 1, 'url' => '1'], 30 => ['rating' => 2, 'url' => '2']]);
@@ -3689,7 +3679,7 @@ public function testGroupByClosureWhereItemsHaveSingleGroupPreservingKeys($colle
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByClosureWhereItemsHaveMultipleGroups($collection)
+ public function testGroupByClosureWhereItemsHaveMultipleGroups($collection): void
{
$data = new $collection([
['user' => 1, 'roles' => ['Role_1', 'Role_3']],
@@ -3719,7 +3709,7 @@ public function testGroupByClosureWhereItemsHaveMultipleGroups($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByClosureWhereItemsHaveMultipleGroupsPreservingKeys($collection)
+ public function testGroupByClosureWhereItemsHaveMultipleGroupsPreservingKeys($collection): void
{
$data = new $collection([
10 => ['user' => 1, 'roles' => ['Role_1', 'Role_3']],
@@ -3749,7 +3739,7 @@ public function testGroupByClosureWhereItemsHaveMultipleGroupsPreservingKeys($co
}
#[DataProvider('collectionClassProvider')]
- public function testGroupByMultiLevelAndClosurePreservingKeys($collection)
+ public function testGroupByMultiLevelAndClosurePreservingKeys($collection): void
{
$data = new $collection([
10 => ['user' => 1, 'skilllevel' => 1, 'roles' => ['Role_1', 'Role_3']],
@@ -3792,7 +3782,7 @@ function ($item) {
}
#[DataProvider('collectionClassProvider')]
- public function testKeyByAttribute($collection)
+ public function testKeyByAttribute($collection): void
{
$data = new $collection([['rating' => 1, 'name' => '1'], ['rating' => 2, 'name' => '2'], ['rating' => 3, 'name' => '3']]);
@@ -3806,7 +3796,21 @@ public function testKeyByAttribute($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testKeyByClosure($collection)
+ public function testKeyByBackedEnum($collection): void
+ {
+ $data = new $collection([
+ ['id' => 1, 'status' => TestStringBackedEnum::A],
+ ['id' => 2, 'status' => TestStringBackedEnum::B],
+ ]);
+
+ $this->assertEquals([
+ TestStringBackedEnum::A->value => ['id' => 1, 'status' => TestStringBackedEnum::A],
+ TestStringBackedEnum::B->value => ['id' => 2, 'status' => TestStringBackedEnum::B],
+ ], $data->keyBy('status')->all());
+ }
+
+ #[DataProvider('collectionClassProvider')]
+ public function testKeyByClosure($collection): void
{
$data = new $collection([
['firstname' => 'Taylor', 'lastname' => 'Otwell', 'locale' => 'US'],
@@ -3822,7 +3826,7 @@ public function testKeyByClosure($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testKeyByObject($collection)
+ public function testKeyByObject($collection): void
{
$data = new $collection([
['firstname' => 'Taylor', 'lastname' => 'Otwell', 'locale' => 'US'],
@@ -3838,7 +3842,7 @@ public function testKeyByObject($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testContains($collection)
+ public function testContains($collection): void
{
$c = new $collection([1, 3, 5]);
@@ -3897,7 +3901,7 @@ public function testContains($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDoesntContain($collection)
+ public function testDoesntContain($collection): void
{
$c = new $collection([1, 3, 5]);
@@ -3956,7 +3960,7 @@ public function testDoesntContain($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDoesntContainStrict($collection)
+ public function testDoesntContainStrict($collection): void
{
$c = new $collection([1, 3, 5, '02']);
@@ -4004,7 +4008,7 @@ public function testDoesntContainStrict($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSome($collection)
+ public function testSome($collection): void
{
$c = new $collection([1, 3, 5]);
@@ -4043,7 +4047,7 @@ public function testSome($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testContainsStrict($collection)
+ public function testContainsStrict($collection): void
{
$c = new $collection([1, 3, 5, '02']);
@@ -4089,7 +4093,7 @@ public function testContainsStrict($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testContainsWithOperator($collection)
+ public function testContainsWithOperator($collection): void
{
$c = new $collection([['v' => 1], ['v' => 3], ['v' => '4'], ['v' => 5]]);
@@ -4100,7 +4104,7 @@ public function testContainsWithOperator($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGettingSumFromCollection($collection)
+ public function testGettingSumFromCollection($collection): void
{
$c = new $collection([(object) ['foo' => 50], (object) ['foo' => 50]]);
$this->assertEquals(100, $c->sum('foo'));
@@ -4112,21 +4116,21 @@ public function testGettingSumFromCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCanSumValuesWithoutACallback($collection)
+ public function testCanSumValuesWithoutACallback($collection): void
{
$c = new $collection([1, 2, 3, 4, 5]);
$this->assertEquals(15, $c->sum());
}
#[DataProvider('collectionClassProvider')]
- public function testGettingSumFromEmptyCollection($collection)
+ public function testGettingSumFromEmptyCollection($collection): void
{
$c = new $collection;
$this->assertEquals(0, $c->sum('foo'));
}
#[DataProvider('collectionClassProvider')]
- public function testValueRetrieverAcceptsDotNotation($collection)
+ public function testValueRetrieverAcceptsDotNotation($collection): void
{
$c = new $collection([
(object) ['id' => 1, 'foo' => ['bar' => 'B']], (object) ['id' => 2, 'foo' => ['bar' => 'A']],
@@ -4136,7 +4140,7 @@ public function testValueRetrieverAcceptsDotNotation($collection)
$this->assertEquals([2, 1], $c->pluck('id')->all());
}
- public function testPullRetrievesItemFromCollection()
+ public function testPullRetrievesItemFromCollection(): void
{
$c = new Collection(['foo', 'bar']);
@@ -4149,7 +4153,7 @@ public function testPullRetrievesItemFromCollection()
$this->assertNull($c->pull(2));
}
- public function testPullRemovesItemFromCollection()
+ public function testPullRemovesItemFromCollection(): void
{
$c = new Collection(['foo', 'bar']);
$c->pull(0);
@@ -4158,7 +4162,7 @@ public function testPullRemovesItemFromCollection()
$this->assertEquals([], $c->all());
}
- public function testPullRemovesItemFromNestedCollection()
+ public function testPullRemovesItemFromNestedCollection(): void
{
$nestedCollection = new Collection([
new Collection([
@@ -4185,7 +4189,7 @@ public function testPullRemovesItemFromNestedCollection()
$this->assertEquals($expectedArray, $actualArray);
}
- public function testPullReturnsDefault()
+ public function testPullReturnsDefault(): void
{
$c = new Collection([]);
$value = $c->pull(0, 'foo');
@@ -4193,7 +4197,7 @@ public function testPullReturnsDefault()
}
#[DataProvider('collectionClassProvider')]
- public function testRejectRemovesElementsPassingTruthTest($collection)
+ public function testRejectRemovesElementsPassingTruthTest($collection): void
{
$c = new $collection(['foo', 'bar']);
$this->assertEquals(['foo'], $c->reject('bar')->values()->all());
@@ -4221,7 +4225,7 @@ public function testRejectRemovesElementsPassingTruthTest($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testRejectWithoutAnArgumentRemovesTruthyValues($collection)
+ public function testRejectWithoutAnArgumentRemovesTruthyValues($collection): void
{
$data1 = new $collection([
false,
@@ -4242,7 +4246,7 @@ public function testRejectWithoutAnArgumentRemovesTruthyValues($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSearchReturnsIndexOfFirstFoundItem($collection)
+ public function testSearchReturnsIndexOfFirstFoundItem($collection): void
{
$c = new $collection([1, 2, 3, 4, 5, 2, 5, 'foo' => 'bar']);
@@ -4258,7 +4262,7 @@ public function testSearchReturnsIndexOfFirstFoundItem($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSearchInStrictMode($collection)
+ public function testSearchInStrictMode($collection): void
{
$c = new $collection([false, 0, 1, [], '']);
$this->assertFalse($c->search('false', true));
@@ -4271,7 +4275,7 @@ public function testSearchInStrictMode($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSearchReturnsFalseWhenItemIsNotFound($collection)
+ public function testSearchReturnsFalseWhenItemIsNotFound($collection): void
{
$c = new $collection([1, 2, 3, 4, 5, 'foo' => 'bar']);
@@ -4286,7 +4290,7 @@ public function testSearchReturnsFalseWhenItemIsNotFound($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testBeforeReturnsItemBeforeTheGivenItem($collection)
+ public function testBeforeReturnsItemBeforeTheGivenItem($collection): void
{
$c = new $collection([1, 2, 3, 4, 5, 2, 5, 'name' => 'taylor', 'framework' => 'laravel']);
@@ -4303,7 +4307,7 @@ public function testBeforeReturnsItemBeforeTheGivenItem($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testBeforeInStrictMode($collection)
+ public function testBeforeInStrictMode($collection): void
{
$c = new $collection([false, 0, 1, [], '']);
$this->assertNull($c->before('false', true));
@@ -4316,7 +4320,7 @@ public function testBeforeInStrictMode($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testBeforeReturnsNullWhenItemIsNotFound($collection)
+ public function testBeforeReturnsNullWhenItemIsNotFound($collection): void
{
$c = new $collection([1, 2, 3, 4, 5, 'foo' => 'bar']);
@@ -4331,7 +4335,7 @@ public function testBeforeReturnsNullWhenItemIsNotFound($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testBeforeReturnsNullWhenItemOnTheFirstitem($collection)
+ public function testBeforeReturnsNullWhenItemOnTheFirstitem($collection): void
{
$c = new $collection([1, 2, 3, 4, 5, 'foo' => 'bar']);
@@ -4345,7 +4349,7 @@ public function testBeforeReturnsNullWhenItemOnTheFirstitem($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testAfterReturnsItemAfterTheGivenItem($collection)
+ public function testAfterReturnsItemAfterTheGivenItem($collection): void
{
$c = new $collection([1, 2, 3, 4, 2, 5, 'name' => 'taylor', 'framework' => 'laravel']);
@@ -4365,7 +4369,7 @@ public function testAfterReturnsItemAfterTheGivenItem($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testAfterInStrictMode($collection)
+ public function testAfterInStrictMode($collection): void
{
$c = new $collection([false, 0, 1, [], '']);
@@ -4378,7 +4382,7 @@ public function testAfterInStrictMode($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testAfterReturnsNullWhenItemIsNotFound($collection)
+ public function testAfterReturnsNullWhenItemIsNotFound($collection): void
{
$c = new $collection([1, 2, 3, 4, 5, 'foo' => 'bar']);
@@ -4393,7 +4397,7 @@ public function testAfterReturnsNullWhenItemIsNotFound($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testAfterReturnsNullWhenItemOnTheLastItem($collection)
+ public function testAfterReturnsNullWhenItemOnTheLastItem($collection): void
{
$c = new $collection([1, 2, 3, 4, 5, 'foo' => 'bar']);
@@ -4407,7 +4411,7 @@ public function testAfterReturnsNullWhenItemOnTheLastItem($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testKeys($collection)
+ public function testKeys($collection): void
{
$c = new $collection(['name' => 'taylor', 'framework' => 'laravel']);
$this->assertEquals(['name', 'framework'], $c->keys()->all());
@@ -4417,7 +4421,7 @@ public function testKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPaginate($collection)
+ public function testPaginate($collection): void
{
$c = new $collection(['one', 'two', 'three', 'four']);
$this->assertEquals(['one', 'two'], $c->forPage(0, 2)->all());
@@ -4427,7 +4431,7 @@ public function testPaginate($collection)
}
#[IgnoreDeprecations]
- public function testPrepend()
+ public function testPrepend(): void
{
$c = new Collection(['one', 'two', 'three', 'four']);
$this->assertEquals(
@@ -4454,7 +4458,7 @@ public function testPrepend()
);
}
- public function testPushWithOneItem()
+ public function testPushWithOneItem(): void
{
$expected = [
0 => 4,
@@ -4473,7 +4477,7 @@ public function testPushWithOneItem()
$this->assertSame($expected, $actual);
}
- public function testPushWithMultipleItems()
+ public function testPushWithMultipleItems(): void
{
$expected = [
0 => 4,
@@ -4499,7 +4503,7 @@ public function testPushWithMultipleItems()
$this->assertSame($expected, $actual);
}
- public function testUnshiftWithOneItem()
+ public function testUnshiftWithOneItem(): void
{
$expected = [
0 => 'Jonny from Laroe',
@@ -4518,7 +4522,7 @@ public function testUnshiftWithOneItem()
$this->assertSame($expected, $actual);
}
- public function testUnshiftWithMultipleItems()
+ public function testUnshiftWithMultipleItems(): void
{
$expected = [
0 => 'a',
@@ -4545,7 +4549,7 @@ public function testUnshiftWithMultipleItems()
}
#[DataProvider('collectionClassProvider')]
- public function testZip($collection)
+ public function testZip($collection): void
{
$c = new $collection([1, 2, 3]);
$c = $c->zip(new $collection([4, 5, 6]));
@@ -4574,7 +4578,7 @@ public function testZip($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPadPadsArrayWithValue($collection)
+ public function testPadPadsArrayWithValue($collection): void
{
$c = new $collection([1, 2, 3]);
$c = $c->pad(4, 0);
@@ -4594,7 +4598,7 @@ public function testPadPadsArrayWithValue($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGettingMaxItemsFromCollection($collection)
+ public function testGettingMaxItemsFromCollection($collection): void
{
$c = new $collection([(object) ['foo' => 10], (object) ['foo' => 20]]);
$this->assertEquals(20, $c->max(function ($item) {
@@ -4615,7 +4619,7 @@ public function testGettingMaxItemsFromCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGettingMinItemsFromCollection($collection)
+ public function testGettingMinItemsFromCollection($collection): void
{
$c = new $collection([(object) ['foo' => 10], (object) ['foo' => 20]]);
$this->assertEquals(10, $c->min(function ($item) {
@@ -4646,7 +4650,7 @@ public function testGettingMinItemsFromCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testOnly($collection)
+ public function testOnly($collection): void
{
$data = new $collection(['first' => 'Taylor', 'last' => 'Otwell', 'email' => 'taylorotwell@gmail.com']);
@@ -4661,7 +4665,7 @@ public function testOnly($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSelectWithArrays($collection)
+ public function testSelectWithArrays($collection): void
{
$data = new $collection([
['first' => 'Taylor', 'last' => 'Otwell', 'email' => 'taylorotwell@gmail.com'],
@@ -4690,7 +4694,7 @@ public function testSelectWithArrays($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSelectWithArrayAccess($collection)
+ public function testSelectWithArrayAccess($collection): void
{
$data = new $collection([
new TestArrayAccessImplementation(['first' => 'Taylor', 'last' => 'Otwell', 'email' => 'taylorotwell@gmail.com']),
@@ -4719,7 +4723,7 @@ public function testSelectWithArrayAccess($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSelectWithObjects($collection)
+ public function testSelectWithObjects($collection): void
{
$data = new $collection([
(object) ['first' => 'Taylor', 'last' => 'Otwell', 'email' => 'taylorotwell@gmail.com'],
@@ -4748,7 +4752,7 @@ public function testSelectWithObjects($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testGettingAvgItemsFromCollection($collection)
+ public function testGettingAvgItemsFromCollection($collection): void
{
$c = new $collection([(object) ['foo' => 10], (object) ['foo' => 20]]);
$this->assertEquals(15, $c->avg(function ($item) {
@@ -4793,7 +4797,7 @@ public function testGettingAvgItemsFromCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testJsonSerialize($collection)
+ public function testJsonSerialize($collection): void
{
$c = new $collection([
new TestArrayableObject,
@@ -4813,7 +4817,7 @@ public function testJsonSerialize($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCombineWithArray($collection)
+ public function testCombineWithArray($collection): void
{
$c = new $collection([1, 2, 3]);
$actual = $c->combine([4, 5, 6])->toArray();
@@ -4854,7 +4858,7 @@ public function testCombineWithArray($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCombineWithCollection($collection)
+ public function testCombineWithCollection($collection): void
{
$expected = [
1 => 4,
@@ -4870,7 +4874,7 @@ public function testCombineWithCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testConcatWithArray($collection)
+ public function testConcatWithArray($collection): void
{
$expected = [
0 => 4,
@@ -4896,7 +4900,7 @@ public function testConcatWithArray($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testConcatWithCollection($collection)
+ public function testConcatWithCollection($collection): void
{
$expected = [
0 => 4,
@@ -4924,7 +4928,7 @@ public function testConcatWithCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDump($collection)
+ public function testDump($collection): void
{
$log = new Collection;
@@ -4940,7 +4944,7 @@ public function testDump($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testReduce($collection)
+ public function testReduce($collection): void
{
$data = new $collection([1, 2, 3]);
$this->assertEquals(6, $data->reduce(function ($carry, $element) {
@@ -4957,7 +4961,43 @@ public function testReduce($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testReduceSpread($collection)
+ public function testReduceInto($collection): void
+ {
+ $data = new $collection([1, 2, 3]);
+ $this->assertSame(6, $data->reduceInto(0, function (&$result, $element): void {
+ $result += $element;
+ }));
+
+ $data = new $collection([
+ 'foo' => 'bar',
+ 'baz' => 'qux',
+ ]);
+ $this->assertSame('foobarbazqux', $data->reduceInto('', function (&$result, $element, $key): void {
+ $result .= $key . $element;
+ }));
+
+ $data = new $collection([1, 2, 3, 4, 5]);
+ $result = $data->reduceInto([], function (&$result, $value): void {
+ if ($value % 2 === 0) {
+ $result[] = $value;
+ }
+ });
+
+ $this->assertSame([2, 4], $result);
+ }
+
+ #[DataProvider('collectionClassProvider')]
+ public function testSumPassesItemKeysToTheCallback($collection): void
+ {
+ $data = new $collection(['first' => 10, 'second' => 20]);
+
+ $this->assertSame(31, $data->sum(
+ static fn (int $value, string $key): int => $value + ($key === 'first' ? 1 : 0),
+ ));
+ }
+
+ #[DataProvider('collectionClassProvider')]
+ public function testReduceSpread($collection): void
{
$data = new $collection([-1, 0, 1, 2, 3, 4, 5]);
@@ -4975,7 +5015,7 @@ public function testReduceSpread($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testReduceSpreadThrowsAnExceptionIfReducerDoesNotReturnAnArray($collection)
+ public function testReduceSpreadThrowsAnExceptionIfReducerDoesNotReturnAnArray($collection): void
{
$data = new $collection([1]);
@@ -4987,7 +5027,7 @@ public function testReduceSpreadThrowsAnExceptionIfReducerDoesNotReturnAnArray($
}
#[DataProvider('collectionClassProvider')]
- public function testRandomThrowsAnExceptionUsingAmountBiggerThanCollectionSize($collection)
+ public function testRandomThrowsAnExceptionUsingAmountBiggerThanCollectionSize($collection): void
{
$this->expectException(InvalidArgumentException::class);
@@ -4996,7 +5036,7 @@ public function testRandomThrowsAnExceptionUsingAmountBiggerThanCollectionSize($
}
#[DataProvider('collectionClassProvider')]
- public function testPipe($collection)
+ public function testPipe($collection): void
{
$data = new $collection([1, 2, 3]);
@@ -5006,7 +5046,7 @@ public function testPipe($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPipeInto($collection)
+ public function testPipeInto($collection): void
{
$data = new $collection([
'first', 'second',
@@ -5018,7 +5058,7 @@ public function testPipeInto($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPipeThrough($collection)
+ public function testPipeThrough($collection): void
{
$data = new $collection([1, 2, 3]);
@@ -5035,7 +5075,7 @@ function ($data) {
}
#[DataProvider('collectionClassProvider')]
- public function testMedianValueWithArrayCollection($collection)
+ public function testMedianValueWithArrayCollection($collection): void
{
$data = new $collection([1, 2, 2, 4]);
@@ -5043,7 +5083,7 @@ public function testMedianValueWithArrayCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMedianValueByKey($collection)
+ public function testMedianValueByKey($collection): void
{
$data = new $collection([
(object) ['foo' => 1],
@@ -5055,7 +5095,7 @@ public function testMedianValueByKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMedianOnCollectionWithNull($collection)
+ public function testMedianOnCollectionWithNull($collection): void
{
$data = new $collection([
(object) ['foo' => 1],
@@ -5067,7 +5107,7 @@ public function testMedianOnCollectionWithNull($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testEvenMedianCollection($collection)
+ public function testEvenMedianCollection($collection): void
{
$data = new $collection([
(object) ['foo' => 0],
@@ -5077,7 +5117,7 @@ public function testEvenMedianCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMedianOutOfOrderCollection($collection)
+ public function testMedianOutOfOrderCollection($collection): void
{
$data = new $collection([
(object) ['foo' => 0],
@@ -5088,21 +5128,21 @@ public function testMedianOutOfOrderCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testMedianOnEmptyCollectionReturnsNull($collection)
+ public function testMedianOnEmptyCollectionReturnsNull($collection): void
{
$data = new $collection;
$this->assertNull($data->median());
}
#[DataProvider('collectionClassProvider')]
- public function testModeOnNullCollection($collection)
+ public function testModeOnNullCollection($collection): void
{
$data = new $collection;
$this->assertNull($data->mode());
}
#[DataProvider('collectionClassProvider')]
- public function testMode($collection)
+ public function testMode($collection): void
{
$data = new $collection([1, 2, 3, 4, 4, 5]);
$this->assertIsArray($data->mode());
@@ -5110,7 +5150,7 @@ public function testMode($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testModeValueByKey($collection)
+ public function testModeValueByKey($collection): void
{
$data = new $collection([
(object) ['foo' => 1],
@@ -5129,84 +5169,84 @@ public function testModeValueByKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWithMultipleModeValues($collection)
+ public function testWithMultipleModeValues($collection): void
{
$data = new $collection([1, 2, 2, 1]);
$this->assertEquals([1, 2], $data->mode());
}
#[DataProvider('collectionClassProvider')]
- public function testSliceOffset($collection)
+ public function testSliceOffset($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6, 7, 8]);
$this->assertEquals([4, 5, 6, 7, 8], $data->slice(3)->values()->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testSliceNegativeOffset($collection)
+ public function testSliceNegativeOffset($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6, 7, 8]);
$this->assertEquals([6, 7, 8], $data->slice(-3)->values()->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testSliceOffsetAndLength($collection)
+ public function testSliceOffsetAndLength($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6, 7, 8]);
$this->assertEquals([4, 5, 6], $data->slice(3, 3)->values()->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testSliceOffsetAndNegativeLength($collection)
+ public function testSliceOffsetAndNegativeLength($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6, 7, 8]);
$this->assertEquals([4, 5, 6, 7], $data->slice(3, -1)->values()->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testSliceNegativeOffsetAndLength($collection)
+ public function testSliceNegativeOffsetAndLength($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6, 7, 8]);
$this->assertEquals([4, 5, 6], $data->slice(-5, 3)->values()->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testSliceNegativeOffsetAndNegativeLength($collection)
+ public function testSliceNegativeOffsetAndNegativeLength($collection): void
{
$data = new $collection([1, 2, 3, 4, 5, 6, 7, 8]);
$this->assertEquals([3, 4, 5, 6], $data->slice(-6, -2)->values()->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testCollectionFromTraversable($collection)
+ public function testCollectionFromTraversable($collection): void
{
$data = new $collection(new ArrayObject([1, 2, 3]));
$this->assertEquals([1, 2, 3], $data->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testCollectionFromTraversableWithKeys($collection)
+ public function testCollectionFromTraversableWithKeys($collection): void
{
$data = new $collection(new ArrayObject(['foo' => 1, 'bar' => 2, 'baz' => 3]));
$this->assertEquals(['foo' => 1, 'bar' => 2, 'baz' => 3], $data->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testCollectionFromEnum($collection)
+ public function testCollectionFromEnum($collection): void
{
$data = new $collection(TestEnum::A);
$this->assertEquals([TestEnum::A], $data->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testCollectionFromBackedEnum($collection)
+ public function testCollectionFromBackedEnum($collection): void
{
$data = new $collection(TestBackedEnum::A);
$this->assertEquals([TestBackedEnum::A], $data->toArray());
}
#[DataProvider('collectionClassProvider')]
- public function testSplitCollectionWithADivisibleCount($collection)
+ public function testSplitCollectionWithADivisibleCount($collection): void
{
$data = new $collection(['a', 'b', 'c', 'd']);
$split = $data->split(2);
@@ -5237,7 +5277,7 @@ public function testSplitCollectionWithADivisibleCount($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitCollectionWithAnUndivisableCount($collection)
+ public function testSplitCollectionWithAnUndivisableCount($collection): void
{
$data = new $collection(['a', 'b', 'c']);
$split = $data->split(2);
@@ -5254,7 +5294,7 @@ public function testSplitCollectionWithAnUndivisableCount($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitCollectionWithCountLessThenDivisor($collection)
+ public function testSplitCollectionWithCountLessThenDivisor($collection): void
{
$data = new $collection(['a']);
$split = $data->split(2);
@@ -5271,7 +5311,7 @@ public function testSplitCollectionWithCountLessThenDivisor($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitCollectionIntoThreeWithCountOfFour($collection)
+ public function testSplitCollectionIntoThreeWithCountOfFour($collection): void
{
$data = new $collection(['a', 'b', 'c', 'd']);
$split = $data->split(3);
@@ -5289,7 +5329,7 @@ public function testSplitCollectionIntoThreeWithCountOfFour($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitCollectionIntoThreeWithCountOfFive($collection)
+ public function testSplitCollectionIntoThreeWithCountOfFive($collection): void
{
$data = new $collection(['a', 'b', 'c', 'd', 'e']);
$split = $data->split(3);
@@ -5307,7 +5347,7 @@ public function testSplitCollectionIntoThreeWithCountOfFive($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitCollectionIntoSixWithCountOfTen($collection)
+ public function testSplitCollectionIntoSixWithCountOfTen($collection): void
{
$data = new $collection(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']);
$split = $data->split(6);
@@ -5328,7 +5368,7 @@ public function testSplitCollectionIntoSixWithCountOfTen($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testSplitEmptyCollection($collection)
+ public function testSplitEmptyCollection($collection): void
{
$data = new $collection;
$split = $data->split(2);
@@ -5345,7 +5385,7 @@ public function testSplitEmptyCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHigherOrderCollectionGroupBy($collection)
+ public function testHigherOrderCollectionGroupBy($collection): void
{
$data = new $collection([
new TestSupportCollectionHigherOrderItem,
@@ -5366,7 +5406,7 @@ public function testHigherOrderCollectionGroupBy($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHigherOrderCollectionMap($collection)
+ public function testHigherOrderCollectionMap($collection): void
{
$person1 = (object) ['name' => 'Taylor'];
$person2 = (object) ['name' => 'Yaz'];
@@ -5381,7 +5421,7 @@ public function testHigherOrderCollectionMap($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHigherOrderCollectionMapFromArrays($collection)
+ public function testHigherOrderCollectionMapFromArrays($collection): void
{
$person1 = ['name' => 'Taylor'];
$person2 = ['name' => 'Yaz'];
@@ -5396,7 +5436,7 @@ public function testHigherOrderCollectionMapFromArrays($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHigherOrderCollectionStaticCall($collection)
+ public function testHigherOrderCollectionStaticCall($collection): void
{
$class1 = TestSupportCollectionHigherOrderStaticClass1::class;
$class2 = TestSupportCollectionHigherOrderStaticClass2::class;
@@ -5409,7 +5449,7 @@ public function testHigherOrderCollectionStaticCall($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPartition($collection)
+ public function testPartition($collection): void
{
$data = new $collection(range(1, 10));
@@ -5422,7 +5462,7 @@ public function testPartition($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPartitionCallbackWithKey($collection)
+ public function testPartitionCallbackWithKey($collection): void
{
$data = new $collection(['zero', 'one', 'two', 'three']);
@@ -5435,7 +5475,7 @@ public function testPartitionCallbackWithKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPartitionByKey($collection)
+ public function testPartitionByKey($collection): void
{
$courses = new $collection([
['free' => true, 'title' => 'Basic'], ['free' => false, 'title' => 'Premium'],
@@ -5448,7 +5488,7 @@ public function testPartitionByKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPartitionWithOperators($collection)
+ public function testPartitionWithOperators($collection): void
{
$data = new $collection([
['name' => 'Tim', 'age' => 17],
@@ -5483,7 +5523,7 @@ public function testPartitionWithOperators($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPartitionPreservesKeys($collection)
+ public function testPartitionPreservesKeys($collection): void
{
$courses = new $collection([
'a' => ['free' => true], 'b' => ['free' => false], 'c' => ['free' => true],
@@ -5496,7 +5536,7 @@ public function testPartitionPreservesKeys($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPartitionEmptyCollection($collection)
+ public function testPartitionEmptyCollection($collection): void
{
$data = new $collection;
@@ -5506,7 +5546,7 @@ public function testPartitionEmptyCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHigherOrderPartition($collection)
+ public function testHigherOrderPartition($collection): void
{
$courses = new $collection([
'a' => ['free' => true], 'b' => ['free' => false], 'c' => ['free' => true],
@@ -5520,7 +5560,7 @@ public function testHigherOrderPartition($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testTap($collection)
+ public function testTap($collection): void
{
$data = new $collection([1, 2, 3]);
@@ -5537,7 +5577,7 @@ public function testTap($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhen($collection)
+ public function testWhen($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5557,7 +5597,7 @@ public function testWhen($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhenDefault($collection)
+ public function testWhenDefault($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5571,7 +5611,7 @@ public function testWhenDefault($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhenEmpty($collection)
+ public function testWhenEmpty($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5591,7 +5631,7 @@ public function testWhenEmpty($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhenEmptyDefault($collection)
+ public function testWhenEmptyDefault($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5605,7 +5645,7 @@ public function testWhenEmptyDefault($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhenNotEmpty($collection)
+ public function testWhenNotEmpty($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5625,7 +5665,7 @@ public function testWhenNotEmpty($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhenNotEmptyDefault($collection)
+ public function testWhenNotEmptyDefault($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5639,7 +5679,7 @@ public function testWhenNotEmptyDefault($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHigherOrderWhenAndUnless($collection)
+ public function testHigherOrderWhenAndUnless($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5661,7 +5701,7 @@ public function testHigherOrderWhenAndUnless($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHigherOrderWhenAndUnlessWithProxy($collection)
+ public function testHigherOrderWhenAndUnlessWithProxy($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5683,7 +5723,7 @@ public function testHigherOrderWhenAndUnlessWithProxy($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUnless($collection)
+ public function testUnless($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5703,7 +5743,7 @@ public function testUnless($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUnlessDefault($collection)
+ public function testUnlessDefault($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5717,7 +5757,7 @@ public function testUnlessDefault($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUnlessEmpty($collection)
+ public function testUnlessEmpty($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5737,7 +5777,7 @@ public function testUnlessEmpty($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUnlessEmptyDefault($collection)
+ public function testUnlessEmptyDefault($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5751,7 +5791,7 @@ public function testUnlessEmptyDefault($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUnlessNotEmpty($collection)
+ public function testUnlessNotEmpty($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5771,7 +5811,7 @@ public function testUnlessNotEmpty($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUnlessNotEmptyDefault($collection)
+ public function testUnlessNotEmptyDefault($collection): void
{
$data = new $collection(['michael', 'tom']);
@@ -5785,7 +5825,7 @@ public function testUnlessNotEmptyDefault($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHasReturnsValidResults($collection)
+ public function testHasReturnsValidResults($collection): void
{
$data = new $collection(['foo' => 'one', 'bar' => 'two', 1 => 'three']);
$this->assertTrue($data->has('foo'));
@@ -5794,7 +5834,7 @@ public function testHasReturnsValidResults($collection)
$this->assertFalse($data->has('baz'));
}
- public function testPutAddsItemToCollection()
+ public function testPutAddsItemToCollection(): void
{
$data = new Collection;
$this->assertSame([], $data->toArray());
@@ -5807,7 +5847,7 @@ public function testPutAddsItemToCollection()
}
#[DataProvider('collectionClassProvider')]
- public function testItThrowsExceptionWhenTryingToAccessNoProxyProperty($collection)
+ public function testItThrowsExceptionWhenTryingToAccessNoProxyProperty($collection): void
{
$data = new $collection;
$this->expectException(Exception::class);
@@ -5816,21 +5856,21 @@ public function testItThrowsExceptionWhenTryingToAccessNoProxyProperty($collecti
}
#[DataProvider('collectionClassProvider')]
- public function testGetWithNullReturnsNull($collection)
+ public function testGetWithNullReturnsNull($collection): void
{
$data = new $collection([1, 2, 3]);
$this->assertNull($data->get(null));
}
#[DataProvider('collectionClassProvider')]
- public function testGetWithDefaultValue($collection)
+ public function testGetWithDefaultValue($collection): void
{
$data = new $collection(['name' => 'taylor', 'framework' => 'laravel']);
$this->assertEquals('34', $data->get('age', 34));
}
#[DataProvider('collectionClassProvider')]
- public function testGetWithCallbackAsDefaultValue($collection)
+ public function testGetWithCallbackAsDefaultValue($collection): void
{
$data = new $collection(['name' => 'taylor', 'framework' => 'laravel']);
$result = $data->get('email', function () {
@@ -5840,7 +5880,7 @@ public function testGetWithCallbackAsDefaultValue($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhereNull($collection)
+ public function testWhereNull($collection): void
{
$data = new $collection([
['name' => 'Taylor'],
@@ -5858,7 +5898,7 @@ public function testWhereNull($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhereNullWithoutKey($collection)
+ public function testWhereNullWithoutKey($collection): void
{
$collection = new $collection([1, null, 3, 'null', false, true]);
$this->assertSame([
@@ -5867,7 +5907,7 @@ public function testWhereNullWithoutKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhereNotNull($collection)
+ public function testWhereNotNull($collection): void
{
$data = new $collection($originalData = [
['name' => 'Taylor'],
@@ -5888,7 +5928,7 @@ public function testWhereNotNull($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testWhereNotNullWithoutKey($collection)
+ public function testWhereNotNullWithoutKey($collection): void
{
$data = new $collection([1, null, 3, 'null', false, true]);
@@ -5902,7 +5942,7 @@ public function testWhereNotNullWithoutKey($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testCollect($collection)
+ public function testCollect($collection): void
{
$data = $collection::make([
'a' => 1,
@@ -5920,7 +5960,7 @@ public function testCollect($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testUndot($collection)
+ public function testUndot($collection): void
{
$data = $collection::make([
'name' => 'Taylor',
@@ -5954,7 +5994,7 @@ public function testUndot($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testDot($collection)
+ public function testDot($collection): void
{
$data = $collection::make([
'name' => 'Taylor',
@@ -6009,7 +6049,7 @@ public function testDotWithDepth($collection): void
}
#[DataProvider('collectionClassProvider')]
- public function testEnsureForScalar($collection)
+ public function testEnsureForScalar($collection): void
{
$data = $collection::make([1, 2, 3]);
$data->ensure('int');
@@ -6021,7 +6061,7 @@ public function testEnsureForScalar($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testEnsureForObjects($collection)
+ public function testEnsureForObjects($collection): void
{
$data = $collection::make([new stdClass, new stdClass, new stdClass]);
$data->ensure(stdClass::class);
@@ -6033,7 +6073,7 @@ public function testEnsureForObjects($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testEnsureForInheritance($collection)
+ public function testEnsureForInheritance($collection): void
{
$data = $collection::make([new Error, new Error]);
$data->ensure(Throwable::class);
@@ -6046,7 +6086,7 @@ public function testEnsureForInheritance($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testEnsureForMultipleTypes($collection)
+ public function testEnsureForMultipleTypes($collection): void
{
$data = $collection::make([new Error, 123]);
$data->ensure([Throwable::class, 'int']);
@@ -6059,7 +6099,7 @@ public function testEnsureForMultipleTypes($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPercentageWithFlatCollection($collection)
+ public function testPercentageWithFlatCollection($collection): void
{
$collection = new $collection([1, 1, 2, 2, 2, 3]);
@@ -6070,7 +6110,7 @@ public function testPercentageWithFlatCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPercentageWithNestedCollection($collection)
+ public function testPercentageWithNestedCollection($collection): void
{
$collection = new $collection([
['name' => 'Taylor', 'foo' => 'foo'],
@@ -6086,7 +6126,7 @@ public function testPercentageWithNestedCollection($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testHighOrderPercentage($collection)
+ public function testHighOrderPercentage($collection): void
{
$collection = new $collection([
['name' => 'Taylor', 'active' => true],
@@ -6099,7 +6139,7 @@ public function testHighOrderPercentage($collection)
}
#[DataProvider('collectionClassProvider')]
- public function testPercentageReturnsNullForEmptyCollections($collection)
+ public function testPercentageReturnsNullForEmptyCollections($collection): void
{
$collection = new $collection([]);
@@ -6108,10 +6148,8 @@ public function testPercentageReturnsNullForEmptyCollections($collection)
/**
* Provides each collection class, respectively.
- *
- * @return array
*/
- public static function collectionClassProvider()
+ public static function collectionClassProvider(): array
{
return [
[Collection::class],
@@ -6372,12 +6410,12 @@ public function __construct($name = 'taylor')
$this->name = $name;
}
- public function uppercase()
+ public function uppercase(): string
{
return $this->name = strtoupper($this->name);
}
- public function is($name)
+ public function is($name): bool
{
return $this->name === $name;
}
@@ -6385,12 +6423,12 @@ public function is($name)
class TestSupportCollectionHigherOrderStaticClass1
{
- public static function transform($name)
+ public static function transform($name): string
{
return strtoupper($name);
}
- public static function matches($name)
+ public static function matches($name): bool
{
return str_starts_with($name, 'T');
}
@@ -6398,12 +6436,12 @@ public static function matches($name)
class TestSupportCollectionHigherOrderStaticClass2
{
- public static function transform($name)
+ public static function transform($name): string
{
return trim(chunk_split($name, 1, ' '));
}
- public static function matches($name)
+ public static function matches($name): bool
{
return str_starts_with($name, 'O');
}
@@ -6418,7 +6456,7 @@ public function __construct($attributes)
$this->attributes = $attributes;
}
- public function __get($attribute)
+ public function __get($attribute): mixed
{
$accessor = 'get' . lcfirst($attribute) . 'Attribute';
if (method_exists($this, $accessor)) {
@@ -6428,7 +6466,7 @@ public function __get($attribute)
return $this->{$attribute};
}
- public function __isset($attribute)
+ public function __isset($attribute): bool
{
$accessor = 'get' . lcfirst($attribute) . 'Attribute';
@@ -6439,7 +6477,7 @@ public function __isset($attribute)
return isset($this->{$attribute});
}
- public function getSomeAttribute()
+ public function getSomeAttribute(): mixed
{
return $this->attributes['some'];
}
diff --git a/tests/Support/SupportConditionableTest.php b/tests/Support/SupportConditionableTest.php
index 386551b7e..4238cf36e 100644
--- a/tests/Support/SupportConditionableTest.php
+++ b/tests/Support/SupportConditionableTest.php
@@ -9,7 +9,7 @@
class SupportConditionableTest extends TestCase
{
- public function testWhenConditionCallback()
+ public function testWhenConditionCallback(): void
{
// With static condition
$logger = (new ConditionableLogger)
@@ -34,7 +34,7 @@ public function testWhenConditionCallback()
$this->assertSame(['init', 'when', true], $logger->values);
}
- public function testWhenDefaultCallback()
+ public function testWhenDefaultCallback(): void
{
// With static condition
$logger = (new ConditionableLogger)
@@ -59,7 +59,7 @@ public function testWhenDefaultCallback()
$this->assertSame(['default', false], $logger->values);
}
- public function testUnlessConditionCallback()
+ public function testUnlessConditionCallback(): void
{
// With static condition
$logger = (new ConditionableLogger)
@@ -84,7 +84,7 @@ public function testUnlessConditionCallback()
$this->assertSame(['unless', false], $logger->values);
}
- public function testUnlessDefaultCallback()
+ public function testUnlessDefaultCallback(): void
{
// With static condition
$logger = (new ConditionableLogger)
@@ -109,7 +109,7 @@ public function testUnlessDefaultCallback()
$this->assertSame(['init', 'default', true], $logger->values);
}
- public function testWhenProxy()
+ public function testWhenProxy(): void
{
// With static condition
$logger = (new ConditionableLogger)
@@ -137,7 +137,20 @@ public function testWhenProxy()
$this->assertSame(['init', 'one', 'three', 'six'], $logger->values);
}
- public function testUnlessProxy()
+ public function testWhenProxyUsesNonBooleanTruthiness(): void
+ {
+ $logger = (new ConditionableLogger)
+ ->when(1)->log('direct truthy')
+ ->when(0)->log('direct falsy')
+ ->when()->truthyProperty->log('property truthy')
+ ->when()->falsyProperty->log('property falsy')
+ ->when()->truthyMethod()->log('method truthy')
+ ->when()->falsyMethod()->log('method falsy');
+
+ $this->assertSame(['direct truthy', 'property truthy', 'method truthy'], $logger->values);
+ }
+
+ public function testUnlessProxy(): void
{
// With static condition
$logger = (new ConditionableLogger)
@@ -164,6 +177,15 @@ public function testUnlessProxy()
$this->assertSame(['init', 'two', 'four', 'five'], $logger->values);
}
+
+ public function testUnlessProxyUsesNonBooleanTruthiness(): void
+ {
+ $logger = (new ConditionableLogger)
+ ->unless()->truthyProperty->log('truthy')
+ ->unless()->falsyProperty->log('falsy');
+
+ $this->assertSame(['falsy'], $logger->values);
+ }
}
class ConditionableLogger
@@ -174,6 +196,10 @@ class ConditionableLogger
public bool $toggle = false;
+ public int $truthyProperty = 1;
+
+ public int $falsyProperty = 0;
+
public function log(mixed ...$values): static
{
array_push($this->values, ...$values);
@@ -186,6 +212,16 @@ public function has(mixed $value): bool
return in_array($value, $this->values);
}
+ public function truthyMethod(): int
+ {
+ return 1;
+ }
+
+ public function falsyMethod(): int
+ {
+ return 0;
+ }
+
public function toggle(): static
{
$this->toggle = ! $this->toggle;
diff --git a/tests/Support/SupportEnumValueFunctionTest.php b/tests/Support/SupportEnumValueFunctionTest.php
index 117f63f9e..cd2e31b9c 100644
--- a/tests/Support/SupportEnumValueFunctionTest.php
+++ b/tests/Support/SupportEnumValueFunctionTest.php
@@ -14,12 +14,12 @@
class SupportEnumValueFunctionTest extends TestCase
{
#[DataProvider('scalarDataProvider')]
- public function testItCanHandleEnumValue($given, $expected)
+ public function testItCanHandleEnumValue($given, $expected): void
{
$this->assertSame($expected, enum_value($given));
}
- public static function scalarDataProvider()
+ public static function scalarDataProvider(): iterable
{
yield [TestEnum::A, 'A'];
yield [TestBackedEnum::A, 1];
@@ -42,7 +42,7 @@ public static function scalarDataProvider()
yield [$collect = collect(), $collect];
}
- public function testItCanFallbackToUseDefaultIfValueIsNull()
+ public function testItCanFallbackToUseDefaultIfValueIsNull(): void
{
$this->assertSame('laravel', enum_value(null, 'laravel'));
$this->assertSame('laravel', enum_value(null, fn () => 'laravel'));
diff --git a/tests/Support/SupportLazyCollectionIsLazyTest.php b/tests/Support/SupportLazyCollectionIsLazyTest.php
index 613e7a4c6..e3a60834c 100644
--- a/tests/Support/SupportLazyCollectionIsLazyTest.php
+++ b/tests/Support/SupportLazyCollectionIsLazyTest.php
@@ -18,7 +18,7 @@ class SupportLazyCollectionIsLazyTest extends TestCase
{
use Concerns\CountsEnumerations;
- public function testMakeWithClosureIsLazy()
+ public function testMakeWithClosureIsLazy(): void
{
[$closure, $recorder] = $this->makeGeneratorFunctionWithRecorder();
@@ -27,14 +27,14 @@ public function testMakeWithClosureIsLazy()
$this->assertEquals([], $recorder->all());
}
- public function testMakeWithLazyCollectionIsLazy()
+ public function testMakeWithLazyCollectionIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
LazyCollection::make($collection);
});
}
- public function testEagerEnumeratesOnce()
+ public function testEagerEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection = $collection->eager();
@@ -44,7 +44,7 @@ public function testEagerEnumeratesOnce()
});
}
- public function testChunkIsLazy()
+ public function testChunkIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->chunk(3);
@@ -55,7 +55,7 @@ public function testChunkIsLazy()
});
}
- public function testChunkWhileIsLazy()
+ public function testChunkWhileIsLazy(): void
{
$collection = LazyCollection::make(['A', 'A', 'B', 'B', 'C', 'C', 'C']);
@@ -78,7 +78,7 @@ public function testChunkWhileIsLazy()
});
}
- public function testCollapseIsLazy()
+ public function testCollapseIsLazy(): void
{
$collection = LazyCollection::make([
[1, 2, 3],
@@ -95,7 +95,7 @@ public function testCollapseIsLazy()
});
}
- public function testCombineIsLazy()
+ public function testCombineIsLazy(): void
{
$firstEnumerations = 0;
$secondEnumerations = 0;
@@ -113,7 +113,7 @@ public function testCombineIsLazy()
$this->assertEnumerations(1, $secondEnumerations);
}
- public function testConcatIsLazy()
+ public function testConcatIsLazy(): void
{
$firstEnumerations = 0;
$secondEnumerations = 0;
@@ -139,7 +139,7 @@ public function testConcatIsLazy()
$this->assertEnumerations(1, $secondEnumerations);
}
- public function testMultiplyIsLazy()
+ public function testMultiplyIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->multiply(2);
@@ -153,35 +153,35 @@ function ($collection) {
);
}
- public function testContainsIsLazy()
+ public function testContainsIsLazy(): void
{
$this->assertEnumerates(5, function ($collection) {
$collection->contains(5);
});
}
- public function testDoesntContainIsLazy()
+ public function testDoesntContainIsLazy(): void
{
$this->assertEnumerates(5, function ($collection) {
$collection->doesntContain(5);
});
}
- public function testContainsStrictIsLazy()
+ public function testContainsStrictIsLazy(): void
{
$this->assertEnumerates(5, function ($collection) {
$collection->containsStrict(5);
});
}
- public function testCountEnumeratesOnce()
+ public function testCountEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->count();
});
}
- public function testCountByIsLazy()
+ public function testCountByIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->countBy();
@@ -195,7 +195,7 @@ function ($collection) {
);
}
- public function testCrossJoinIsLazy()
+ public function testCrossJoinIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->crossJoin([1]);
@@ -206,7 +206,7 @@ public function testCrossJoinIsLazy()
});
}
- public function testDiffIsLazy()
+ public function testDiffIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->diff([1, 2]);
@@ -217,7 +217,7 @@ public function testDiffIsLazy()
});
}
- public function testDiffAssocIsLazy()
+ public function testDiffAssocIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->diffAssoc([1, 2]);
@@ -228,7 +228,7 @@ public function testDiffAssocIsLazy()
});
}
- public function testDiffAssocUsingIsLazy()
+ public function testDiffAssocUsingIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->diffAssocUsing([1, 2], 'strcasecmp');
@@ -239,7 +239,7 @@ public function testDiffAssocUsingIsLazy()
});
}
- public function testDiffKeysIsLazy()
+ public function testDiffKeysIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->diffKeys([1, 2]);
@@ -250,7 +250,7 @@ public function testDiffKeysIsLazy()
});
}
- public function testDiffKeysUsingIsLazy()
+ public function testDiffKeysUsingIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->diffKeysUsing([1, 2], 'strcasecmp');
@@ -261,7 +261,7 @@ public function testDiffKeysUsingIsLazy()
});
}
- public function testDiffUsingIsLazy()
+ public function testDiffUsingIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->diffUsing([1, 2], 'strcasecmp');
@@ -272,7 +272,7 @@ public function testDiffUsingIsLazy()
});
}
- public function testDuplicatesIsLazy()
+ public function testDuplicatesIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->duplicates();
@@ -283,7 +283,7 @@ public function testDuplicatesIsLazy()
});
}
- public function testDuplicatesStrictIsLazy()
+ public function testDuplicatesStrictIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->duplicatesStrict();
@@ -294,7 +294,7 @@ public function testDuplicatesStrictIsLazy()
});
}
- public function testEachIsLazy()
+ public function testEachIsLazy(): void
{
$this->assertEnumerates(5, function ($collection) {
$collection->each(function ($value, $key) {
@@ -325,7 +325,7 @@ public function testEachIsLazy()
});
}
- public function testEachSpreadIsLazy()
+ public function testEachSpreadIsLazy(): void
{
$data = $this->make([[1, 2], [3, 4], [5, 6], [7, 8]]);
@@ -344,7 +344,7 @@ public function testEachSpreadIsLazy()
});
}
- public function testEveryIsLazy()
+ public function testEveryIsLazy(): void
{
$this->assertEnumerates(2, function ($collection) {
$collection->every(function ($value) {
@@ -359,7 +359,7 @@ public function testEveryIsLazy()
});
}
- public function testExceptIsLazy()
+ public function testExceptIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->except([1, 2]);
@@ -370,7 +370,7 @@ public function testExceptIsLazy()
});
}
- public function testFilterIsLazy()
+ public function testFilterIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->filter(function ($value) {
@@ -385,7 +385,7 @@ public function testFilterIsLazy()
});
}
- public function testFirstIsLazy()
+ public function testFirstIsLazy(): void
{
$this->assertEnumerates(1, function ($collection) {
$collection->first();
@@ -398,7 +398,7 @@ public function testFirstIsLazy()
});
}
- public function testFirstWhereIsLazy()
+ public function testFirstWhereIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3]]);
@@ -407,7 +407,7 @@ public function testFirstWhereIsLazy()
});
}
- public function testFlatMapIsLazy()
+ public function testFlatMapIsLazy(): void
{
$data = $this->make([1, 2, 3, 4, 5]);
@@ -424,7 +424,7 @@ public function testFlatMapIsLazy()
});
}
- public function testFlattenIsLazy()
+ public function testFlattenIsLazy(): void
{
$data = $this->make([1, [2, 3], [4, 5], [6, 7]]);
@@ -437,7 +437,7 @@ public function testFlattenIsLazy()
});
}
- public function testFlipIsLazy()
+ public function testFlipIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->flip();
@@ -448,7 +448,7 @@ public function testFlipIsLazy()
});
}
- public function testForPageIsLazy()
+ public function testForPageIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->forPage(2, 10);
@@ -459,14 +459,14 @@ public function testForPageIsLazy()
});
}
- public function testGetIsLazy()
+ public function testGetIsLazy(): void
{
$this->assertEnumerates(5, function ($collection) {
$collection->get(4);
});
}
- public function testGroupByIsLazy()
+ public function testGroupByIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->groupBy(function ($value) {
@@ -481,7 +481,7 @@ public function testGroupByIsLazy()
});
}
- public function testHasIsLazy()
+ public function testHasIsLazy(): void
{
$this->assertEnumerates(5, function ($collection) {
$collection->has(4);
@@ -492,7 +492,7 @@ public function testHasIsLazy()
});
}
- public function testHasAnyIsLazy()
+ public function testHasAnyIsLazy(): void
{
$this->assertEnumerates(5, function ($collection) {
$collection->hasAny(4);
@@ -507,14 +507,14 @@ public function testHasAnyIsLazy()
});
}
- public function testImplodeEnumeratesOnce()
+ public function testImplodeEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->implode(', ');
});
}
- public function testIntersectIsLazy()
+ public function testIntersectIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->intersect([1, 2, 3]);
@@ -525,7 +525,7 @@ public function testIntersectIsLazy()
});
}
- public function testIntersectUsingIsLazy()
+ public function testIntersectUsingIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->intersectUsing([1, 2], 'strcasecmp');
@@ -536,7 +536,7 @@ public function testIntersectUsingIsLazy()
});
}
- public function testIntersectAssocIsLazy()
+ public function testIntersectAssocIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->intersectAssoc([1, 2]);
@@ -547,7 +547,7 @@ public function testIntersectAssocIsLazy()
});
}
- public function testIntersectAssocUsingIsLazy()
+ public function testIntersectAssocUsingIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->intersectAssocUsing([1, 2], 'strcasecmp');
@@ -558,7 +558,7 @@ public function testIntersectAssocUsingIsLazy()
});
}
- public function testIntersectByKeysIsLazy()
+ public function testIntersectByKeysIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->intersectByKeys([1, 2, 3]);
@@ -569,28 +569,23 @@ public function testIntersectByKeysIsLazy()
});
}
- public function testIsEmptyIsLazy()
+ public function testIsEmptyIsLazy(): void
{
$this->assertEnumerates(1, function ($collection) {
$collection->isEmpty();
});
}
- public function testIsNotEmptyIsLazy()
+ public function testIsNotEmptyIsLazy(): void
{
$this->assertEnumerates(1, function ($collection) {
$collection->isNotEmpty();
});
}
- public function testContainsOneItemIsLazy()
- {
- $this->assertEnumerates(2, function ($collection) {
- $collection->containsOneItem();
- });
- }
+ // REMOVED: Laziness test for Laravel's deprecated containsOneItem(); use hasSole().
- public function testHasSoleIsLazy()
+ public function testHasSoleIsLazy(): void
{
$this->assertEnumerates(2, function ($collection) {
$collection->hasSole();
@@ -607,7 +602,7 @@ public function testHasSoleIsLazy()
);
}
- public function testHasManyIsLazy()
+ public function testHasManyIsLazy(): void
{
$this->assertEnumerates(2, function ($collection) {
$collection->hasMany();
@@ -624,21 +619,21 @@ public function testHasManyIsLazy()
);
}
- public function testJoinIsLazy()
+ public function testJoinIsLazy(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->join(', ', ' and ');
});
}
- public function testJsonSerializeEnumeratesOnce()
+ public function testJsonSerializeEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->jsonSerialize();
});
}
- public function testKeyByIsLazy()
+ public function testKeyByIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->keyBy(function ($value) {
@@ -653,7 +648,7 @@ public function testKeyByIsLazy()
});
}
- public function testKeysIsLazy()
+ public function testKeysIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->keys();
@@ -664,14 +659,14 @@ public function testKeysIsLazy()
});
}
- public function testLastEnumeratesOnce()
+ public function testLastEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->last();
});
}
- public function testMapIsLazy()
+ public function testMapIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->map(function ($value) {
@@ -686,7 +681,7 @@ public function testMapIsLazy()
});
}
- public function testMapIntoIsLazy()
+ public function testMapIntoIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->mapInto(stdClass::class);
@@ -697,7 +692,7 @@ public function testMapIntoIsLazy()
});
}
- public function testMapSpreadIsLazy()
+ public function testMapSpreadIsLazy(): void
{
$data = $this->make([[1, 2], [3, 4], [5, 6], [7, 8]]);
@@ -714,7 +709,7 @@ public function testMapSpreadIsLazy()
});
}
- public function testMapToDictionaryIsLazy()
+ public function testMapToDictionaryIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->mapToDictionary(function ($value, $key) {
@@ -729,7 +724,7 @@ public function testMapToDictionaryIsLazy()
});
}
- public function testMapToGroupsIsLazy()
+ public function testMapToGroupsIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->mapToGroups(function ($value, $key) {
@@ -744,7 +739,7 @@ public function testMapToGroupsIsLazy()
});
}
- public function testMapWithKeysIsLazy()
+ public function testMapWithKeysIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->mapWithKeys(function ($value, $key) {
@@ -759,28 +754,28 @@ public function testMapWithKeysIsLazy()
});
}
- public function testMaxEnumeratesOnce()
+ public function testMaxEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->max();
});
}
- public function testMedianEnumeratesOnce()
+ public function testMedianEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->median();
});
}
- public function testAvgEnumeratesOnce()
+ public function testAvgEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->avg();
});
}
- public function testMergeIsLazy()
+ public function testMergeIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->merge([1, 2, 3]);
@@ -791,7 +786,7 @@ public function testMergeIsLazy()
});
}
- public function testMergeRecursiveIsLazy()
+ public function testMergeRecursiveIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->mergeRecursive([1, 2, 3]);
@@ -802,21 +797,21 @@ public function testMergeRecursiveIsLazy()
});
}
- public function testMinEnumeratesOnce()
+ public function testMinEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->min();
});
}
- public function testModeEnumeratesOnce()
+ public function testModeEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->mode();
});
}
- public function testNthIsLazy()
+ public function testNthIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->nth(5);
@@ -827,7 +822,7 @@ public function testNthIsLazy()
});
}
- public function testOnlyIsLazy()
+ public function testOnlyIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->only(5, 6, 7);
@@ -838,7 +833,7 @@ public function testOnlyIsLazy()
});
}
- public function testPadIsLazy()
+ public function testPadIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->pad(200, null);
@@ -854,7 +849,7 @@ public function testPadIsLazy()
});
}
- public function testPartitionEnumeratesOnce()
+ public function testPartitionEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->partition(function ($value) {
@@ -863,7 +858,7 @@ public function testPartitionEnumeratesOnce()
});
}
- public function testPipeDoesNotEnumerate()
+ public function testPipeDoesNotEnumerate(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->pipe(function () {
@@ -872,7 +867,7 @@ public function testPipeDoesNotEnumerate()
});
}
- public function testPluckIsLazy()
+ public function testPluckIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3], ['a' => 4]]);
@@ -885,7 +880,7 @@ public function testPluckIsLazy()
});
}
- public function testRandomEnumeratesOnce()
+ public function testRandomEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->random();
@@ -896,7 +891,7 @@ public function testRandomEnumeratesOnce()
});
}
- public function testRangeIsLazy()
+ public function testRangeIsLazy(): void
{
$data = LazyCollection::range(10, 1000);
@@ -909,7 +904,7 @@ public function testRangeIsLazy()
});
}
- public function testReduceIsLazy()
+ public function testReduceIsLazy(): void
{
$this->assertEnumerates(1, function ($collection) {
$this->rescue(function () use ($collection) {
@@ -926,7 +921,7 @@ public function testReduceIsLazy()
});
}
- public function testReduceSpreadIsLazy()
+ public function testReduceSpreadIsLazy(): void
{
$this->assertEnumerates(1, function ($collection) {
$this->rescue(function () use ($collection) {
@@ -943,7 +938,7 @@ public function testReduceSpreadIsLazy()
});
}
- public function testRejectIsLazy()
+ public function testRejectIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->reject(function ($value) {
@@ -958,7 +953,7 @@ public function testRejectIsLazy()
});
}
- public function testRememberIsLazy()
+ public function testRememberIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->remember();
@@ -979,7 +974,7 @@ public function testRememberIsLazy()
});
}
- public function testReplaceIsLazy()
+ public function testReplaceIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->replace([5 => 'a', 10 => 'b']);
@@ -990,7 +985,7 @@ public function testReplaceIsLazy()
});
}
- public function testReplaceRecursiveIsLazy()
+ public function testReplaceRecursiveIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->replaceRecursive([5 => 'a', 10 => 'b']);
@@ -1001,7 +996,7 @@ public function testReplaceRecursiveIsLazy()
});
}
- public function testReverseIsLazy()
+ public function testReverseIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->reverse();
@@ -1012,7 +1007,7 @@ public function testReverseIsLazy()
});
}
- public function testSearchIsLazy()
+ public function testSearchIsLazy(): void
{
$this->assertEnumerates(5, function ($collection) {
$collection->search(5);
@@ -1023,7 +1018,7 @@ public function testSearchIsLazy()
});
}
- public function testShuffleIsLazy()
+ public function testShuffleIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->shuffle();
@@ -1034,7 +1029,7 @@ public function testShuffleIsLazy()
});
}
- public function testSlidingIsLazy()
+ public function testSlidingIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->sliding();
@@ -1057,7 +1052,7 @@ public function testSlidingIsLazy()
});
}
- public function testSkipIsLazy()
+ public function testSkipIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->skip(10);
@@ -1068,7 +1063,7 @@ public function testSkipIsLazy()
});
}
- public function testSkipUntilIsLazy()
+ public function testSkipUntilIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->skipUntil(INF);
@@ -1085,7 +1080,7 @@ public function testSkipUntilIsLazy()
});
}
- public function testSkipWhileIsLazy()
+ public function testSkipWhileIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->skipWhile(1);
@@ -1102,7 +1097,7 @@ public function testSkipWhileIsLazy()
});
}
- public function testSliceIsLazy()
+ public function testSliceIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->slice(2);
@@ -1123,7 +1118,7 @@ public function testSliceIsLazy()
});
}
- public function testFindFirstOrFailIsLazy()
+ public function testFindFirstOrFailIsLazy(): void
{
$this->assertEnumerates(1, function ($collection) {
$collection->firstOrFail();
@@ -1151,7 +1146,7 @@ public function testFindFirstOrFailIsLazy()
});
}
- public function testSomeIsLazy()
+ public function testSomeIsLazy(): void
{
$this->assertEnumerates(5, function ($collection) {
$collection->some(function ($value) {
@@ -1166,7 +1161,7 @@ public function testSomeIsLazy()
});
}
- public function testSoleIsLazy()
+ public function testSoleIsLazy(): void
{
$this->assertEnumerates(2, function ($collection) {
try {
@@ -1191,7 +1186,7 @@ public function testSoleIsLazy()
});
}
- public function testSortIsLazy()
+ public function testSortIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->sort();
@@ -1202,7 +1197,7 @@ public function testSortIsLazy()
});
}
- public function testSortDescIsLazy()
+ public function testSortDescIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->sortDesc();
@@ -1213,7 +1208,7 @@ public function testSortDescIsLazy()
});
}
- public function testSortByIsLazy()
+ public function testSortByIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->sortBy(function ($value) {
@@ -1228,7 +1223,7 @@ public function testSortByIsLazy()
});
}
- public function testSortByDescIsLazy()
+ public function testSortByDescIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->sortByDesc(function ($value) {
@@ -1243,7 +1238,7 @@ public function testSortByDescIsLazy()
});
}
- public function testSortKeysIsLazy()
+ public function testSortKeysIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->sortKeys();
@@ -1254,7 +1249,7 @@ public function testSortKeysIsLazy()
});
}
- public function testSortKeysDescIsLazy()
+ public function testSortKeysDescIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->sortKeysDesc();
@@ -1265,7 +1260,7 @@ public function testSortKeysDescIsLazy()
});
}
- public function testSplitIsLazy()
+ public function testSplitIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->split(4);
@@ -1276,14 +1271,14 @@ public function testSplitIsLazy()
});
}
- public function testSumEnumeratesOnce()
+ public function testSumEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->sum();
});
}
- public function testTakeIsLazy()
+ public function testTakeIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->take(10);
@@ -1294,7 +1289,7 @@ public function testTakeIsLazy()
});
}
- public function testTakeUntilIsLazy()
+ public function testTakeUntilIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->takeUntil(INF);
@@ -1311,7 +1306,7 @@ public function testTakeUntilIsLazy()
});
}
- public function testTakeUntilTimeoutIsLazy()
+ public function testTakeUntilTimeoutIsLazy(): void
{
tap(m::mock(LazyCollection::class . '[now]')->times(100), function ($mock) {
$this->assertDoesNotEnumerateCollection($mock, function ($mock) {
@@ -1375,7 +1370,7 @@ public function testTakeUntilTimeoutIsLazy()
});
}
- public function testTakeWhileIsLazy()
+ public function testTakeWhileIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->takeWhile(0);
@@ -1392,7 +1387,7 @@ public function testTakeWhileIsLazy()
});
}
- public function testTapDoesNotEnumerate()
+ public function testTapDoesNotEnumerate(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->tap(function ($collection) {
@@ -1401,7 +1396,7 @@ public function testTapDoesNotEnumerate()
});
}
- public function testTapEachIsLazy()
+ public function testTapEachIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->tapEach(function ($value) {
@@ -1416,7 +1411,7 @@ public function testTapEachIsLazy()
});
}
- public function testThrottleIsLazy()
+ public function testThrottleIsLazy(): void
{
Sleep::fake();
@@ -1435,7 +1430,7 @@ public function testThrottleIsLazy()
Sleep::fake(false);
}
- public function testTimesIsLazy()
+ public function testTimesIsLazy(): void
{
$data = LazyCollection::times(INF);
@@ -1444,21 +1439,21 @@ public function testTimesIsLazy()
});
}
- public function testToArrayEnumeratesOnce()
+ public function testToArrayEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->toArray();
});
}
- public function testToJsonEnumeratesOnce()
+ public function testToJsonEnumeratesOnce(): void
{
$this->assertEnumeratesOnce(function ($collection) {
$collection->toJson();
});
}
- public function testUnionIsLazy()
+ public function testUnionIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->union([4, 5, 6]);
@@ -1469,7 +1464,7 @@ public function testUnionIsLazy()
});
}
- public function testUniqueIsLazy()
+ public function testUniqueIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->unique();
@@ -1480,7 +1475,7 @@ public function testUniqueIsLazy()
});
}
- public function testUniqueStrictIsLazy()
+ public function testUniqueStrictIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->uniqueStrict();
@@ -1491,7 +1486,7 @@ public function testUniqueStrictIsLazy()
});
}
- public function testUnlessDoesNotEnumerate()
+ public function testUnlessDoesNotEnumerate(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->unless(true, function ($collection) {
@@ -1504,7 +1499,7 @@ public function testUnlessDoesNotEnumerate()
});
}
- public function testUnlessEmptyIsLazy()
+ public function testUnlessEmptyIsLazy(): void
{
$this->assertEnumerates(1, function ($collection) {
$collection->unlessEmpty(function ($collection) {
@@ -1513,7 +1508,7 @@ public function testUnlessEmptyIsLazy()
});
}
- public function testUnlessNotEmptyIsLazy()
+ public function testUnlessNotEmptyIsLazy(): void
{
$this->assertEnumerates(1, function ($collection) {
$collection->unlessNotEmpty(function ($collection) {
@@ -1522,14 +1517,14 @@ public function testUnlessNotEmptyIsLazy()
});
}
- public function testUnwrapEnumeratesOne()
+ public function testUnwrapEnumeratesOne(): void
{
$this->assertEnumeratesOnce(function ($collection) {
LazyCollection::unwrap($collection);
});
}
- public function testValuesIsLazy()
+ public function testValuesIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->values();
@@ -1540,7 +1535,7 @@ public function testValuesIsLazy()
});
}
- public function testWhenDoesNotEnumerate()
+ public function testWhenDoesNotEnumerate(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->when(true, function ($collection) {
@@ -1553,7 +1548,7 @@ public function testWhenDoesNotEnumerate()
});
}
- public function testWhenEmptyIsLazy()
+ public function testWhenEmptyIsLazy(): void
{
$this->assertEnumerates(1, function ($collection) {
$collection->whenEmpty(function ($collection) {
@@ -1562,7 +1557,7 @@ public function testWhenEmptyIsLazy()
});
}
- public function testWhenNotEmptyIsLazy()
+ public function testWhenNotEmptyIsLazy(): void
{
$this->assertEnumerates(1, function ($collection) {
$collection->whenNotEmpty(function ($collection) {
@@ -1571,7 +1566,7 @@ public function testWhenNotEmptyIsLazy()
});
}
- public function testWhereIsLazy()
+ public function testWhereIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3], ['a' => 4]]);
@@ -1584,7 +1579,7 @@ public function testWhereIsLazy()
});
}
- public function testWhereBetweenIsLazy()
+ public function testWhereBetweenIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3], ['a' => 4]]);
@@ -1597,7 +1592,7 @@ public function testWhereBetweenIsLazy()
});
}
- public function testWhereInIsLazy()
+ public function testWhereInIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3], ['a' => 4]]);
@@ -1610,7 +1605,7 @@ public function testWhereInIsLazy()
});
}
- public function testWhereInstanceOfIsLazy()
+ public function testWhereInstanceOfIsLazy(): void
{
$data = $this->make(['a' => 0])->concat(
$this->make([['a' => 1], ['a' => 2], ['a' => 3], ['a' => 4]])
@@ -1626,7 +1621,7 @@ public function testWhereInstanceOfIsLazy()
});
}
- public function testWhereInStrictIsLazy()
+ public function testWhereInStrictIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3], ['a' => 4]]);
@@ -1639,7 +1634,7 @@ public function testWhereInStrictIsLazy()
});
}
- public function testWhereNotBetweenIsLazy()
+ public function testWhereNotBetweenIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3], ['a' => 4]]);
@@ -1652,7 +1647,7 @@ public function testWhereNotBetweenIsLazy()
});
}
- public function testWhereNotInIsLazy()
+ public function testWhereNotInIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3], ['a' => 4]]);
@@ -1665,7 +1660,7 @@ public function testWhereNotInIsLazy()
});
}
- public function testWhereNotInStrictIsLazy()
+ public function testWhereNotInStrictIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3], ['a' => 4]]);
@@ -1678,7 +1673,7 @@ public function testWhereNotInStrictIsLazy()
});
}
- public function testWhereNotNullIsLazy()
+ public function testWhereNotNullIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => null], ['a' => 2], ['a' => 3]]);
@@ -1701,7 +1696,7 @@ public function testWhereNotNullIsLazy()
});
}
- public function testWhereNullIsLazy()
+ public function testWhereNullIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => null], ['a' => 2], ['a' => 3]]);
@@ -1724,7 +1719,7 @@ public function testWhereNullIsLazy()
});
}
- public function testWhereStrictIsLazy()
+ public function testWhereStrictIsLazy(): void
{
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3], ['a' => 4]]);
@@ -1737,7 +1732,7 @@ public function testWhereStrictIsLazy()
});
}
- public function testWithHeartbeatIsLazy()
+ public function testWithHeartbeatIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->withHeartbeat(1, function () {
@@ -1752,7 +1747,7 @@ public function testWithHeartbeatIsLazy()
});
}
- public function testWrapIsLazy()
+ public function testWrapIsLazy(): void
{
$this->assertDoesNotEnumerate(function ($collection) {
LazyCollection::wrap($collection);
@@ -1763,7 +1758,7 @@ public function testWrapIsLazy()
});
}
- public function testZipIsLazy()
+ public function testZipIsLazy(): void
{
$firstEnumerations = 0;
$secondEnumerations = 0;
@@ -1781,12 +1776,12 @@ public function testZipIsLazy()
$this->assertEnumerations(1, $secondEnumerations);
}
- protected function make($source)
+ protected function make($source): LazyCollection
{
return new LazyCollection($source);
}
- protected function rescue($callback)
+ protected function rescue($callback): void
{
try {
$callback();
diff --git a/tests/Support/SupportLazyCollectionTest.php b/tests/Support/SupportLazyCollectionTest.php
index 4367d7c96..ca58be618 100644
--- a/tests/Support/SupportLazyCollectionTest.php
+++ b/tests/Support/SupportLazyCollectionTest.php
@@ -4,7 +4,9 @@
namespace Hypervel\Tests\Support;
+use ArrayIterator;
use Carbon\CarbonInterval as Duration;
+use Generator;
use Hypervel\Foundation\Testing\Wormhole;
use Hypervel\Support\Carbon;
use Hypervel\Support\Collection;
@@ -16,13 +18,13 @@
class SupportLazyCollectionTest extends TestCase
{
- public function testCanCreateEmptyCollection()
+ public function testCanCreateEmptyCollection(): void
{
$this->assertSame([], LazyCollection::make()->all());
$this->assertSame([], LazyCollection::empty()->all());
}
- public function testCanCreateCollectionFromArray()
+ public function testCanCreateCollectionFromArray(): void
{
$array = [1, 2, 3];
@@ -37,7 +39,7 @@ public function testCanCreateCollectionFromArray()
$this->assertSame($array, $data->all());
}
- public function testCanCreateCollectionFromArrayable()
+ public function testCanCreateCollectionFromArrayable(): void
{
$array = [1, 2, 3];
@@ -52,7 +54,7 @@ public function testCanCreateCollectionFromArrayable()
$this->assertSame($array, $data->all());
}
- public function testCanCreateCollectionFromGeneratorFunction()
+ public function testCanCreateCollectionFromGeneratorFunction(): void
{
$data = LazyCollection::make(function () {
yield 1;
@@ -75,7 +77,7 @@ public function testCanCreateCollectionFromGeneratorFunction()
], $data->all());
}
- public function testCanCreateCollectionFromNonGeneratorFunction()
+ public function testCanCreateCollectionFromNonGeneratorFunction(): void
{
$data = LazyCollection::make(function () {
return 'laravel';
@@ -84,7 +86,7 @@ public function testCanCreateCollectionFromNonGeneratorFunction()
$this->assertSame(['laravel'], $data->all());
}
- public function testDoesNotCreateCollectionFromGenerator()
+ public function testDoesNotCreateCollectionFromGenerator(): void
{
$this->expectException(InvalidArgumentException::class);
@@ -95,7 +97,47 @@ public function testDoesNotCreateCollectionFromGenerator()
LazyCollection::make($generateNumber());
}
- public function testEager()
+ public function testCombineAcceptsPlainIterators(): void
+ {
+ $keys = new LazyCollection(['first', 'second']);
+
+ $this->assertSame(
+ ['first' => 1, 'second' => 2],
+ $keys->combine(new ArrayIterator([1, 2]))->all()
+ );
+
+ $values = (function (): Generator {
+ yield 3;
+ yield 4;
+ })();
+
+ $this->assertSame(
+ ['first' => 3, 'second' => 4],
+ $keys->combine($values)->all()
+ );
+ }
+
+ public function testZipAcceptsPlainIterators(): void
+ {
+ $values = new LazyCollection([1, 2]);
+
+ $this->assertSame(
+ [[1, 3], [2, 4]],
+ $values->zip(new ArrayIterator([3, 4]))->map->all()->all()
+ );
+
+ $items = (function (): Generator {
+ yield 5;
+ yield 6;
+ })();
+
+ $this->assertSame(
+ [[1, 5], [2, 6]],
+ $values->zip($items)->map->all()->all()
+ );
+ }
+
+ public function testEager(): void
{
$source = [1, 2, 3, 4, 5];
@@ -108,7 +150,7 @@ public function testEager()
$this->assertSame([1, 2, 3, 4, 5], $data->all());
}
- public function testRemember()
+ public function testRemember(): void
{
$source = [1, 2, 3, 4];
@@ -123,7 +165,7 @@ public function testRemember()
$this->assertSame([1, 2, 3, 4], $collection->all());
}
- public function testRememberWithTwoRunners()
+ public function testRememberWithTwoRunners(): void
{
$source = [1, 2, 3, 4];
@@ -168,7 +210,7 @@ public function testRememberWithTwoRunners()
$this->assertEquals(4, $b->current());
}
- public function testRememberWithDuplicateKeys()
+ public function testRememberWithDuplicateKeys(): void
{
$collection = LazyCollection::make(function () {
yield 'key' => 1;
@@ -182,7 +224,7 @@ public function testRememberWithDuplicateKeys()
$this->assertSame([['key', 1], ['key', 2]], $results);
}
- public function testTakeUntilTimeout()
+ public function testTakeUntilTimeout(): void
{
$timeout = Carbon::now();
@@ -213,7 +255,7 @@ public function testTakeUntilTimeout()
$this->assertSame([2, 1], $timedOutWith);
}
- public function testTapEach()
+ public function testTapEach(): void
{
$data = LazyCollection::times(10);
@@ -231,7 +273,7 @@ public function testTapEach()
$this->assertSame([1, 2, 3, 4, 5], $tapped);
}
- public function testThrottle()
+ public function testThrottle(): void
{
Sleep::fake();
@@ -254,7 +296,7 @@ public function testThrottle()
Sleep::fake(false);
}
- public function testThrottleAccountsForTimePassed()
+ public function testThrottleAccountsForTimePassed(): void
{
Sleep::fake();
Carbon::setTestNow(now());
@@ -287,7 +329,7 @@ public function testThrottleAccountsForTimePassed()
Carbon::setTestNow();
}
- public function testUniqueDoubleEnumeration()
+ public function testUniqueDoubleEnumeration(): void
{
$data = LazyCollection::times(2)->unique();
@@ -296,7 +338,7 @@ public function testUniqueDoubleEnumeration()
$this->assertSame([1, 2], $data->all());
}
- public function testAfter()
+ public function testAfter(): void
{
$data = new LazyCollection([1, '2', 3, 4]);
@@ -322,7 +364,7 @@ public function testAfter()
$this->assertSame(['name' => 'Mohamed', 'age' => 35], $result);
}
- public function testBefore()
+ public function testBefore(): void
{
// Test finding item before value with non-strict comparison
$data = new LazyCollection([1, 2, '3', 4]);
@@ -345,7 +387,7 @@ public function testBefore()
$this->assertSame(['name' => 'Taylor', 'age' => 35], $result);
}
- public function testShuffle()
+ public function testShuffle(): void
{
$data = new LazyCollection([1, 2, 3, 4, 5]);
$shuffled = $data->shuffle();
@@ -365,7 +407,7 @@ public function testShuffle()
$this->assertTrue($shuffled->contains('name', 'Jeffrey'));
}
- public function testCollapseWithKeys()
+ public function testCollapseWithKeys(): void
{
$collection = new LazyCollection([
['a' => 1, 'b' => 2],
@@ -384,34 +426,9 @@ public function testCollapseWithKeys()
$this->assertEquals(['a' => 1, 'b' => 2], $collapsed->all());
}
- public function testContainsOneItem()
- {
- $collection = new LazyCollection([5]);
- $this->assertTrue($collection->containsOneItem());
-
- $emptyCollection = new LazyCollection([]);
- $this->assertFalse($emptyCollection->containsOneItem());
-
- $multipleCollection = new LazyCollection([1, 2, 3]);
- $this->assertFalse($multipleCollection->containsOneItem());
- }
-
- public function testContainsManyItems()
- {
- $emptyCollection = new LazyCollection([]);
- $this->assertFalse($emptyCollection->containsManyItems());
-
- $singleCollection = new LazyCollection([1]);
- $this->assertFalse($singleCollection->containsManyItems());
-
- $multipleCollection = new LazyCollection([1, 2]);
- $this->assertTrue($multipleCollection->containsManyItems());
+ // REMOVED: Tests for Laravel's deprecated containsOneItem() and containsManyItems(); use hasSole() and hasMany().
- $manyCollection = new LazyCollection([1, 2, 3]);
- $this->assertTrue($manyCollection->containsManyItems());
- }
-
- public function testDoesntContain()
+ public function testDoesntContain(): void
{
$collection = new LazyCollection([1, 2, 3, 4, 5]);
@@ -437,7 +454,7 @@ public function testDoesntContain()
$this->assertFalse($users->doesntContain('name', 'Taylor'));
}
- public function testDot()
+ public function testDot(): void
{
$collection = new LazyCollection([
'foo' => [
@@ -472,7 +489,7 @@ public function testDot()
$this->assertEquals($expected, $dotted->all());
}
- public function testWithHeartbeat()
+ public function testWithHeartbeat(): void
{
$start = Carbon::create(2000, 1, 1);
$after2Minutes = $start->copy()->addMinutes(2);
@@ -518,4 +535,38 @@ public function testWithHeartbeat()
Carbon::setTestNow();
}
+
+ public function testRandomPreservesKeys(): void
+ {
+ $collection = new LazyCollection([
+ 'first' => 1,
+ 'second' => 2,
+ 'third' => 3,
+ ]);
+
+ $this->assertSame([0, 1], array_keys($collection->random(2)->all()));
+
+ foreach (array_keys($collection->random(2, true)->all()) as $key) {
+ $this->assertContains($key, ['first', 'second', 'third']);
+ }
+ }
+
+ public function testHasDoesNotCountDuplicateKeys(): void
+ {
+ $collection = LazyCollection::make(function (): iterable {
+ yield 'a' => 1;
+ yield 'a' => 2;
+ yield 'c' => 3;
+ });
+
+ $this->assertFalse($collection->has('a', 'b'));
+ $this->assertFalse($collection->has(['a', 'b']));
+ $this->assertTrue($collection->has('a'));
+ }
+
+ public function testHasTreatsAnEmptyKeySetAsSatisfied(): void
+ {
+ $this->assertTrue(LazyCollection::empty()->has([]));
+ $this->assertTrue((new LazyCollection([1, 2, 3]))->has([]));
+ }
}
diff --git a/tests/Support/SupportMacroableTest.php b/tests/Support/SupportMacroableTest.php
index cb3573fe8..d372ba0c4 100644
--- a/tests/Support/SupportMacroableTest.php
+++ b/tests/Support/SupportMacroableTest.php
@@ -5,6 +5,7 @@
namespace Hypervel\Tests\Support;
use BadMethodCallException;
+use Closure;
use Hypervel\Support\Traits\Macroable;
use Hypervel\Tests\TestCase;
@@ -19,12 +20,20 @@ protected function setUp(): void
$this->macroable = $this->createObjectForTrait();
}
+ protected function tearDown(): void
+ {
+ EmptyMacroable::flushMacros();
+ TestMacroable::flushMacros();
+
+ parent::tearDown();
+ }
+
private function createObjectForTrait(): EmptyMacroable
{
return new EmptyMacroable;
}
- public function testRegisterMacro()
+ public function testRegisterMacro(): void
{
$macroable = $this->macroable;
$macroable::macro(__CLASS__, function () {
@@ -33,7 +42,7 @@ public function testRegisterMacro()
$this->assertSame('Taylor', $macroable::{__CLASS__}());
}
- public function testHasMacro()
+ public function testHasMacro(): void
{
$macroable = $this->macroable;
$macroable::macro('foo', function () {
@@ -43,7 +52,7 @@ public function testHasMacro()
$this->assertFalse($macroable::hasMacro('bar'));
}
- public function testRegisterMacroAndCallWithoutStatic()
+ public function testRegisterMacroAndCallWithoutStatic(): void
{
$macroable = $this->macroable;
$macroable::macro(__CLASS__, function () {
@@ -52,7 +61,7 @@ public function testRegisterMacroAndCallWithoutStatic()
$this->assertSame('Taylor', $macroable->{__CLASS__}());
}
- public function testWhenCallingMacroClosureIsBoundToObject()
+ public function testWhenCallingMacroClosureIsBoundToObject(): void
{
TestMacroable::macro('tryInstance', function () {
return $this->protectedVariable;
@@ -69,14 +78,14 @@ public function testWhenCallingMacroClosureIsBoundToObject()
$this->assertSame('static', $result);
}
- public function testClassBasedMacros()
+ public function testClassBasedMacros(): void
{
TestMacroable::mixin(new TestMixin);
$instance = new TestMacroable;
$this->assertSame('instance-Adam', $instance->methodOne('Adam'));
}
- public function testClassBasedMacrosNoReplace()
+ public function testClassBasedMacrosNoReplace(): void
{
TestMacroable::macro('methodThree', function () {
return 'bar';
@@ -89,7 +98,7 @@ public function testClassBasedMacrosNoReplace()
$this->assertSame('foo', $instance->methodThree());
}
- public function testFlushMacros()
+ public function testFlushMacros(): void
{
TestMacroable::macro('flushMethod', function () {
return 'flushMethod';
@@ -106,7 +115,7 @@ public function testFlushMacros()
$instance->flushMethod();
}
- public function testFlushMacrosStatic()
+ public function testFlushMacrosStatic(): void
{
TestMacroable::macro('flushMethod', function () {
return 'flushMethod';
@@ -123,7 +132,7 @@ public function testFlushMacrosStatic()
$instance::flushMethod();
}
- public function testMacroWithArguments()
+ public function testMacroWithArguments(): void
{
$this->macroable::macro('concatenate', function ($arg1, $arg2) {
return $arg1 . ' ' . $arg2;
@@ -133,7 +142,7 @@ public function testMacroWithArguments()
$this->assertSame('Hello World', $result);
}
- public function testMacroWithDefaultArguments()
+ public function testMacroWithDefaultArguments(): void
{
$this->macroable::macro('greet', function ($name = 'Guest') {
return 'Hello, ' . $name;
@@ -143,14 +152,14 @@ public function testMacroWithDefaultArguments()
$this->assertSame('Hello, Saleh', $this->macroable::greet('Saleh'));
}
- public function testCallingUndefinedMacroThrowsException()
+ public function testCallingUndefinedMacroThrowsException(): void
{
$this->expectException(BadMethodCallException::class);
$this->macroable::nonExistentMacro();
}
- public function testMethodConflictDoesNotThrowException()
+ public function testMethodConflictDoesNotThrowException(): void
{
$this->macroable::macro('existingMethod', function () {
return 'oldMethod';
@@ -163,6 +172,84 @@ public function testMethodConflictDoesNotThrowException()
$this->assertSame('newMethod', $this->macroable::existingMethod());
}
+
+ public function testStaticCallOfNonStaticClosure(): void
+ {
+ $this->macroable::macro('nonStaticClosure', function () {
+ return 'Taylor';
+ });
+
+ $this->assertSame('Taylor', $this->macroable::nonStaticClosure());
+ }
+
+ public function testNonStaticCallOfNonStaticClosure(): void
+ {
+ $this->macroable::macro('nonStaticClosure', function () {
+ return 'Taylor';
+ });
+
+ $this->assertSame('Taylor', $this->macroable->nonStaticClosure());
+ }
+
+ public function testStaticCallOfStaticClosure(): void
+ {
+ $this->macroable::macro('staticClosure', static function () {
+ return 'Taylor';
+ });
+
+ $this->assertSame('Taylor', $this->macroable::staticClosure());
+ }
+
+ public function testNonStaticCallOfStaticClosure(): void
+ {
+ $this->macroable::macro('staticClosure', static function () {
+ return 'Taylor';
+ });
+
+ $this->assertSame('Taylor', $this->macroable->staticClosure());
+ }
+
+ public function testNonStaticCallOfStaticClosureBindsClassScope(): void
+ {
+ TestMacroable::macro('staticClosure', static function () {
+ return static::getProtectedStatic();
+ });
+
+ $this->assertSame('static', (new TestMacroable)->staticClosure());
+ }
+
+ public function testClosureFromInternalFunctionRetainsItsCallableBinding(): void
+ {
+ $this->macroable::macro('length', Closure::fromCallable('strlen'));
+
+ $this->assertSame(6, $this->macroable::length('Taylor'));
+ $this->assertSame(6, $this->macroable->length('Taylor'));
+ }
+
+ public function testBoundInstanceMethodFirstClassCallableRetainsItsBinding(): void
+ {
+ $callable = new TestMacroCallable;
+ $this->macroable::macro('instanceCallable', $callable->instanceMethod(...));
+
+ $this->assertSame('instance-Taylor', $this->macroable::instanceCallable('Taylor'));
+ $this->assertSame('instance-Taylor', $this->macroable->instanceCallable('Taylor'));
+ }
+
+ public function testStaticMethodFirstClassCallableRetainsItsBinding(): void
+ {
+ $this->macroable::macro('staticCallable', TestMacroCallable::staticMethod(...));
+
+ $this->assertSame('static-Taylor', $this->macroable::staticCallable('Taylor'));
+ $this->assertSame('static-Taylor', $this->macroable->staticCallable('Taylor'));
+ }
+
+ public function testInvokableObjectCanBeCalledStaticallyAndNonStatically(): void
+ {
+ $this->macroable::macro('invokable', new TestInvokableMacro);
+
+ $this->assertSame('invokable-Taylor', $this->macroable::invokable('Taylor'));
+ $this->assertSame('invokable-Taylor', $this->macroable->invokable('Taylor'));
+ }
}
class EmptyMacroable
@@ -205,3 +292,24 @@ protected function methodThree()
};
}
}
+
+class TestMacroCallable
+{
+ public function instanceMethod(string $value): string
+ {
+ return 'instance-' . $value;
+ }
+
+ public static function staticMethod(string $value): string
+ {
+ return 'static-' . $value;
+ }
+}
+
+class TestInvokableMacro
+{
+ public function __invoke(string $value): string
+ {
+ return 'invokable-' . $value;
+ }
+}
diff --git a/tests/Testbench/Foundation/Process/RemoteCommandTest.php b/tests/Testbench/Foundation/Process/RemoteCommandTest.php
index 6f812e3ab..1de13b86e 100644
--- a/tests/Testbench/Foundation/Process/RemoteCommandTest.php
+++ b/tests/Testbench/Foundation/Process/RemoteCommandTest.php
@@ -4,6 +4,7 @@
namespace Hypervel\Tests\Testbench\Foundation\Process;
+use Hypervel\Filesystem\Filesystem;
use Hypervel\Foundation\Application;
use Hypervel\Testbench\Attributes\WithConfig;
use Hypervel\Testbench\Concerns\Database\InteractsWithSqliteDatabaseFile;
@@ -67,6 +68,45 @@ public function itDoesNotForwardTheParentRuntimeCopyToServeCommands(): void
});
}
+ #[Test]
+ public function itRestoresThePackageManifestAfterRemoteCommands(): void
+ {
+ $this->withoutSqliteDatabase(function (): void {
+ $files = new Filesystem;
+ $path = $this->app->getCachedPackagesPath();
+ // This must match the baseline captured by the base TestCase earlier in setUp.
+ $existed = $files->isFile($path);
+ $contents = $existed ? $files->get($path) : '';
+
+ // The base TestCase registered its restoration callback during setUp,
+ // so this later callback observes the already-restored manifest.
+ $this->beforeApplicationDestroyed(function () use ($files, $path, $existed, $contents): void {
+ if ($existed) {
+ $this->assertFileExists($path);
+ $this->assertSame($contents, $files->get($path));
+ } else {
+ $this->assertFileDoesNotExist($path);
+ }
+ });
+
+ // Force the child to build the manifest instead of reusing the baseline cache.
+ if ($files->isFile($path)) {
+ $this->assertTrue($files->delete($path));
+ }
+
+ remote('about --json')->mustRun();
+
+ $this->assertFileExists($path);
+
+ // Exercise restoration deterministically even when the child's
+ // rebuilt manifest matches the captured baseline byte-for-byte.
+ $probe = " true];\n";
+ $files->replace($path, $probe);
+
+ $this->assertSame($probe, $files->get($path));
+ });
+ }
+
/**
* Get the configured environment variables for the wrapped Symfony process.
*
diff --git a/tests/Testing/PHPUnit/AfterEachTestSubscriberTest.php b/tests/Testing/PHPUnit/AfterEachTestSubscriberTest.php
index c3b2ca591..e9515889e 100644
--- a/tests/Testing/PHPUnit/AfterEachTestSubscriberTest.php
+++ b/tests/Testing/PHPUnit/AfterEachTestSubscriberTest.php
@@ -5,7 +5,19 @@
namespace Hypervel\Tests\Testing\PHPUnit;
use Hypervel\Contracts\Pool\ConnectionInterface;
+use Hypervel\Database\Eloquent\Factories\Factory as EloquentFactory;
use Hypervel\Foundation\Testing\DatabaseConnectionResolver;
+use Hypervel\Http\Client\Factory as HttpFactory;
+use Hypervel\Http\Client\PendingRequest;
+use Hypervel\Http\Client\Response as HttpClientResponse;
+use Hypervel\Http\JsonResponse;
+use Hypervel\Http\RedirectResponse;
+use Hypervel\Http\Request;
+use Hypervel\Http\Resources\Json\JsonResource;
+use Hypervel\Http\Resources\JsonApi\JsonApiResource;
+use Hypervel\Http\Response as HttpResponse;
+use Hypervel\Http\UploadedFile;
+use Hypervel\Support\Testing\Fakes\NotificationFake;
use Hypervel\Testing\PHPUnit\AfterEachTestCleanup;
use Hypervel\Testing\PHPUnit\AfterEachTestSubscriber;
use Hypervel\Tests\TestCase;
@@ -25,6 +37,81 @@ protected function tearDown(): void
parent::tearDown();
}
+ public function testFrameworkCleanupFlushesEveryMacroableRegistry(): void
+ {
+ $classes = [
+ EloquentFactory::class,
+ HttpFactory::class,
+ PendingRequest::class,
+ HttpClientResponse::class,
+ JsonResponse::class,
+ RedirectResponse::class,
+ Request::class,
+ JsonResource::class,
+ JsonApiResource::class,
+ HttpResponse::class,
+ UploadedFile::class,
+ NotificationFake::class,
+ ];
+ $macro = 'testingStaticStateProbe';
+
+ foreach ($classes as $class) {
+ $class::macro($macro, static fn (): string => 'ok');
+ $this->assertTrue($class::hasMacro($macro));
+ }
+
+ $subscriber = new class extends AfterEachTestSubscriber {
+ public function flushFrameworkStateForTest(): void
+ {
+ $this->flushFrameworkState();
+ }
+ };
+
+ try {
+ $subscriber->flushFrameworkStateForTest();
+
+ foreach ($classes as $class) {
+ $this->assertFalse($class::hasMacro($macro));
+ }
+ } finally {
+ foreach ($classes as $class) {
+ $class::flushMacros();
+ }
+ }
+ }
+
+ public function testFrameworkCleanupFlushesInheritedRequestStaticState(): void
+ {
+ $request = new Request;
+ $request->setFormat('testing', 'application/x-testing');
+ Request::enableHttpMethodParameterOverride();
+ Request::setAllowedHttpMethodOverride(['PATCH']);
+ Request::setFactory(static fn (): Request => new Request(attributes: ['from_factory' => true]));
+
+ $this->assertSame(['application/x-testing'], Request::getMimeTypes('testing'));
+ $this->assertTrue(Request::getHttpMethodParameterOverride());
+ $this->assertSame(['PATCH'], Request::getAllowedHttpMethodOverride());
+ $this->assertTrue(Request::create('/')->attributes->get('from_factory'));
+
+ $subscriber = new class extends AfterEachTestSubscriber {
+ public function flushFrameworkStateForTest(): void
+ {
+ $this->flushFrameworkState();
+ }
+ };
+
+ try {
+ $subscriber->flushFrameworkStateForTest();
+
+ $this->assertSame([], Request::getMimeTypes('testing'));
+ $this->assertFalse(Request::getHttpMethodParameterOverride());
+ $this->assertNull(Request::getAllowedHttpMethodOverride());
+ $this->assertNull(Request::create('/')->attributes->get('from_factory'));
+ } finally {
+ Request::flushState();
+ }
+ }
+
public function testFlushStateAfterTestRunsCustomCallbacksBeforeFrameworkCleanup(): void
{
$subscriber = new class extends AfterEachTestSubscriber {
diff --git a/types/Collections/Arr.php b/types/Collections/Arr.php
new file mode 100644
index 000000000..ae90dfeb2
--- /dev/null
+++ b/types/Collections/Arr.php
@@ -0,0 +1,46 @@
+, array<1|2>}", Arr::divide(['a' => 1, 'b' => 2]));
+assertType('array>', Arr::crossJoin([1], [2], ['third' => 3]));
+
+$array = ['first' => 1, 'second' => 2, 'third' => 3];
+
+assertType('mixed', Arr::random($array));
+assertType('array', Arr::random($array, 2));
+assertType("array<'first'|'second'|'third', 1|2|3>", Arr::sort($array));
+assertType("array<'first'|'second'|'third', 1|2|3>", Arr::sortDesc($array));
+assertType("array<'first'|'second'|'third', 1|2|3>", Arr::where($array, static fn (int $value): bool => $value > 1));
+assertType("array<'first'|'second'|'third', 1|2|3>", Arr::reject($array, static fn (int $value): bool => $value > 1));
+
+/** @var array $nullable */
+$nullable = [];
+assertType('array', Arr::whereNotNull($nullable));
+
+assertType('array{}', Arr::wrap(null));
+assertType('array{1}', Arr::wrap(1));
+assertType("array<'first'|'second'|'third', 1|2|3>", Arr::wrap($array));
+assertType("''", Arr::toCssClasses([]));
+assertType('non-empty-string', Arr::toCssClasses(['hidden' => true]));
+assertType("''", Arr::toCssStyles([]));
+assertType('non-empty-string', Arr::toCssStyles(['display: none' => true]));
+
+/** @var iterable $iterable */
+$iterable = new ArrayObject($array);
+assertType('int|null', Arr::last($iterable));
+assertType('bool', Arr::every($iterable, static fn (int $value, string $key): bool => $value > 0 && $key !== ''));
+assertType('bool', Arr::some($iterable, static fn (int $value, string $key): bool => $value > 0 && $key !== ''));
+
+$target = [];
+assertType('array', Arr::push($target, 'items', new stdClass));
diff --git a/types/Collections/Collection.php b/types/Collections/Collection.php
new file mode 100644
index 000000000..8537ea18d
--- /dev/null
+++ b/types/Collections/Collection.php
@@ -0,0 +1,66 @@
+ 1, 'second' => 2, 'third' => 3]);
+$lazy = new LazyCollection(['first' => 1, 'second' => 2, 'third' => 3]);
+
+/** @return Generator */
+$lazySource = static function (): Generator {
+ yield 'first' => 1;
+ yield 'second' => 2;
+};
+
+assertType('array', $collection->all());
+assertType('Hypervel\Support\Collection', Collection::range(1, 3));
+assertType('Hypervel\Support\Collection', Collection::times(3));
+assertType('Hypervel\Support\Collection', Collection::times(3, static fn (int $number): bool => $number > 1));
+assertType('Hypervel\Support\LazyCollection', LazyCollection::times(3));
+assertType('Hypervel\Support\LazyCollection', LazyCollection::times(3, static fn (int $number): bool => $number > 1));
+assertType('Hypervel\Support\Collection', $collection->flatten());
+
+assertType('1|2|3|null', $collection->min());
+assertType("'1'|'2'|'3'|null", $collection->min(static fn (int $value): string => (string) $value));
+assertType('1|2|3|null', $collection->max());
+assertType("'1'|'2'|'3'|null", $collection->max(static fn (int $value): string => (string) $value));
+
+assertType('float|int', $collection->sum(function (int $value, string $key): int {
+ assertType('1|2|3', $value);
+ assertType('string', $key);
+
+ return $value;
+}));
+assertType('mixed', $collection->sum('amount'));
+
+assertType('stdClass', $collection->reduceInto(new stdClass, static function (stdClass $result, int $value, string $key): void {
+ $result->{$key} = $value;
+}));
+
+assertType('1|2|3', $collection->random());
+assertType('Hypervel\Support\Collection', $collection->random(2));
+assertType('Hypervel\Support\Collection', $collection->random(2, true));
+assertType('1|2|3', $lazy->random());
+assertType('Hypervel\Support\LazyCollection', $lazy->random(2));
+assertType('Hypervel\Support\LazyCollection', $lazy->random(2, true));
+assertType('Hypervel\Support\LazyCollection', LazyCollection::make($lazySource));
+
+/**
+ * @param Enumerable $enumerable
+ */
+function assertEnumerableTypes(Enumerable $enumerable): void
+{
+ assertType('Hypervel\Support\Enumerable', $enumerable->random(2));
+ assertType('Hypervel\Support\Enumerable', $enumerable->random(2, true));
+ assertType('float|int', $enumerable->sum(static fn (int $value): int => $value));
+ assertType('mixed', $enumerable->sum('amount'));
+}
+
+assertEnumerableTypes($collection);
diff --git a/types/Collections/helpers.php b/types/Collections/helpers.php
index 01ea45671..3d1d059ae 100644
--- a/types/Collections/helpers.php
+++ b/types/Collections/helpers.php
@@ -2,6 +2,7 @@
declare(strict_types=1);
+use function Hypervel\Support\enum_value;
use function PHPStan\Testing\assertType;
assertType("'foo'", value('foo', 42));
@@ -11,3 +12,12 @@
return 42;
}, true));
+
+assertType("'foo'", when(true, 'foo'));
+assertType("'foo'", when(true, 'foo', 42));
+assertType('null', when(false, 'foo'));
+assertType('42', when(false, 'foo', 42));
+assertType('42|null', when(random_int(0, 1), 42));
+assertType('42|1337', when(random_int(0, 1), 42, 1337));
+
+assertType("'fallback'", enum_value(null, static fn () => 'fallback'));