quotevelocity/novaunit
NovaUnit brings a PHPUnit-friendly testing layer to Laravel Nova, letting you unit test resources, fields, actions, filters, lenses, and metrics without a browser. Write expressive assertions for Nova components right inside your existing test suite.
Architecture fit. NovaUnit is a dev-only Composer dependency that lives entirely in the test harness — no production runtime footprint, no shipping code, no data-layer or request-path changes. That makes it architecturally low-consequence to adopt and trivially reversible. The fit is conditional on two facts about our stack: (1) we run Laravel Nova, and (2) we own non-trivial custom Nova components — reactive Fields, Actions with authorization and side effects, Filters with real query logic, Cards, Lenses, Metrics. If our Nova usage is config-only (resources and field declarations, no custom classes), there is nothing at this layer to test and the dependency earns nothing. It extends PHPUnit rather than introducing a runner, so it fits an existing PHPUnit-standardized team; Pest support is claimed but not first-class, and a Pest-first codebase risks a split testing idiom.
Integration feasibility. Cheap on paper: install as a pinned dev dependency, add a tests/Nova testsuite, create one base TestCase, write tests. The real prerequisites are organizational, not technical — every CI runner must authenticate to Nova's credential-gated Composer repository, and that is a shared-secret/procurement task that should be resolved before the spike, not during rollout. Two pre-flight unknowns must be closed in the spike: the canonical Packagist name (quotevelocity/novaunit in the description vs. qvelocity/NovaUnit in the repo — a mismatch is an immediate install failure or, worse, a silent fork), and the supported Nova/PHP/PHPUnit matrix read from composer.json, not the README, since documentation lags at this adoption level.
Technical risk. The dominant risk is structural: the harness and the thing it tests break at the same time. NovaUnit necessarily reaches into Nova internals, which sit outside Nova's backward-compatibility promise, so a Nova minor release can rewrite our test suite's failure mode overnight — precisely when we need the safety net. Compounding that, adoption signal is thin: 9 stars, 0 dependents, single maintainer, MIT, and a release date (2026-03-27) that should be treated as unverified. This is code we adopt, not a product we buy; the low opportunity score reflects the absence of community validation and a bus factor of one. The mitigation is not avoidance — it is pinning an exact version, keeping our base test case thin so the package is swappable, and writing down a fork trigger in advance (e.g. two blocking issues open for 30 days, or no compatible release within N weeks of a Nova major). Forking is viable precisely because it is MIT and dev-only — but only if the trigger is pre-agreed.
Key questions for the spike.
composer.json confirm it?Stack fit. Laravel + Nova + PHPUnit, with PHPUnit as the assumed runner. The package adds assertions and a base test case; it does not touch application code. That means no migration of existing tests is required — adoption is additive, which is the single strongest argument for doing it.
Migration path. Do not start a big-bang conversion. Stand up a new tests/Nova testsuite alongside the existing tests/Feature, with a single app-owned base TestCase that extends NovaUnit's base case. That one file is the migration seam: if we abandon the package, we rewrite a base class, not two hundred tests. Retrofit opportunistically — when an engineer is already touching an HTTP-driven Nova feature test, rewrite that one into a component test where it will be faster and more precise. Existing feature tests remain a valid safety net and stay in place.
Compatibility discipline. Install pinned to an exact version, no caret. Treat the package's own tests/ directory as the authoritative documentation for assertion signatures and base-case setup — read it before the README. Confirm Nova repository credentials exist as a shared CI secret before the spike concludes.
Sequencing.
TestCase, tests/Nova suite, CI job split so the Nova suite runs on every PR as the fastest gate in the pipeline.RefreshDatabase). This proves the value proposition; nothing else does.Maintenance. Low steady-state cost: a dev dependency, a base class, and tests we'd want anyway. The concentrated maintenance event is every Nova upgrade, where we should expect to repair the harness before the tests. Naming an owner and a fork trigger converts an unbounded risk into a scheduled task.
Support. No vendor, no SLA, single maintainer, effectively no community. Internal ownership is the support model. That is acceptable for a dev-only MIT dependency of this size — the failure mode is a broken test suite, not broken production — but it must be stated plainly to stakeholders rather than discovered during an upgrade.
Scaling. Test count scales linearly and cheaply, provided database usage stays deliberate: components that don't touch the database must not boot RefreshDatabase. The value proposition — seconds, not minutes — depends on most tests being pure in-memory field/action assertions. A suite where every test migrates is a suite engineers start skipping, and a skipped suite is worse than none because it launders confidence.
Failure modes to plan for.
Ramp-up. Low for engineers fluent in PHPUnit — roughly a day, most of it spent reading the package's own test suite. The genuine ramp is Nova internals knowledge: the fluent helpers obscure what they inspect, so debugging starts with dumping the resolved component object and running isolated via --filter against the Nova testsuite. Expect the first Action test to take longer than the estimate and subsequent ones to be fast.
Success measures. Nova suite runtime under a minute and green on every PR; every destructive Action covered by an authorization test; Nova major upgrade executed on our cadence with a quantified, reversible blast radius rather than an unquantified gamble; zero production incidents attributable to an untested Nova customization.
How can I help you explore Laravel packages today?