jetzt(), ); } public function testAnlegenErzeugtGeplanteMahlzeit(): void { $m = $this->geplant(); self::assertSame(0, $m->id); self::assertSame('Spaghetti Bolognese', $m->name); self::assertSame('mit mehr Soße', $m->notiz); self::assertSame([Wochentag::Mo, Wochentag::Di], $m->wochentage()); self::assertSame(1, $m->sortOrder); self::assertSame(MahlzeitStatus::Geplant, $m->status); self::assertNull($m->gegessenAm); self::assertTrue($m->istGeplant()); } public function testAnlegenTrimmtNameUndNotiz(): void { $m = Mahlzeit::anlegen(' Bolognese ', ' Notiz ', [], 0, $this->jetzt()); self::assertSame('Bolognese', $m->name); self::assertSame('Notiz', $m->notiz); } public function testMarkAsGegessenSetztStatusZeitpunktUndAktualisiertAm(): void { $m = $this->geplant(); $später = $this->jetzt()->modify('+2 days'); $gegessen = $m->markAsGegessen($später); self::assertSame(MahlzeitStatus::Gegessen, $gegessen->status); self::assertSame($später, $gegessen->gegessenAm); self::assertSame($später, $gegessen->aktualisiertAm); self::assertTrue($gegessen->istGegessen()); // Ursprung bleibt unverändert (Unveränderlichkeit) self::assertSame(MahlzeitStatus::Geplant, $m->status); } public function testMarkAsGeplantSetztGegessenAmZurück(): void { $gegessen = $this->geplant()->markAsGegessen($this->jetzt()); $geplant = $gegessen->markAsGeplant($this->jetzt()); self::assertSame(MahlzeitStatus::Geplant, $geplant->status); self::assertNull($geplant->gegessenAm); self::assertTrue($geplant->istGeplant()); } public function testMarkAsGegessenIstIdempotent(): void { $m = $this->geplant(); $einmal = $m->markAsGegessen($this->jetzt()); $zweimal = $einmal->markAsGegessen($this->jetzt()); self::assertSame($einmal->gegessenAm, $zweimal->gegessenAm); self::assertSame(MahlzeitStatus::Gegessen, $zweimal->status); } public function testAktualisierenÄndertInhaltUndBelässtStatus(): void { $gegessen = $this->geplant()->markAsGegessen($this->jetzt()); $aktualisiert = $gegessen->aktualisieren( name: 'Linsen', notiz: 'scharf', wochentage: [Wochentag::Mi], sortOrder: $gegessen->sortOrder, jetzt: $this->jetzt(), ); self::assertSame('Linsen', $aktualisiert->name); self::assertSame('scharf', $aktualisiert->notiz); self::assertSame([Wochentag::Mi], $aktualisiert->wochentage()); self::assertSame(MahlzeitStatus::Gegessen, $aktualisiert->status); self::assertNotNull($aktualisiert->gegessenAm); } public function testAktualisierenMitLeerenNameWirft(): void { $this->expectException(BusinessRuleViolationException::class); $this->geplant()->aktualisieren(' ', '', [], 1, $this->jetzt()); } public function testMitSortOrderNegativWirft(): void { $this->expectException(BusinessRuleViolationException::class); $this->geplant()->mitSortOrder(-1); } public function testMitSortOrderÄndertNurPosition(): void { $m = $this->geplant()->mitSortOrder(5); self::assertSame(5, $m->sortOrder); self::assertSame('Spaghetti Bolognese', $m->name); } public function testMitIdSetztPersistenzId(): void { $m = $this->geplant()->mitId(42); self::assertSame(42, $m->id); } public function testGegessenOhneZeitpunktWirft(): void { $this->expectException(BusinessRuleViolationException::class); new Mahlzeit(1, 'X', '', [], 0, MahlzeitStatus::Gegessen, $this->jetzt(), $this->jetzt(), null); } public function testGeplanteMitGegessenAmWirft(): void { $this->expectException(BusinessRuleViolationException::class); new Mahlzeit(1, 'X', '', [], 0, MahlzeitStatus::Geplant, $this->jetzt(), $this->jetzt(), $this->jetzt()); } public function testUngültigerWochentagWirft(): void { $this->expectException(\TypeError::class); Mahlzeit::anlegen('X', '', ['kein-tag'], 0, $this->jetzt()); } }