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()); } }