Skip to content

Commit e7278d3

Browse files
innocenziBapawe
andauthored
test(database): cover down migration hashing (#1542)
Co-authored-by: Bapawe <[email protected]>
1 parent 1d50336 commit e7278d3

File tree

6 files changed

+42
-13
lines changed

6 files changed

+42
-13
lines changed

docs/1-essentials/07-testing.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ composer phpunit
2222

2323
## Test-specific discovery locations
2424

25-
Tempest will only discover non-dev namespaces defined in composer.json automatically. That means that `{:hl-keyword:require-dev:}` namespaces aren't discovered automatically. Whenever you need Tempest to discover test-specific locations, you may specify them within the `discoverTestLocations()` method of the provided `IntegrationTest` class.
25+
Tempest will only discover non-dev namespaces defined in composer.json automatically. That means that `{:hl-keyword:require-dev:}` namespaces aren't discovered automatically. Whenever you need Tempest to discover test-specific locations, you may specify them within the `discoverTestLocations()` method of the provided `IntegrationTest` class.
2626

2727
On top of that, Tempest _will_ look for files in the `tests/Fixtures` directory and discover them by default. You can override this behavior by providing your own implementation of `discoverTestLocations()`, where you can return an array of `DiscoveryLocation` objects (or nothing).
2828

@@ -46,7 +46,7 @@ final class HomeControllerTest extends IntegrationTest
4646
If you want to test code that interacts with the database, your test class can call the `setupDatabase()` method. This method will create and migrate a clean database for you on the fly.
4747

4848
```php
49-
class TodoControllerTest extends IntegrationTest
49+
final class TodoControllerTest extends IntegrationTest
5050
{
5151
protected function setUp(): void
5252
{
@@ -60,8 +60,6 @@ class TodoControllerTest extends IntegrationTest
6060
Most likely, you'll want to use a test-specific database connection. You can create a `database.config.php` file anywhere within test-specific discovery locations, and Tempest will use that connection instead of the project's default. For example, you can create a file `tests/Fixtures/database.config.php` like so:
6161

6262
```php tests/Fixtures/database.config.php
63-
<?php
64-
6563
use Tempest\Database\Config\SQLiteConfig;
6664

6765
return new SQLiteConfig(
@@ -72,7 +70,7 @@ return new SQLiteConfig(
7270
By default, no tables will be migrated. You can choose to provide a list of migrations that will be run for every test that calls `setupDatabase()`, or you can run specific migrations on a per-test basis.
7371

7472
```php
75-
class TodoControllerTest extends IntegrationTest
73+
final class TodoControllerTest extends IntegrationTest
7674
{
7775
protected function migrateDatabase(): void
7876
{
@@ -85,7 +83,7 @@ class TodoControllerTest extends IntegrationTest
8583
```
8684

8785
```php
88-
class TodoControllerTest extends IntegrationTest
86+
final class TodoControllerTest extends IntegrationTest
8987
{
9088
public function test_create_todo(): void
9189
{

packages/database/src/Migrations/MigrationManager.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ private function getTableDefinitions(): array
306306
);
307307
}
308308

309-
private function getMigrationHash(MigratesUp $migration): string
309+
private function getMigrationHash(MigratesUp|MigratesDown $migration): string
310310
{
311311
$sql = '';
312312

packages/database/src/Migrations/RunnableMigrations.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ final class RunnableMigrations implements IteratorAggregate
1919
public function __construct(
2020
private array $migrations = [],
2121
) {
22-
usort($this->migrations, static fn (MigratesUp $a, MigratesUp $b) => strnatcmp($a->name, $b->name));
22+
usort($this->migrations, static fn (MigratesUp|MigratesDown $a, MigratesUp|MigratesDown $b) => strnatcmp($a->name, $b->name));
2323
}
2424

2525
public function getIterator(): Traversable

src/Tempest/Framework/Testing/IntegrationTest.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,21 +166,24 @@ protected function setupBaseRequest(): self
166166
protected function setupDatabase(): self
167167
{
168168
$migrationManager = $this->container->get(MigrationManager::class);
169-
170169
$migrationManager->dropAll();
171170

172171
$this->migrateDatabase();
173172

174173
return $this;
175174
}
176175

176+
/**
177+
* Creates the migration table. You may override this method to provide more migrations to run for every tests in this file.
178+
*/
177179
protected function migrateDatabase(): void
178180
{
179-
$this->migrate(
180-
CreateMigrationsTable::class,
181-
);
181+
$this->migrate(CreateMigrationsTable::class);
182182
}
183183

184+
/**
185+
* Migrates the specified migration classes.
186+
*/
184187
protected function migrate(string|object ...$migrationClasses): void
185188
{
186189
$migrationManager = $this->container->get(MigrationManager::class);

tests/Integration/Framework/Commands/MigrateRehashCommandTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace Tests\Tempest\Integration\Framework\Commands;
66

7-
use PHPUnit\Framework\Assert;
87
use Tempest\Console\ExitCode;
98
use Tempest\Database\Migrations\Migration;
109
use Tempest\Framework\Commands\MigrateFreshCommand;

tests/Integration/Framework/Commands/MigrateValidateCommandTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44

55
namespace Tests\Tempest\Integration\Framework\Commands;
66

7+
use PHPUnit\Framework\Attributes\PreCondition;
78
use Tempest\Console\ExitCode;
9+
use Tempest\Database\MigratesDown;
810
use Tempest\Database\Migrations\Migration;
11+
use Tempest\Database\Migrations\RunnableMigrations;
12+
use Tempest\Database\QueryStatement;
13+
use Tempest\Database\QueryStatements\RawStatement;
914
use Tempest\Framework\Commands\MigrateFreshCommand;
1015
use Tempest\Framework\Commands\MigrateValidateCommand;
1116
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
@@ -15,6 +20,20 @@
1520
*/
1621
final class MigrateValidateCommandTest extends FrameworkIntegrationTestCase
1722
{
23+
#[PreCondition]
24+
protected function configure(): void
25+
{
26+
$this->container->singleton(
27+
className: RunnableMigrations::class,
28+
definition: new RunnableMigrations(
29+
migrations: [
30+
...iterator_to_array($this->container->get(RunnableMigrations::class)->getIterator()),
31+
new DownMigrationForRehash(),
32+
],
33+
),
34+
);
35+
}
36+
1837
public function test_migration_validate_command_verifies_valid_migrations(): void
1938
{
2039
$this->console
@@ -53,3 +72,13 @@ public function test_migration_validate_command_fails_when_migration_file_is_mis
5372
->assertExitCode(ExitCode::ERROR);
5473
}
5574
}
75+
76+
final class DownMigrationForRehash implements MigratesDown
77+
{
78+
private(set) string $name = '2025-10-12_down_migration_for_rehash_test';
79+
80+
public function down(): QueryStatement
81+
{
82+
return new RawStatement('SELECT 1');
83+
}
84+
}

0 commit comments

Comments
 (0)