Weave Code
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

Pest Plugin Snapshots Laravel Package

spatie/pest-plugin-snapshots

Adds snapshot testing to Pest via Spatie’s snapshot assertions. Compare strings or JSON against stored snapshots with helper functions or Pest expectations. Ideal for stable output/regression testing in PHP projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package in your Laravel/Pest project:

    composer require spatie/pest-plugin-snapshots --dev
    
  2. Configure snapshot storage (default: tests/__snapshots__/). No additional config is needed unless customizing paths.

  3. First test case (string snapshot):

    use function Spatie\Snapshots\assertMatchesSnapshot;
    
    it('matches a string snapshot', function () {
        $output = 'Hello, World!';
        assertMatchesSnapshot($output);
    });
    

    Run the test. The package creates a snapshot file (e.g., tests/__snapshots__/TestClass/test_matches_a_string_snapshot.txt) with the output.

  4. Update snapshots (when intentionally changing outputs):

    ./vendor/bin/pest --update-snapshots
    

Key First Use Cases

  • API responses: Validate JSON structures without manual assertions.
    it('returns a valid user response', function () {
        $response = $this->getJson('/api/user');
        expect($response->json())->toMatchJsonSnapshot();
    });
    
  • Blade templates/emails: Test rendered HTML.
    it('renders the welcome email', function () {
        $email = $this->mail->html('emails.welcome');
        expect($email)->toMatchSnapshot();
    });
    
  • Livewire/Inertia components: Capture component outputs.
    it('renders the dashboard component', function () {
        $component = new Dashboard;
        expect($component->render()->toHtml())->toMatchSnapshot();
    });
    

Implementation Patterns

Core Workflows

  1. Assertion-Based Testing (explicit assertions):

    use function Spatie\Snapshots\{assertMatchesSnapshot, assertDoesNotMatchSnapshot};
    
    it('matches a snapshot', function () {
        $data = ['name' => 'John', 'active' => true];
        assertMatchesSnapshot(json_encode($data));
    });
    
    it('fails on mismatch', function () {
        $data = ['name' => 'John', 'active' => false];
        assertDoesNotMatchSnapshot(json_encode($data)); // Fails if snapshot exists
    });
    
  2. Expectation-Based Testing (Pest fluent syntax):

    it('uses expectations', function () {
        $output = $this->get('/report')->content();
        expect($output)->toMatchSnapshot();
    });
    
  3. JSON-Specific Snapshots (for API responses):

    it('validates JSON structure', function () {
        $response = $this->getJson('/api/data');
        expect($response->json())->toMatchJsonSnapshot();
    });
    
  4. Image Snapshots (for PDFs, canvas, or image generation):

    it('matches a generated image', function () {
        $image = $this->generateReportImage();
        expect($image)->toMatchImageSnapshot();
    });
    

Integration Tips

  • Laravel HTTP Tests: Combine with actingAs() or withHeaders():
    it('authenticated response matches snapshot', function () {
        $this->actingAs($user);
        expect($this->get('/dashboard')->content())->toMatchSnapshot();
    });
    
  • Database-Driven Tests: Use refreshDatabase() or withDatabaseModifications() to ensure consistent snapshots:
    it('snapshot with fresh database', function () {
        $this->refreshDatabase();
        expect($this->get('/report')->json())->toMatchJsonSnapshot();
    });
    
  • Parameterized Snapshots: Use Pest’s with() or withTable() to generate snapshots for multiple inputs:
    it('matches snapshots for different locales', function (string $locale) {
        $this->withLocale($locale);
        expect($this->get('/home')->content())->toMatchSnapshot();
    })->with(['en', 'fr', 'es']);
    
  • Custom Snapshot Directories: Override the default path in pest.php:
    use Spatie\Snapshots\Snapshot;
    
    Snapshot::create()->setPath(__DIR__.'/custom_snapshots');
    

