id())->toBe($id) ->and($coupon->code)->toBe($code) ->and($coupon->name)->toBe($name) ->and($coupon->amount)->toBe($amount) ->and($coupon->picture)->toBe($picture) ->and($coupon->diffusion)->toBe($diffusion) ->and($coupon->validityInformations)->toBe($validityInformations) ->and($coupon->legalInformations)->toBe($legalInformations) ->and($coupon->processingCode)->toBe($processingCode) ->and($coupon->brandCode)->toBe($brandCode) ->and($coupon->createdBy)->toBe($createdBy) ->and($coupon->products)->toBe($products) ->and($coupon->availabilityCalendar)->toBe($availabilityCalendar) ->and($coupon->movements)->toBe($movements) ->and($coupon->createdAt())->toBeInstanceOf(DateTimeInterface::class) ->and($coupon->updatedAt())->toBeInstanceOf(DateTimeInterface::class); }); it('hydrates a coupon without availability calendar', function () use ( $code, $name, $amount, $picture, $diffusion, $validityInformations, $legalInformations, $processingCode, $brandCode, $createdBy, $products, $movements, ): void { // GIVEN $id = CouponId::generate(); // WHEN $coupon = Coupon::hydrate( id: $id, code: $code, name: $name, amount: $amount, picture: $picture, diffusion: $diffusion, validityInformations: $validityInformations, legalInformations: $legalInformations, processingCode: $processingCode, brandCode: $brandCode, createdBy: $createdBy, products: $products, movements: $movements, ); // THEN expect($coupon->availabilityCalendar)->toBeNull() ->and($coupon->products)->toBe($products); }); it('hydrates a coupon without products', function () use ( $code, $name, $amount, $picture, $diffusion, $validityInformations, $legalInformations, $processingCode, $brandCode, $createdBy, $movements, $availabilityCalendar, ): void { // GIVEN $id = CouponId::generate(); // WHEN $coupon = Coupon::hydrate( id: $id, code: $code, name: $name, amount: $amount, picture: $picture, diffusion: $diffusion, validityInformations: $validityInformations, legalInformations: $legalInformations, processingCode: $processingCode, brandCode: $brandCode, createdBy: $createdBy, products: new CouponProductArray(), movements: $movements, availabilityCalendar: $availabilityCalendar, ); // THEN expect($coupon->products->value)->toBe([]) ->and($coupon->availabilityCalendar)->toBe($availabilityCalendar); }); it('throws when validity information contains an invalid item', function () use ( $code, $name, $amount, $picture, $diffusion, $legalInformations, $processingCode, $brandCode, $createdBy, $products, $movements, $availabilityCalendar, ): void { // GIVEN $id = CouponId::generate(); // WHEN / THEN expect(fn (): Coupon => Coupon::hydrate( id: $id, code: $code, name: $name, amount: $amount, picture: $picture, diffusion: $diffusion, validityInformations: new CouponValidityInformationArray(['Not a CouponValidityInformation']), legalInformations: $legalInformations, processingCode: $processingCode, brandCode: $brandCode, createdBy: $createdBy, products: $products, movements: $movements, availabilityCalendar: $availabilityCalendar, ))->toThrow(\DomainException::class, 'Value of CouponValidityInformationArray must be CouponValidityInformation instances.'); }); it('throws when legal information contains an invalid item', function () use ( $code, $name, $amount, $picture, $diffusion, $validityInformations, $processingCode, $brandCode, $createdBy, $products, $movements, $availabilityCalendar, ): void { // GIVEN $id = CouponId::generate(); // WHEN / THEN expect(fn (): Coupon => Coupon::hydrate( id: $id, code: $code, name: $name, amount: $amount, picture: $picture, diffusion: $diffusion, validityInformations: $validityInformations, legalInformations: new CouponLegalInformationArray(['Not a CouponLegalInformation']), processingCode: $processingCode, brandCode: $brandCode, createdBy: $createdBy, products: $products, movements: $movements, availabilityCalendar: $availabilityCalendar, ))->toThrow(\DomainException::class, 'Value of CouponLegalInformationArray must be CouponLegalInformation instances.'); }); it('creates a new coupon with a freshly generated id', function () use ( $code, $name, $amount, $picture, $diffusion, $validityInformations, $legalInformations, $processingCode, $brandCode, $createdBy, $products, $movements, $availabilityCalendar, ): void { // GIVEN / WHEN $coupon = Coupon::create( code: $code, name: $name, amount: $amount, picture: $picture, diffusion: $diffusion, validityInformations: $validityInformations, legalInformations: $legalInformations, processingCode: $processingCode, brandCode: $brandCode, createdBy: $createdBy, products: $products, movements: $movements, availabilityCalendar: $availabilityCalendar, ); // THEN expect($coupon->id())->toBeInstanceOf(CouponId::class) ->and($coupon->code)->toBe($code) ->and($coupon->name)->toBe($name) ->and($coupon->amount)->toBe($amount) ->and($coupon->picture)->toBe($picture) ->and($coupon->diffusion)->toBe($diffusion) ->and($coupon->validityInformations)->toBe($validityInformations) ->and($coupon->legalInformations)->toBe($legalInformations) ->and($coupon->processingCode)->toBe($processingCode) ->and($coupon->brandCode)->toBe($brandCode) ->and($coupon->createdBy)->toBe($createdBy) ->and($coupon->products)->toBe($products) ->and($coupon->movements)->toBe($movements) ->and($coupon->availabilityCalendar)->toBe($availabilityCalendar) ->and($coupon->createdAt())->toBeInstanceOf(DateTimeInterface::class) ->and($coupon->updatedAt())->toBeNull(); }); it('generates a different id for each created coupon', function () use ( $code, $name, $amount, $picture, $diffusion, $validityInformations, $legalInformations, $processingCode, $brandCode, $createdBy, $products, $movements, $availabilityCalendar, ): void { // GIVEN / WHEN $firstCoupon = Coupon::create( code: $code, name: $name, amount: $amount, picture: $picture, diffusion: $diffusion, validityInformations: $validityInformations, legalInformations: $legalInformations, processingCode: $processingCode, brandCode: $brandCode, createdBy: $createdBy, products: $products, movements: $movements, availabilityCalendar: $availabilityCalendar, ); $secondCoupon = Coupon::create( code: $code, name: $name, amount: $amount, picture: $picture, diffusion: $diffusion, validityInformations: $validityInformations, legalInformations: $legalInformations, processingCode: $processingCode, brandCode: $brandCode, createdBy: $createdBy, products: $products, movements: $movements, availabilityCalendar: $availabilityCalendar, ); // THEN expect($firstCoupon->id()->equals($secondCoupon->id()))->toBeFalse(); }); it('returns the creation date extracted from the id', function () use ( $code, $name, $amount, $picture, $diffusion, $validityInformations, $legalInformations, $processingCode, $brandCode, $createdBy, $products, $movements, $availabilityCalendar, ): void { // GIVEN $expected = new \DateTimeImmutable('2024-06-15 12:34:56.789000', new \DateTimeZone('UTC')); $id = new CouponId(Uuid::uuid7($expected)); $coupon = Coupon::hydrate( $id, code: $code, name: $name, amount: $amount, picture: $picture, diffusion: $diffusion, validityInformations: $validityInformations, legalInformations: $legalInformations, processingCode: $processingCode, brandCode: $brandCode, createdBy: $createdBy, products: $products, movements: $movements, availabilityCalendar: $availabilityCalendar, ); // WHEN $result = $coupon->createdAt(); // THEN expect($result->format('Y-m-d H:i:s.v'))->toBe($expected->format('Y-m-d H:i:s.v')); }); it('computes the quantity from its movements', function () use ( $code, $name, $amount, $picture, $diffusion, $validityInformations, $legalInformations, $processingCode, $brandCode, $createdBy, $products, ): void { // GIVEN $coupon = Coupon::create( code: $code, name: $name, amount: $amount, picture: $picture, diffusion: $diffusion, validityInformations: $validityInformations, legalInformations: $legalInformations, processingCode: $processingCode, brandCode: $brandCode, createdBy: $createdBy, products: $products, movements: new CouponMovementArray([ new CouponMovement(1000), new CouponMovement(-200), ]), ); // WHEN $quantity = $coupon->quantity(); // THEN expect($quantity)->toBe(800); }); });