diff --git a/tests/TestCase.php b/tests/TestCase.php index d6d1b15f3..48957614d 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -10,6 +10,7 @@ use Illuminate\Database\Schema\Builder as SchemaBuilder; use Illuminate\Filesystem\Filesystem; use Illuminate\Foundation\Testing\DatabaseTruncation; +use Illuminate\Foundation\Testing\RefreshDatabaseState; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Queue; @@ -64,6 +65,11 @@ abstract class TestCase extends BaseTestCase */ private static array $workers = []; + /** + * @var array}>|null + */ + private static ?array $truncationSchema = null; + /** * @var arraytruncationSchema()) { + RefreshDatabaseState::$migrated = false; + } + + if (! RefreshDatabaseState::$migrated) { + // A fresh migration also invalidates Laravel's per-connection table + // cache; retaining it can miss new tables or query removed ones. + static::$allTables = []; + } + } + protected function setUpDatabaseTruncation(): void { + self::$truncationSchema = $this->truncationSchema(); // Testbench's PendingCommand binds a mocked OutputStyle while it runs // migrations. Remove that per-command binding so application commands // invoked by a test can write to the output buffer supplied by Artisan. @@ -426,6 +449,30 @@ protected static function workerDiagnostics(): array return $diagnostics; } + /** + * @return array}> + */ + private function truncationSchema(): array + { + $schema = []; + foreach ($this->connectionsToTruncate() as $name) { + $connection = $this->app->make('db') + ->connection($name); + $tables = $connection->getSchemaBuilder() + ->getTableListing(); + sort($tables); + $schema[$connection->getName()] = [ + 'database' => $connection->getDatabaseName(), + 'prefix' => $connection->getTablePrefix(), + 'tables' => $tables, + ]; + } + + ksort($schema); + + return $schema; + } + private static function normalizeJsonObject(array $value): array { $normalized = array_map( diff --git a/tests/Unit/TestDatabaseSchemaBoundaryTest.php b/tests/Unit/TestDatabaseSchemaBoundaryTest.php new file mode 100644 index 000000000..81233ad30 --- /dev/null +++ b/tests/Unit/TestDatabaseSchemaBoundaryTest.php @@ -0,0 +1,51 @@ +insert([ + 'id' => 'schema-boundary-probe', + 'workflow_class' => self::class, + 'workflow_type' => 'test.schema-boundary', + 'run_count' => 0, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + self::assertFalse(Schema::hasTable('users')); + self::assertFalse(Schema::hasTable('jobs')); + self::assertSame(1, DB::table('workflow_instances')->count()); + } + + #[Depends('testAnotherMigrationScopeCanLeaveOnlyWorkflowTables')] + public function testNextTestRestoresTheWholeSchemaAndClearsCommittedRows(): void + { + foreach (['users', 'jobs', 'workflow_instances', 'workflow_runs'] as $table) { + self::assertTrue(Schema::hasTable($table), "Expected [{$table}] to be restored."); + self::assertSame(0, DB::table($table)->count(), "Expected [{$table}] to be empty."); + } + self::assertGreaterThan(0, DB::table('migrations')->count()); + } +}