Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Crucible Laravel Package

cruciblephp/crucible

Crucible is a PHP package that provides a clean, extensible foundation for building robust applications. It pairs sensible defaults with flexible configuration and a developer-friendly API, helping teams ship maintainable features faster.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a Pest-compatible test runner for Laravel: it collects *Test.php files, honours Pest.php configuration (class bindings, traits, groups, hooks, ->in() scoping), and executes them with Pest's semantics for describe() blocks and lifecycle hooks. v1.1.7 is a parity release — nothing new to learn, but four behaviours changed so the runner now matches Pest exactly.

Minimal steps:

  1. composer require --dev <vendor>/<package> and confirm the binary/plugin is registered (php artisan about or composer show <vendor>/<package>).
  2. Open tests/Pest.php first — it is the package's whole configuration surface. Read the existing uses(...)->in(...) and beforeEach/afterEach calls before touching anything else.
  3. Run the existing suite unchanged on v1.1.7 before writing new tests. This release can refuse files that previously ran (see Gotchas), so establish a green baseline first.
  4. First real use case: take one legacy TestCase-style file that relies on global setup and rewrite it as a describe() block with its own beforeEach, leaving the shared Pest.php hooks alone. Run it in isolation (--filter) and then with the full suite to verify hook ordering.

Where to look when something is off: the collection phase, not the run phase. Three of the four v1.1.7 fixes are collection-time decisions (which hooks attach to which tests, whether a file is refused), so if a test "doesn't see" a hook, the problem is almost always in how the file was collected rather than in the test body.

Implementation Patterns

Scope shared setup in Pest.php with absolute paths. uses(RefreshDatabase::class)->in(__DIR__) is the idiom the release notes fix, and it is the one you want in tests/Pest.php. Prefer __DIR__.'/Feature' over relative strings so the scoping is unambiguous and survives changes to the working directory.

// tests/Pest.php
uses(Tests\TestCase::class)->in(__DIR__);
uses(RefreshDatabase::class)->in(__DIR__.'/Feature');

afterEach(function () {
    // global teardown — now runs BEFORE each file's own afterEach
})->in(__DIR__);

Group lifecycle hooks by the block that owns them. Put hooks inside a describe() only for state that block introduces. The v1.1.7 fix means a beforeEach inside describe('Billing') no longer leaks into sibling tests declared earlier in the file, which makes this a safe, local pattern:

describe('Billing', function () {
    beforeEach(fn () => $this->tenant = Tenant::factory()->create());

    test('charges the card', function () { /* has $this->tenant */ });
});

test('unrelated', function () { /* does NOT have $this->tenant */ });

Never use beforeAll/afterAll inside describe(). Since v1.1.7 these are rejected at collection and the entire file is refused. If you need once-per-file setup, do it at file top level with beforeAll, or hoist it into Pest.php scoped with ->in(). For shared fixtures across a nested block, beforeEach plus a memoised static or a container singleton is the portable answer.

Order-sensitive teardown. Because the global afterEach now runs before the file's own, structure teardown outside-in: the file's afterEach should assume the global one has already cleaned up. Typical example — the global hook resets the container/cache, the file-level hook asserts on database state; that ordering is now the supported one.

Migration pattern for the ->in() fix. Files that previously "worked" under a non-matching ->in(__DIR__) were running with no base class, traits, groups, or hooks at all — i.e. silently naked. After upgrading, run the suite and expect a burst of new failures/successes in exactly those files. Treat the upgrade as a behaviour change per file, and migrate in one pass rather than interleaving with feature work.

Debugging workflow for hook problems. Reduce to a single file with two tests, one before and one after the describe() block, then move hooks between Pest.php and the block until behaviour matches intent. Use whatever list/collection flag the package exposes to print collected hooks per test — this is far faster than dd() inside a hook.

Gotchas and Tips

  • Files can now be refused entirely. beforeAll/afterAll inside describe() is a hard collection error. Every test in that file stops running — including ones that would otherwise pass. In CI this looks like a sudden mass of "not run" rather than failures; check the collection output first.
  • Silent-drop bugs hide the real coverage. Any ->in() that "matched nothing" before v1.1.7 means those tests were running without RefreshDatabase, without your base TestCase, without custom expectations. A suite that was green may have been green because the setup never applied. Grep Pest.php for ->in( and verify each path resolves to at least one file after upgrading.
  • ->in() takes directories, not globs. ->in(__DIR__.'/*Test.php') is not the same as ->in(__DIR__); paths select every file beneath them.
  • Ordering with describe() nesting is declaration order, not depth. A file-level beforeEach declared after the describe() block still runs for tests in that block, in file-declaration order. If you rely on "Pest.php first, always", verify with the global afterEach change too — that one, and only that one, is now inverted.
  • Config caching. If the package participates in Laravel's config/collection cache, clear it between upgrades or you will debug stale hook graphs.
  • --filter doesn't change semantics. Hooks are still attached at collection for the whole file; filtering only skips execution. A file refused for beforeAll in describe() stays refused even when filtering to one test.
  • Extension points. Pest.php is the only supported extension point: base class via uses(), traits, groups, and hooks. There is no per-directory config file — resist adding one, since it will diverge from Pest parity, which is what this package spends its releases chasing.
  • Pin the patch. Given three of four fixes are semantic corrections, pin ^1.1.7 in composer.json and upgrade deliberately with a full-suite run, not as a lockfile refresh during an unrelated branch.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums