From 68ed294b821f7a8dd20fd91e855c56f49b12838e Mon Sep 17 00:00:00 2001 From: myrmidex Date: Sun, 16 Aug 2026 10:38:00 +0200 Subject: [PATCH] 46 - Squash migrations and run CI against sqlite --- .env.testing | 7 +- .forgejo/workflows/ci.yml | 30 +--- .forgejo/workflows/images.yml | 2 +- .../0001_01_01_000000_create_assets_table.php | 25 --- .../0001_01_01_000001_create_users_table.php | 53 ------- ...07_10_152716_create_asset_prices_table.php | 28 ---- ...5_07_12_221324_create_milestones_table.php | 29 ---- ...026_05_02_000001_create_trackers_table.php | 50 ------ ...2026_05_02_000002_create_entries_table.php | 30 ---- ..._tracker_to_milestones_drop_from_users.php | 44 ------ ...026_08_15_000001_drop_milestones_table.php | 26 ---- ...002_add_count_to_trackers_drop_entries.php | 60 -------- ...6_08_15_000003_drop_assets_and_pricing.php | 51 ------ ...6_08_15_000004_drop_users_and_sessions.php | 57 ------- ...026_08_16_000000_create_trackers_table.php | 37 +++++ docker/build/Dockerfile.ci | 7 +- phpstan.neon | 8 - phpunit.xml | 1 - tests/Feature/CountBackfillMigrationTest.php | 145 ------------------ tests/Feature/DropAssetsMigrationTest.php | 68 -------- tests/Feature/DropUsersMigrationTest.php | 86 ----------- 21 files changed, 49 insertions(+), 795 deletions(-) delete mode 100644 database/migrations/0001_01_01_000000_create_assets_table.php delete mode 100644 database/migrations/0001_01_01_000001_create_users_table.php delete mode 100644 database/migrations/2025_07_10_152716_create_asset_prices_table.php delete mode 100644 database/migrations/2025_07_12_221324_create_milestones_table.php delete mode 100644 database/migrations/2026_05_02_000001_create_trackers_table.php delete mode 100644 database/migrations/2026_05_02_000002_create_entries_table.php delete mode 100644 database/migrations/2026_05_02_000003_add_tracker_to_milestones_drop_from_users.php delete mode 100644 database/migrations/2026_08_15_000001_drop_milestones_table.php delete mode 100644 database/migrations/2026_08_15_000002_add_count_to_trackers_drop_entries.php delete mode 100644 database/migrations/2026_08_15_000003_drop_assets_and_pricing.php delete mode 100644 database/migrations/2026_08_15_000004_drop_users_and_sessions.php create mode 100644 database/migrations/2026_08_16_000000_create_trackers_table.php delete mode 100644 tests/Feature/CountBackfillMigrationTest.php delete mode 100644 tests/Feature/DropAssetsMigrationTest.php delete mode 100644 tests/Feature/DropUsersMigrationTest.php diff --git a/.env.testing b/.env.testing index e0b6eaa..989e21a 100644 --- a/.env.testing +++ b/.env.testing @@ -1,11 +1,8 @@ APP_ENV=testing APP_KEY=base64:+7T2RuonhTIij1yLp3rTOv2uQlYJh0TQulu20MlCA+s= -DB_CONNECTION=mysql -DB_HOST=db -DB_DATABASE=testing -DB_USERNAME=incr_user -DB_PASSWORD=incr_password +DB_CONNECTION=sqlite +DB_DATABASE=:memory: SESSION_DRIVER=array CACHE_STORE=array diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 5a58da1..790dc78 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -10,17 +10,11 @@ jobs: ci: runs-on: docker container: - image: forge.lvl0.xyz/lvl0/incr-ci:php8.3-2 - - services: - db: - image: mysql:8.0 - env: - MYSQL_DATABASE: testing - MYSQL_USER: incr_user - MYSQL_PASSWORD: incr_password - MYSQL_ROOT_PASSWORD: root_password + image: forge.lvl0.xyz/lvl0/incr-ci:php8.3-3 + # No service container: on this runner a job container cannot reach one + # (the service starts fine but lands on a different network). Tests run + # against sqlite in memory instead — see .env.testing. steps: - uses: https://data.forgejo.org/actions/checkout@v4 @@ -37,22 +31,6 @@ jobs: - name: Prepare environment run: cp .env.testing .env - - name: Wait for MySQL - run: | - for i in $(seq 1 30); do - if php -r 'exit(@fsockopen("db", 3306) ? 0 : 1);'; then - echo "MySQL is up after ${i} attempt(s)" - exit 0 - fi - echo "Waiting for MySQL... ($i/30)" - sleep 2 - done - echo "MySQL never became reachable on db:3306" >&2 - exit 1 - - - name: Run migrations - run: php artisan migrate --force - - name: Lint run: vendor/bin/pint --test diff --git a/.forgejo/workflows/images.yml b/.forgejo/workflows/images.yml index a098759..9d83591 100644 --- a/.forgejo/workflows/images.yml +++ b/.forgejo/workflows/images.yml @@ -20,7 +20,7 @@ jobs: include: - name: incr-ci file: docker/build/Dockerfile.ci - version: php8.3-2 + version: php8.3-3 steps: - uses: https://data.forgejo.org/actions/checkout@v4 diff --git a/database/migrations/0001_01_01_000000_create_assets_table.php b/database/migrations/0001_01_01_000000_create_assets_table.php deleted file mode 100644 index a27ba44..0000000 --- a/database/migrations/0001_01_01_000000_create_assets_table.php +++ /dev/null @@ -1,25 +0,0 @@ -id(); - $table->string('symbol')->unique(); - $table->string('full_name')->nullable(); - $table->timestamps(); - - $table->index('symbol'); - }); - } - - public function down(): void - { - Schema::dropIfExists('assets'); - } -}; diff --git a/database/migrations/0001_01_01_000001_create_users_table.php b/database/migrations/0001_01_01_000001_create_users_table.php deleted file mode 100644 index 4f7f9b6..0000000 --- a/database/migrations/0001_01_01_000001_create_users_table.php +++ /dev/null @@ -1,53 +0,0 @@ -id(); - $table->string('name'); - $table->string('email')->unique(); - $table->timestamp('email_verified_at')->nullable(); - $table->string('password'); - $table->foreignId('asset_id')->nullable()->constrained()->onDelete('set null'); - $table->boolean('price_tracking_enabled')->default(false); - $table->rememberToken(); - $table->timestamps(); - - $table->index('asset_id'); - }); - - Schema::create('password_reset_tokens', function (Blueprint $table) { - $table->string('email')->primary(); - $table->string('token'); - $table->timestamp('created_at')->nullable(); - }); - - Schema::create('sessions', function (Blueprint $table) { - $table->string('id')->primary(); - $table->foreignId('user_id')->nullable()->index(); - $table->string('ip_address', 45)->nullable(); - $table->text('user_agent')->nullable(); - $table->longText('payload'); - $table->integer('last_activity')->index(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('users'); - Schema::dropIfExists('password_reset_tokens'); - Schema::dropIfExists('sessions'); - } -}; diff --git a/database/migrations/2025_07_10_152716_create_asset_prices_table.php b/database/migrations/2025_07_10_152716_create_asset_prices_table.php deleted file mode 100644 index 36653db..0000000 --- a/database/migrations/2025_07_10_152716_create_asset_prices_table.php +++ /dev/null @@ -1,28 +0,0 @@ -id(); - $table->foreignId('asset_id')->constrained()->onDelete('cascade'); - $table->date('date'); - $table->decimal('price', 10, 4); - $table->timestamps(); - - $table->unique(['asset_id', 'date']); - $table->index('asset_id'); - $table->index('date'); - }); - } - - public function down(): void - { - Schema::dropIfExists('asset_prices'); - } -}; diff --git a/database/migrations/2025_07_12_221324_create_milestones_table.php b/database/migrations/2025_07_12_221324_create_milestones_table.php deleted file mode 100644 index da034cc..0000000 --- a/database/migrations/2025_07_12_221324_create_milestones_table.php +++ /dev/null @@ -1,29 +0,0 @@ -id(); - $table->integer('target'); - $table->string('description'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('milestones'); - } -}; diff --git a/database/migrations/2026_05_02_000001_create_trackers_table.php b/database/migrations/2026_05_02_000001_create_trackers_table.php deleted file mode 100644 index 6b3afcf..0000000 --- a/database/migrations/2026_05_02_000001_create_trackers_table.php +++ /dev/null @@ -1,50 +0,0 @@ -id(); - $table->foreignId('user_id')->constrained()->cascadeOnDelete(); - $table->foreignId('asset_id')->nullable()->constrained()->nullOnDelete(); - $table->string('label'); - $table->string('unit'); - $table->boolean('price_tracking_enabled')->default(false); - $table->timestamps(); - }); - - // Migrate existing users: create one tracker per user from their current asset_id + price_tracking_enabled - DB::table('users')->orderBy('id')->each(function (object $user) { - DB::table('trackers')->insert([ - 'user_id' => $user->id, - 'asset_id' => $user->asset_id, - 'label' => 'Portfolio', - 'unit' => 'shares', - 'price_tracking_enabled' => $user->price_tracking_enabled ?? false, - 'created_at' => now(), - 'updated_at' => now(), - ]); - }); - } - - public function down(): void - { - // Restore asset_id and price_tracking_enabled back onto users before dropping trackers - DB::table('trackers')->orderBy('id')->each(function (object $tracker) { - DB::table('users') - ->where('id', $tracker->user_id) - ->update([ - 'asset_id' => $tracker->asset_id, - 'price_tracking_enabled' => $tracker->price_tracking_enabled, - ]); - }); - - Schema::dropIfExists('trackers'); - } -}; diff --git a/database/migrations/2026_05_02_000002_create_entries_table.php b/database/migrations/2026_05_02_000002_create_entries_table.php deleted file mode 100644 index b6fbec3..0000000 --- a/database/migrations/2026_05_02_000002_create_entries_table.php +++ /dev/null @@ -1,30 +0,0 @@ -id(); - $table->foreignId('tracker_id')->constrained()->cascadeOnDelete(); - $table->date('date'); - $table->decimal('quantity', 12, 6); - $table->decimal('unit_price', 12, 4)->nullable(); - $table->decimal('total_cost', 12, 2)->nullable(); - $table->timestamps(); - - $table->index(['tracker_id', 'date']); - }); - } - - public function down(): void - { - Schema::dropIfExists('entries'); - } -}; diff --git a/database/migrations/2026_05_02_000003_add_tracker_to_milestones_drop_from_users.php b/database/migrations/2026_05_02_000003_add_tracker_to_milestones_drop_from_users.php deleted file mode 100644 index b1cbc2a..0000000 --- a/database/migrations/2026_05_02_000003_add_tracker_to_milestones_drop_from_users.php +++ /dev/null @@ -1,44 +0,0 @@ -foreignId('tracker_id')->nullable()->after('id')->constrained()->cascadeOnDelete(); - }); - - // Backfill tracker_id on milestones - $trackerId = DB::table('trackers')->value('id'); - if ($trackerId) { - DB::table('milestones')->update(['tracker_id' => $trackerId]); - } - - Schema::table('milestones', function (Blueprint $table) { - $table->unsignedBigInteger('tracker_id')->nullable(false)->change(); - }); - - Schema::table('users', function (Blueprint $table) { - $table->dropForeign(['asset_id']); - $table->dropColumn(['asset_id', 'price_tracking_enabled']); - }); - } - - public function down(): void - { - Schema::table('users', function (Blueprint $table) { - $table->foreignId('asset_id')->nullable()->constrained()->nullOnDelete(); - $table->boolean('price_tracking_enabled')->default(false); - }); - - Schema::table('milestones', function (Blueprint $table) { - $table->dropForeign(['tracker_id']); - $table->dropColumn('tracker_id'); - }); - } -}; diff --git a/database/migrations/2026_08_15_000001_drop_milestones_table.php b/database/migrations/2026_08_15_000001_drop_milestones_table.php deleted file mode 100644 index 7461c21..0000000 --- a/database/migrations/2026_08_15_000001_drop_milestones_table.php +++ /dev/null @@ -1,26 +0,0 @@ -id(); - $table->foreignId('tracker_id')->constrained()->cascadeOnDelete(); - $table->integer('target'); - $table->string('description'); - $table->timestamps(); - }); - } -}; diff --git a/database/migrations/2026_08_15_000002_add_count_to_trackers_drop_entries.php b/database/migrations/2026_08_15_000002_add_count_to_trackers_drop_entries.php deleted file mode 100644 index f7940ab..0000000 --- a/database/migrations/2026_08_15_000002_add_count_to_trackers_drop_entries.php +++ /dev/null @@ -1,60 +0,0 @@ -unsignedInteger('count')->default(0)->after('unit'); - }); - - if (Schema::hasTable('entries')) { - DB::table('trackers')->orderBy('id')->each(function (object $tracker): void { - $total = (float) DB::table('entries')->where('tracker_id', $tracker->id)->sum('quantity'); - - DB::table('trackers') - ->where('id', $tracker->id) - ->update(['count' => max(0, (int) round($total))]); - }); - } - - Schema::dropIfExists('entries'); - } - - // Lossy by design: per-entry dates and prices cannot be rebuilt from a scalar. - public function down(): void - { - Schema::create('entries', function (Blueprint $table): void { - $table->id(); - $table->foreignId('tracker_id')->constrained()->cascadeOnDelete(); - $table->date('date'); - $table->decimal('quantity', 12, 6); - $table->decimal('unit_price', 12, 4)->nullable(); - $table->decimal('total_cost', 12, 2)->nullable(); - $table->timestamps(); - - $table->index(['tracker_id', 'date']); - }); - - DB::table('trackers')->where('count', '>', 0)->orderBy('id')->each(function (object $tracker): void { - DB::table('entries')->insert([ - 'tracker_id' => $tracker->id, - 'date' => now()->toDateString(), - 'quantity' => $tracker->count, - 'created_at' => now(), - 'updated_at' => now(), - ]); - }); - - Schema::table('trackers', function (Blueprint $table): void { - $table->dropColumn('count'); - }); - } -}; diff --git a/database/migrations/2026_08_15_000003_drop_assets_and_pricing.php b/database/migrations/2026_08_15_000003_drop_assets_and_pricing.php deleted file mode 100644 index 00bdd1a..0000000 --- a/database/migrations/2026_08_15_000003_drop_assets_and_pricing.php +++ /dev/null @@ -1,51 +0,0 @@ -dropForeign(['asset_id']); - $table->dropColumn(['asset_id', 'price_tracking_enabled']); - }); - - Schema::dropIfExists('asset_prices'); - Schema::dropIfExists('assets'); - } - - // Lossy by design: recorded symbols and prices cannot be recovered. - public function down(): void - { - Schema::create('assets', function (Blueprint $table): void { - $table->id(); - $table->string('symbol')->unique(); - $table->string('full_name')->nullable(); - $table->timestamps(); - - $table->index('symbol'); - }); - - Schema::create('asset_prices', function (Blueprint $table): void { - $table->id(); - $table->foreignId('asset_id')->constrained()->onDelete('cascade'); - $table->date('date'); - $table->decimal('price', 10, 4); - $table->timestamps(); - - $table->unique(['asset_id', 'date']); - $table->index('asset_id'); - $table->index('date'); - }); - - Schema::table('trackers', function (Blueprint $table): void { - $table->foreignId('asset_id')->nullable()->constrained()->nullOnDelete(); - $table->boolean('price_tracking_enabled')->default(false); - }); - } -}; diff --git a/database/migrations/2026_08_15_000004_drop_users_and_sessions.php b/database/migrations/2026_08_15_000004_drop_users_and_sessions.php deleted file mode 100644 index 3fca6fa..0000000 --- a/database/migrations/2026_08_15_000004_drop_users_and_sessions.php +++ /dev/null @@ -1,57 +0,0 @@ -dropForeign(['user_id']); - $table->dropColumn('user_id'); - }); - - Schema::dropIfExists('sessions'); - Schema::dropIfExists('password_reset_tokens'); - Schema::dropIfExists('users'); - } - - // Lossy by design: the app has no users, so nothing is restored into these tables. - public function down(): void - { - Schema::create('users', function (Blueprint $table): void { - $table->id(); - $table->string('name'); - $table->string('email')->unique(); - $table->timestamp('email_verified_at')->nullable(); - $table->string('password'); - $table->rememberToken(); - $table->timestamps(); - }); - - Schema::create('password_reset_tokens', function (Blueprint $table): void { - $table->string('email')->primary(); - $table->string('token'); - $table->timestamp('created_at')->nullable(); - }); - - Schema::create('sessions', function (Blueprint $table): void { - $table->string('id')->primary(); - $table->foreignId('user_id')->nullable()->index(); - $table->string('ip_address', 45)->nullable(); - $table->text('user_agent')->nullable(); - $table->longText('payload'); - $table->integer('last_activity')->index(); - }); - - // Nullable, unlike the original: existing trackers have no user to point at, - // so a NOT NULL foreign key cannot be added back. - Schema::table('trackers', function (Blueprint $table): void { - $table->foreignId('user_id')->nullable()->after('id')->constrained()->cascadeOnDelete(); - }); - } -}; diff --git a/database/migrations/2026_08_16_000000_create_trackers_table.php b/database/migrations/2026_08_16_000000_create_trackers_table.php new file mode 100644 index 0000000..c946f53 --- /dev/null +++ b/database/migrations/2026_08_16_000000_create_trackers_table.php @@ -0,0 +1,37 @@ +id(); + $table->string('label'); + $table->string('unit'); + $table->unsignedInteger('count')->default(0); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('trackers'); + } +}; diff --git a/docker/build/Dockerfile.ci b/docker/build/Dockerfile.ci index 02e53f2..c7b1348 100644 --- a/docker/build/Dockerfile.ci +++ b/docker/build/Dockerfile.ci @@ -8,13 +8,16 @@ # Debian-based rather than alpine: ffr hit repeated DNS resolution timeouts # against codeload.github.com on the alpine build. # -# pdo_mysql, not sqlite: the migration tests query information_schema and -# exercise MySQL-specific DDL, so CI runs against a real mysql:8.0 service. +# pdo_sqlite: tests run against sqlite in memory (see .env.testing). Service +# containers are not reachable from job containers on this runner, so CI must +# not depend on one. pdo_mysql is kept so artisan can talk to a real database +# when run manually inside this image. FROM php:8.3-cli COPY --from=mlocati/php-extension-installer:2 /usr/bin/install-php-extensions /usr/local/bin/ RUN install-php-extensions \ + pdo_sqlite \ pdo_mysql \ mbstring \ dom \ diff --git a/phpstan.neon b/phpstan.neon index 7564db0..f091dc1 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -11,11 +11,3 @@ parameters: excludePaths: - bootstrap/*.php - storage/* - - ignoreErrors: - # Migration files return an anonymous class; the base Migration declares neither up() nor down(). - # An interface on the migration is not an option: it would live under autoload-dev, which - # production omits (`composer install --no-dev`), so every migration would fatal on deploy. - - - message: '#Call to an undefined method Illuminate\\Database\\Migrations\\Migration::(up|down)\(\)#' - path: tests/Feature/*MigrationTest.php diff --git a/phpunit.xml b/phpunit.xml index 15ab25c..01bf6f9 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -22,7 +22,6 @@ - diff --git a/tests/Feature/CountBackfillMigrationTest.php b/tests/Feature/CountBackfillMigrationTest.php deleted file mode 100644 index 8b826d4..0000000 --- a/tests/Feature/CountBackfillMigrationTest.php +++ /dev/null @@ -1,145 +0,0 @@ -migration()->down(); - } - - private function makeTracker(): int - { - return DB::table('trackers')->insertGetId([ - 'label' => 'Counter', - 'unit' => 'units', - 'created_at' => now(), - 'updated_at' => now(), - ]); - } - - private function addEntry(int $trackerId, string $quantity): void - { - DB::table('entries')->insert([ - 'tracker_id' => $trackerId, - 'date' => now()->toDateString(), - 'quantity' => $quantity, - 'created_at' => now(), - 'updated_at' => now(), - ]); - } - - private function countFor(int $trackerId): int - { - return (int) DB::table('trackers')->where('id', $trackerId)->value('count'); - } - - public function test_backfill_sums_entries_into_count(): void - { - $this->revertToLedger(); - - $trackerId = $this->makeTracker(); - $this->addEntry($trackerId, '10'); - $this->addEntry($trackerId, '15'); - - $this->migration()->up(); - - $this->assertSame(25, $this->countFor($trackerId)); - } - - public function test_backfill_rounds_fractional_totals(): void - { - $this->revertToLedger(); - - $trackerId = $this->makeTracker(); - $this->addEntry($trackerId, '1.4'); - $this->addEntry($trackerId, '1.2'); - - $this->migration()->up(); - - $this->assertSame(3, $this->countFor($trackerId)); - } - - public function test_backfill_clamps_negative_totals_to_zero(): void - { - $this->revertToLedger(); - - $trackerId = $this->makeTracker(); - $this->addEntry($trackerId, '5'); - $this->addEntry($trackerId, '-9'); - - $this->migration()->up(); - - $this->assertSame(0, $this->countFor($trackerId)); - } - - public function test_tracker_without_entries_defaults_to_zero(): void - { - $this->revertToLedger(); - - $trackerId = $this->makeTracker(); - - $this->migration()->up(); - - $this->assertSame(0, $this->countFor($trackerId)); - } - - public function test_up_drops_the_entries_table(): void - { - $this->revertToLedger(); - $this->assertTrue(Schema::hasTable('entries')); - - $this->migration()->up(); - - $this->assertFalse(Schema::hasTable('entries')); - $this->assertTrue(Schema::hasColumn('trackers', 'count')); - } - - // The two down() tests start from the migrated schema, so they do not call revertToLedger(). - public function test_down_recreates_entries_from_count(): void - { - $trackerId = $this->makeTracker(); - DB::table('trackers')->where('id', $trackerId)->update(['count' => 7]); - - $this->migration()->down(); - - $this->assertTrue(Schema::hasTable('entries')); - $this->assertFalse(Schema::hasColumn('trackers', 'count')); - - $entries = DB::table('entries')->where('tracker_id', $trackerId)->get(); - - $this->assertCount(1, $entries); - $this->assertSame(7.0, (float) $entries->first()->quantity); - } - - public function test_down_writes_no_entry_for_a_zero_count(): void - { - $trackerId = $this->makeTracker(); - - $this->migration()->down(); - - $this->assertSame(0, DB::table('entries')->where('tracker_id', $trackerId)->count()); - } -} diff --git a/tests/Feature/DropAssetsMigrationTest.php b/tests/Feature/DropAssetsMigrationTest.php deleted file mode 100644 index da17be1..0000000 --- a/tests/Feature/DropAssetsMigrationTest.php +++ /dev/null @@ -1,68 +0,0 @@ -assertFalse(Schema::hasTable('assets')); - $this->assertFalse(Schema::hasTable('asset_prices')); - $this->assertFalse(Schema::hasColumn('trackers', 'asset_id')); - $this->assertFalse(Schema::hasColumn('trackers', 'price_tracking_enabled')); - } - - public function test_down_restores_the_tables_and_columns(): void - { - $this->migration()->down(); - - $this->assertTrue(Schema::hasTable('assets')); - $this->assertTrue(Schema::hasTable('asset_prices')); - $this->assertTrue(Schema::hasColumn('trackers', 'asset_id')); - $this->assertTrue(Schema::hasColumn('trackers', 'price_tracking_enabled')); - } - - public function test_up_drops_them_again_respecting_foreign_keys(): void - { - $this->migration()->down(); - $this->migration()->up(); - - $this->assertFalse(Schema::hasTable('assets')); - $this->assertFalse(Schema::hasTable('asset_prices')); - $this->assertFalse(Schema::hasColumn('trackers', 'asset_id')); - $this->assertFalse(Schema::hasColumn('trackers', 'price_tracking_enabled')); - } - - public function test_dropping_assets_does_not_disturb_the_counter(): void - { - $this->migration()->down(); - - $trackerId = DB::table('trackers')->insertGetId([ - 'label' => 'Counter', - 'unit' => 'units', - 'count' => 31, - 'created_at' => now(), - 'updated_at' => now(), - ]); - - $this->migration()->up(); - - $this->assertSame(31, (int) DB::table('trackers')->where('id', $trackerId)->value('count')); - } -} diff --git a/tests/Feature/DropUsersMigrationTest.php b/tests/Feature/DropUsersMigrationTest.php deleted file mode 100644 index f642a1e..0000000 --- a/tests/Feature/DropUsersMigrationTest.php +++ /dev/null @@ -1,86 +0,0 @@ -assertFalse(Schema::hasTable('users')); - $this->assertFalse(Schema::hasTable('sessions')); - $this->assertFalse(Schema::hasTable('password_reset_tokens')); - $this->assertFalse(Schema::hasColumn('trackers', 'user_id')); - } - - public function test_down_restores_the_tables_and_column(): void - { - $this->migration()->down(); - - $this->assertTrue(Schema::hasTable('users')); - $this->assertTrue(Schema::hasTable('sessions')); - $this->assertTrue(Schema::hasTable('password_reset_tokens')); - $this->assertTrue(Schema::hasColumn('trackers', 'user_id')); - } - - public function test_restored_user_id_is_nullable_so_existing_trackers_survive(): void - { - DB::table('trackers')->insert([ - 'label' => 'Counter', - 'unit' => 'units', - 'count' => 3, - 'created_at' => now(), - 'updated_at' => now(), - ]); - - $this->migration()->down(); - - $nullable = DB::selectOne( - 'select is_nullable from information_schema.columns - where table_schema = database() and table_name = ? and column_name = ?', - ['trackers', 'user_id'] - ); - - $this->assertSame('YES', $nullable->is_nullable ?? $nullable->IS_NULLABLE); - } - - public function test_up_drops_them_again_respecting_foreign_keys(): void - { - $this->migration()->down(); - $this->migration()->up(); - - $this->assertFalse(Schema::hasTable('users')); - $this->assertFalse(Schema::hasColumn('trackers', 'user_id')); - } - - public function test_the_counter_survives_the_round_trip(): void - { - $trackerId = DB::table('trackers')->insertGetId([ - 'label' => 'Counter', - 'unit' => 'units', - 'count' => 77, - 'created_at' => now(), - 'updated_at' => now(), - ]); - - $this->migration()->down(); - $this->migration()->up(); - - $this->assertSame(77, (int) DB::table('trackers')->where('id', $trackerId)->value('count')); - } -}