cloak/peridot-cloak-plugin
A Peridot plugin that brings Cloak into your PHP test suite, letting you wire up its features directly from your specs with minimal configuration. Install via Composer, enable the plugin, and keep your tests readable and expressive.
This is a Peridot plugin, not a Laravel package — there is no service provider to register, no config file to publish, and nothing that hooks into the framework. It only matters if you have (or are considering) Peridot as the test runner for some part of your code — typically a library, a package you are extracting out of a Laravel app, or a small service where you want BDD-style describe/it specs. Cloak supplies the object-double machinery; this plugin wires it into Peridot's scope/lifecycle so you can reach it from inside a .spec.php file.
Minimal steps:
composer require --dev cloak/peridot-cloak-pluginsrc/ (the class that attaches to Peridot's emitter), then Cloak's own README for the double API. The registration snippet is the whole contract; everything else is Cloak.peridot.php file that Peridot loads from the working directory. It is an event subscriber, so you hand it the emitter Peridot passes to the bootstrap closure.Register once, globally. Peridot reads a single peridot.php per run, so plugin registration lives there and applies to every suite. If you need it only for some suites, gate it on an env var or on the presence of a spec/unit path rather than maintaining multiple bootstrap files.
Use the scope, not globals. Peridot injects a scope object into each spec. The plugin's job is to make Cloak's factory available through that scope, so arrange doubles in beforeEach and let them fall out of scope between specs. This keeps doubles isolated per example — the classic failure mode in Peridot is a double arranged in one it leaking into the next because it was stashed on a shared object.
describe('InvoiceCalculator', function () {
beforeEach(function () {
$this->repo = $this->cloak(InvoiceRepository::class); // helper name from the README
});
it('sums open invoices', function () {
// arrange via Cloak, exercise, assert
});
});
Bridging a Laravel app. Cloak knows nothing about the container, facades, or Eloquent. If your spec needs a real collaborator resolved from Laravel, boot the app first (a tiny custom plugin, or a peridot.php closure that requires bootstrap/app.php), resolve the concrete object from the container, and then wrap/stub the parts you want to control. Do not expect Cloak to mock a facade or to understand app()->bind() — you are resolving first and doubling second.
Split your runners deliberately. The pragmatic layout for a Laravel codebase is Peridot + this plugin for fast, isolated domain specs, and PHPUnit/Pest for HTTP, database, and feature tests. Wire both into composer.json scripts ("test": ["phpunit", "peridot"]) and into CI as separate jobs so a Peridot failure is obvious and doesn't get lost behind a PHPUnit summary.
Prefer constructor injection in the code under test. Because the plugin operates at the object level, code that pulls dependencies out of app() mid-method is painful to double. Nudging the codebase toward explicit constructor dependencies makes these specs trivial and is usually a bigger win than the plugin itself.
composer.json, and be prepared to fork or copy the subscriber into your own test bootstrap rather than wait for a fix.each()-style constructs). If it won't run, the plugin is small enough to reimplement — the registration is a handful of lines against Peridot's emitter.composer update is the most likely way to break the integration.peridot.php is being loaded from the directory you think it is (Peridot resolves it from cwd, so running from a subdirectory silently skips it). Second is checking the subscriber actually attached to the emitter without throwing.$this->mock() equivalent to Laravel's built-in helpers, no facade swapping, no automatic container rebinding. Every bridge is manual.beforeEach; do not accumulate expectations across examples. If an assertion about an interaction fails, verify the double was actually passed into the object under test — a double that never receives the call looks identical to a double whose expectation was never met.How can I help you explore Laravel packages today?