placeOrder(); self::assertSame(OrderStatus::Placed, $order->status()); self::assertCount(1, $order->lines()); self::assertTrue($order->total()->isPositive()); } public function test_place_order_records_order_placed_event(): void { $order = $this->placeOrder(); $events = $order->releaseEvents(); self::assertCount(1, $events); self::assertInstanceOf(OrderPlaced::class, $events[0]); } public function test_place_order_without_lines_throws(): void { $this->expectException(EmptyOrderException::class); Order::place( OrderId::fromString('order-1'), CustomerId::fromString('cust-1'), [], new \DateTimeImmutable(), ); } public function test_confirm_placed_order(): void { $order = $this->placeOrder(); $order->releaseEvents(); $order->confirm(); self::assertSame(OrderStatus::Confirmed, $order->status()); $events = $order->releaseEvents(); self::assertCount(1, $events); self::assertInstanceOf(OrderConfirmed::class, $events[0]); } public function test_confirm_draft_order_throws(): void { $this->expectException(InvalidOrderStateException::class); $order = $this->placeOrder(); $order->confirm(); $order->releaseEvents(); $order->confirm(); // already confirmed } public function test_cancel_placed_order(): void { $order = $this->placeOrder(); $order->releaseEvents(); $order->cancel(); self::assertSame(OrderStatus::Cancelled, $order->status()); $events = $order->releaseEvents(); self::assertCount(1, $events); self::assertInstanceOf(OrderCancelled::class, $events[0]); } public function test_cannot_cancel_confirmed_order(): void { $this->expectException(InvalidOrderStateException::class); $order = $this->placeOrder(); $order->confirm(); $order->cancel(); } public function test_total_is_sum_of_line_totals(): void { $order = Order::place( OrderId::fromString('order-1'), CustomerId::fromString('cust-1'), [ new OrderLine('Widget', 2, new Money(1000, 'EUR')), new OrderLine('Gadget', 1, new Money(2500, 'EUR')), ], new \DateTimeImmutable(), ); self::assertTrue($order->total()->equals(new Money(4500, 'EUR'))); } private function placeOrder(): Order { return Order::place( OrderId::fromString('order-1'), CustomerId::fromString('cust-1'), [new OrderLine('Widget', 2, new Money(1500, 'EUR'))], new \DateTimeImmutable(), ); } }