next()); } public function testNextFromFirstReturnsSecond(): void { self::assertSame(OrderStatus::Pending, OrderStatus::Draft->next()); } public function testNextFromLastReturnsNull(): void { self::assertNull(OrderStatus::Cancelled->next()); } public function testNextFromSecondToLastReturnsLast(): void { self::assertSame(OrderStatus::Cancelled, OrderStatus::Delivered->next()); } // ------------------------------------------------------------------------- // prev() // ------------------------------------------------------------------------- public function testPrevReturnsPrecedingCase(): void { self::assertSame(OrderStatus::Draft, OrderStatus::Pending->prev()); } public function testPrevFromLastReturnsPenultimate(): void { self::assertSame(OrderStatus::Delivered, OrderStatus::Cancelled->prev()); } public function testPrevFromFirstReturnsNull(): void { self::assertNull(OrderStatus::Draft->prev()); } public function testPrevFromSecondReturnsFirst(): void { self::assertSame(OrderStatus::Draft, OrderStatus::Pending->prev()); } // ------------------------------------------------------------------------- // Chaining // ------------------------------------------------------------------------- public function testNextThenPrevReturnsSameCase(): void { $case = OrderStatus::Pending; self::assertSame($case, $case->next()?->prev()); } public function testPrevThenNextReturnsSameCase(): void { $case = OrderStatus::Shipped; self::assertSame($case, $case->prev()?->next()); } // ------------------------------------------------------------------------- // Single-case enum edge case // ------------------------------------------------------------------------- public function testNextAndPrevReturnNullForOnlyCase(): void { self::assertNull(Alone::Only->next()); self::assertNull(Alone::Only->prev()); } } enum Alone { use StepTrait; case Only; }