shouldReceive('find')->with($orderId)->andReturn($order); $repository->shouldReceive('persist')->with($order)->once(); $service = new OrderService($repository); // WHEN $service->cancelOrder($orderId); // THEN expect($order->status)->toBe(OrderStatus::CANCELED); }); it('throws exception if order not found', function () { // GIVEN $orderId = new OrderId(Uuid::uuid7()); /** @var OrderRepository|\Mockery\MockInterface $repository */ $repository = Mockery::mock(OrderRepository::class); $repository->shouldReceive('find')->with($orderId)->andReturn(null); $service = new OrderService($repository); // WHEN $action = fn () => $service->cancelOrder($orderId); // THEN expect($action)->toThrow(\DomainException::class, 'Order not found'); }); }); describe('Order Creation', function () { it('creates an order from a basket correctly', function () { // GIVEN $basketId = new BasketId(Uuid::uuid7()); $basket = new Basket($basketId); $basketProduct = new BasketProduct( id: new ProductId(Uuid::uuid7()), name: 'Poulet Rôti', qty: 2, unitPriceHt: Money::EUR(1000), unitDiscount: Money::EUR(100), taxRate: TaxRate::TVA_5_5, weightGrams: 1200, brand: ProductBrand::marie, incoId: new IncoId(45), orderUnit: OrderUnit::PCE, slug: 'poulet-roti', picture: 'images/poulet.jpg', description: 'Un bon poulet', weightVariable: false, discountRate: DiscountRate::fromRatio(0.1), priceKgTtc: Money::EUR(1500) ); $basket->addOrUpdate($basketProduct); $pickupTimeSlot = new PickupTimeSlot( new \DateTimeImmutable('2023-12-01 10:00:00'), new \DateInterval('PT10M') ); $shopper = new Shopper( id: new ShopperId(Uuid::uuid7()), email: new Email('jean.dupont@example.com'), matricule: new Matricule('1234567'), nom: 'Dupont', prenom: 'Jean', startDate: CarbonImmutable::now(), endDate: null, etablissement: new ShopperEstablishmentCode('ETAB01'), site: new ShopperSiteCode('SITEA'), service: new ShopperServiceCode('101') ); $shop = new Shop( id: new ShopId(Uuid::uuid7()), name: 'Cocotte Lyon', address: '12 rue de la Paix', postcode: '69001', city: 'Lyon', phone: '0478123456' ); /** @var OrderRepository|\Mockery\MockInterface $repository */ $repository = Mockery::mock(OrderRepository::class); $service = new OrderService($repository); // WHEN $order = $service->createOrderFromBasket($basket, $pickupTimeSlot, $shopper, $shop); // THEN expect($order)->toBeInstanceOf(Order::class); expect($order->status)->toBe(OrderStatus::VALIDATED); expect(UuidHelper::isV7($order->reference->value))->toBeTrue(); // * Employee $employee = $order->employee; expect($employee->matricule->value)->toBe('1234567'); expect($employee->firstname)->toBe('Jean'); expect($employee->lastname)->toBe('Dupont'); expect($employee->facility->value)->toBe('ETAB01'); expect($employee->site->value)->toBe('SITEA'); expect($employee->service->value)->toBe('101'); // * Delivery Address $delivery = $order->deliveryAddress; expect($delivery->name)->toBe('Cocotte Lyon'); expect($delivery->address)->toBe('12 rue de la Paix'); expect($delivery->postcode)->toBe('69001'); expect($delivery->city)->toBe('Lyon'); expect($delivery->phone)->toBe('0478123456'); // * Total expect($order->getTotal()->getAmount())->toBe('1899'); // * Lines $lines = $order->getLines(); expect($lines)->toHaveCount(1); $line = $lines[0]; expect($line->quantity)->toBe(2); expect($line->unitPriceHt->getAmount())->toBe('1000'); expect($line->unitDiscount->getAmount())->toBe('100'); expect($line->unitTtc->getAmount())->toBe('950'); expect($line->totalHt->getAmount())->toBe('1800'); expect($line->totalDiscount->getAmount())->toBe('200'); expect($line->totalTtc->getAmount())->toBe('1899'); // * product mapping $product = $line->product; expect($product->name)->toBe('Poulet Rôti'); expect($product->weight->toGrams())->toBe(1200); expect($product->brand)->toBe(ProductBrand::marie); expect($product->incoId->value)->toBe(45); expect($product->orderUnit)->toBe(OrderUnit::PCE); expect($product->picture)->toBe('images/poulet.jpg'); }); it('throws exception if basket product has no incoId', function () { // GIVEN $basketId = new BasketId(Uuid::uuid7()); $basket = new Basket($basketId); $basketProduct = new BasketProduct( id: new ProductId(Uuid::uuid7()), name: 'Poulet Rôti', qty: 2, unitPriceHt: Money::EUR(1000), unitDiscount: Money::EUR(100), taxRate: TaxRate::TVA_5_5, weightGrams: 1200, brand: ProductBrand::marie, incoId: null, // NO INCO ID orderUnit: OrderUnit::PCE, slug: 'poulet-roti', picture: null, description: null, weightVariable: false, discountRate: DiscountRate::fromRatio(0.1), priceKgTtc: Money::EUR(1500) ); $basket->addOrUpdate($basketProduct); $pickupTimeSlot = new PickupTimeSlot(new \DateTimeImmutable(), new \DateInterval('PT10M')); $shopper = new Shopper( id: new ShopperId(Uuid::uuid7()), email: new Email('a@a.com'), matricule: new Matricule('1234567'), nom: 'A', prenom: 'B', startDate: CarbonImmutable::now(), endDate: null, etablissement: new ShopperEstablishmentCode('ETAB01'), site: new ShopperSiteCode('SITEA'), service: new ShopperServiceCode('101') ); $shop = new Shop( id: new ShopId(Uuid::uuid7()), name: 'S', address: 'A', postcode: 'P', city: 'C' ); $repository = Mockery::mock(OrderRepository::class); $service = new OrderService($repository); // WHEN $action = fn () => $service->createOrderFromBasket($basket, $pickupTimeSlot, $shopper, $shop); // THEN expect($action)->toThrow(\DomainException::class, 'incoId cannot be null for an order'); }); });