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->updatedAt)->toBeNull() ->and($coupon->updatedAt())->toBeNull(); }); it('hydrates a coupon without availability calendar', function () use ( $code, $name, $amount, $picture, $diffusion, $validityInformations, $legalInformations, $processingCode, $brandCode, $createdBy, $products, $movements, $quantity, ): 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, quantity: $quantity, ); // 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, $quantity, $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, quantity: $quantity, 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, $quantity, $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, quantity: $quantity, 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, $quantity, $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, quantity: $quantity, availabilityCalendar: $availabilityCalendar, ))->toThrow(\DomainException::class, 'Value of CouponLegalInformationArray must be CouponLegalInformation instances.'); }); it('hydrates a coupon with an explicit updatedAt date', function () use ( $code, $name, $amount, $picture, $diffusion, $validityInformations, $legalInformations, $processingCode, $brandCode, $createdBy, $products, $movements, $quantity, $availabilityCalendar, ): void { // GIVEN $id = CouponId::generate(); $updatedAt = new \DateTimeImmutable('2026-09-22 10:00:00', new \DateTimeZone('UTC')); // WHEN $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, quantity: $quantity, availabilityCalendar: $availabilityCalendar, updatedAt: $updatedAt, ); // THEN expect($coupon->updatedAt)->toBe($updatedAt) ->and($coupon->updatedAt())->toBe($updatedAt); }); it('creates a new coupon with a freshly generated id', function () use ( $code, $name, $amount, $picture, $diffusion, $validityInformations, $legalInformations, $processingCode, $brandCode, $createdBy, $products, $movements, $quantity, $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, quantity: $quantity, 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->quantity)->toBe($quantity) ->and($coupon->availabilityCalendar)->toBe($availabilityCalendar) ->and($coupon->updatedAt)->toBeNull() ->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, $quantity, $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, quantity: $quantity, 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, quantity: $quantity, 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, $quantity, $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, quantity: $quantity, 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')); }); });