Advanced Patterns

  1. Snapshot Descriptions: Add context to snapshots using describe():
    it('has a descriptive snapshot', function () {
        $output = $this->get('/complex-report')->content();
        expect($output)->toMatchSnapshot()->describe('Full report HTML with charts');
    });
    
  2. Partial Snapshots: Use assertMatchesSnapshotPartial() for large outputs where only parts change:
    it('matches partial snapshot', function () {
        $largeOutput = $this->get('/large-data')->content();
        assertMatchesSnapshotPartial($largeOutput, 'unique-section-id');
    });
    
  3. Snapshot Diffs: Configure diff tools (e.g., vscode-diff, kdiff3) in phpunit.xml:
    <php>
        <env name="SNAPSHOT_DIFF_TOOL" value="vscode-diff"/>
    </php>
    
  4. CI/CD Integration: Update snapshots on intentional changes:
    # In CI (e.g., GitHub Actions)
    if [ "$UPDATE_SNAPSHOTS" = "true" ]; then
      ./vendor/bin/pest --update-snapshots
    fi
    

Gotchas and Tips

Common Pitfalls

  1. Snapshot ID Conflicts:

    • Issue: Duplicate snapshot IDs can occur if tests are reordered or renamed.
    • Fix: Ensure test names are unique. Upgrade to v2.3.1+ which fixes ID increment regression.
    • Debug: Check tests/__snapshots__/ for duplicate filenames.
  2. Non-Deterministic Data:

    • Issue: Snapshots fail due to timestamps, UUIDs, or dynamic IDs in outputs.
    • Fix: Preprocess data before snapping:
      $json = json_encode($response->json());
      $json = preg_replace('/"timestamp": "\d+"/', '"timestamp": "REDACTED"', $json);
      expect($json)->toMatchJsonSnapshot();
      
    • Tip: Use assertMatchesSnapshotPartial() for dynamic sections.
  3. Large Files:

    • Issue: Snapshots for large JSON/HTML files slow down tests.
    • Fix: Use assertMatchesSnapshotPartial() or exclude static sections (e.g., headers/footers).
  4. Case Sensitivity:

    • Issue: JSON snapshots may fail due to key order or whitespace differences.
    • Fix: Normalize JSON before snapping:
      $normalized = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_SORT_KEYS);
      expect($normalized)->toMatchJsonSnapshot();
      
  5. Image Snapshots:

    • Issue: Image snapshots fail due to minor pixel differences (e.g., anti-aliasing).
    • Fix: Use assertMatchesImageSnapshotWithTolerance():
      expect($image)->toMatchImageSnapshotWithTolerance(0.1); // 10% tolerance
      

Debugging Tips

  • View Snapshots: Open tests/__snapshots__/ to inspect stored outputs.
  • Update Snapshots: Run ./vendor/bin/pest --update-snapshots to refresh expectations.
  • Diff Tool: Configure SNAPSHOT_DIFF_TOOL in .env or phpunit.xml for visual diffs:
    export SNAPSHOT_DIFF_TOOL="kdiff3"
    
  • Verbose Output: Enable debug mode in pest.php:
    Snapshot::create()->setDebug(true);
    
  • Exclude Files: Use .gitignore to exclude snapshot directories if needed:
    tests/__snapshots__/
    

Extension Points

  1. Custom Snapshot Paths:
    Snapshot::create()->setPath(__DIR__.'/custom_path');
    
  2. Snapshot Naming: Override the default naming convention by implementing SnapshotIdAware:
    use Spatie\Snapshots\SnapshotIdAware;
    
    class CustomTest extends TestCase implements SnapshotIdAware {
        public function getSnapshotId(): string {
            return 'custom_' . $this->getName();
        }
    }
    
  3. Pre/Post-Processing: Extend snapshot logic by subclassing Spatie\Snapshots\Snapshot:
    use Spatie\Snapshots\Snapshot;
    
    class CustomSnapshot extends Snapshot {
        protected function getContent(): string {
            $content = parent::getContent();
            return str_replace('REDACTED', '[FILTERED]', $content);
        }
    }
    
  4. Integration with Factories: Use Pest factories to generate consistent test data for snapshots:
    it('matches factory-generated snapshot', function () {
        $user = User::factory()->create();
        expect($
    
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony