Skip to content

Instantly share code, notes, and snippets.

@mortenscheel
Last active September 13, 2024 13:03
Show Gist options
  • Save mortenscheel/332f15c04cc91fe8549aed066f73bfdf to your computer and use it in GitHub Desktop.
Save mortenscheel/332f15c04cc91fe8549aed066f73bfdf to your computer and use it in GitHub Desktop.
A replacement for Laravel's LazilyRefreshDatabase trait that only runs migrate:fresh if necessary.
<?php
namespace Tests;
use Artisan;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\RefreshDatabaseState;
use Illuminate\Support\Str;
trait LazilyRefreshDatabaseIfNecessary
{
use RefreshDatabase {
refreshDatabase as baseRefreshDatabase;
}
/**
* Define hooks to migrate the database before and after each test.
*
* @return void
*/
public function refreshDatabase()
{
$database = $this->app->make('db');
$callback = function () {
if (RefreshDatabaseState::$lazilyRefreshed) {
return;
}
RefreshDatabaseState::$lazilyRefreshed = true;
if (property_exists($this, 'mockConsoleOutput')) {
$shouldMockOutput = $this->mockConsoleOutput;
$this->mockConsoleOutput = false;
}
if (!RefreshDatabaseState::$migrated) {
if (! $this->hasPendingMigrations() && ! $this->hasDirtyState()) {
RefreshDatabaseState::$migrated = true;
}
}
$this->baseRefreshDatabase();
if (property_exists($this, 'mockConsoleOutput')) {
$this->mockConsoleOutput = $shouldMockOutput;
}
};
$database->beforeStartingTransaction($callback);
$database->beforeExecuting($callback);
$this->beforeApplicationDestroyed(function () {
RefreshDatabaseState::$lazilyRefreshed = false;
});
}
protected function hasPendingMigrations(): bool
{
Artisan::call('migrate:status --pending --no-ansi');
$output = Artisan::output();
return !Str::contains($output, 'No pending migrations');
}
protected function hasDirtyState(): bool
{
// Check if DB state is dirty
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment