name = new CouponName('Coupon A'); $this->quantity = new RequestedCouponQuantity(100); $this->diffusion = new Period(new DateTime('2026-01-01'), new DateTime('2026-02-01')); $this->moneyAmount = new MoneyAmount(new Money(Currency::EUR, 300)); $this->processingCode = new ProcessingCode('PC1'); $this->couponValidity = new CouponValidity(30, new DateTime('2026-02-01')); $this->franceValidityInformation = new CouponValidityInformation( 'Lorem ipsum dolor sit amet consectetur adipiscing elit.', Country::FRANCE ); $this->beneluxValidityInformation = new CouponValidityInformation( 'Lorem ipsum dolor sit amet consectetur adipiscing elit.', Country::BENELUX ); $this->couponValidityInformation = [ $this->franceValidityInformation, $this->beneluxValidityInformation, ]; $this->products = [new IncoCode(35784), new IncoCode(15522)]; $this->printRules = new PrintRules(maxPerCustomer: 3); $this->gs1 = new GS1('01234567890128', BarcodeFormat::EAN13); }); afterEach(function (): void { CarbonImmutable::setTestNow(); }); it('hydrates a requested coupon with all its fields', function (): void { // GIVEN / WHEN $coupon = new RequestedCoupon( $this->name, $this->quantity, $this->diffusion, $this->moneyAmount, $this->processingCode, $this->couponValidity, $this->couponValidityInformation, $this->products, $this->printRules, $this->gs1, ); // THEN expect($coupon->name)->toBe($this->name) ->and($coupon->quantity)->toBe($this->quantity) ->and($coupon->diffusion)->toBe($this->diffusion) ->and($coupon->moneyAmount)->toBe($this->moneyAmount) ->and($coupon->processingCode)->toBe($this->processingCode) ->and($coupon->couponValidity)->toBe($this->couponValidity) ->and($coupon->couponValidityInformation)->toBe($this->couponValidityInformation) ->and($coupon->products)->toBe($this->products) ->and($coupon->printRules)->toBe($this->printRules) ->and($coupon->gs1)->toBe($this->gs1); }); it('hydrates a requested coupon without products', function (): void { // GIVEN / WHEN $coupon = new RequestedCoupon( name: $this->name, quantity: $this->quantity, diffusion: $this->diffusion, moneyAmount: $this->moneyAmount, processingCode: $this->processingCode, couponValidity: $this->couponValidity, couponValidityInformation: $this->couponValidityInformation, printRules: $this->printRules, gs1: $this->gs1 ); // THEN expect($coupon->products)->toBe([]) ->and($coupon->printRules)->toBe($this->printRules) ->and($coupon->gs1)->toBe($this->gs1); }); it('hydrates a requested coupon without print rules', function (): void { // GIVEN / WHEN $coupon = new RequestedCoupon( name: $this->name, quantity: $this->quantity, diffusion: $this->diffusion, moneyAmount: $this->moneyAmount, processingCode: $this->processingCode, couponValidity: $this->couponValidity, couponValidityInformation: $this->couponValidityInformation, products: $this->products, gs1: $this->gs1 ); // THEN expect($coupon->printRules)->toBeNull() ->and($coupon->products)->toBe($this->products) ->and($coupon->gs1)->toBe($this->gs1); }); it('hydrates a requested coupon without gs1', function (): void { // GIVEN / WHEN $coupon = new RequestedCoupon( name: $this->name, quantity: $this->quantity, diffusion: $this->diffusion, moneyAmount: $this->moneyAmount, processingCode: $this->processingCode, couponValidity: $this->couponValidity, couponValidityInformation: $this->couponValidityInformation, products: $this->products, printRules: $this->printRules ); // THEN expect($coupon->gs1)->toBeNull() ->and($coupon->products)->toBe($this->products) ->and($coupon->printRules)->toBe($this->printRules); }); it('hydrates a requested coupon with only required fields', function (): void { // GIVEN / WHEN $coupon = new RequestedCoupon( name: $this->name, quantity: $this->quantity, diffusion: $this->diffusion, moneyAmount: $this->moneyAmount, processingCode: $this->processingCode, couponValidity: $this->couponValidity, couponValidityInformation: $this->couponValidityInformation, ); // THEN expect($coupon->products)->toBe([]) ->and($coupon->printRules)->toBeNull() ->and($coupon->gs1)->toBeNull(); }); it('throws when there is no validity information for france', function (): void { // GIVEN / WHEN / THEN expect(fn () => new RequestedCoupon( name: $this->name, quantity: $this->quantity, diffusion: $this->diffusion, moneyAmount: $this->moneyAmount, processingCode: $this->processingCode, couponValidity: $this->couponValidity, couponValidityInformation: [], ))->toThrow(\DomainException::class, 'A coupon requires validity information for France.'); }); it('throws when validity information contains an invalid item', function (): void { // GIVEN / WHEN / THEN expect(fn () => new RequestedCoupon( $this->name, $this->quantity, $this->diffusion, $this->moneyAmount, $this->processingCode, $this->couponValidity, ['Not a CouponValidityInformation'], $this->products, $this->printRules, $this->gs1 ))->toThrow(\DomainException::class, 'Coupon validity information must be CouponValidityInformation instances.'); }); it('throws when a gs1 coupon has no benelux validity information', function (): void { // GIVEN / WHEN / THEN expect(fn () => new RequestedCoupon( name: $this->name, quantity: $this->quantity, diffusion: $this->diffusion, moneyAmount: $this->moneyAmount, processingCode: $this->processingCode, couponValidity: $this->couponValidity, couponValidityInformation: [$this->franceValidityInformation], gs1: $this->gs1, ))->toThrow(\DomainException::class, 'A GS1 coupon requires validity information for Benelux.'); }); it('throws when a gs1 coupon has only benelux validity information', function (): void { // GIVEN / WHEN / THEN expect(fn () => new RequestedCoupon( name: $this->name, quantity: $this->quantity, diffusion: $this->diffusion, moneyAmount: $this->moneyAmount, processingCode: $this->processingCode, couponValidity: $this->couponValidity, couponValidityInformation: [$this->beneluxValidityInformation], gs1: $this->gs1, ))->toThrow(\DomainException::class, 'A coupon requires validity information for France.'); }); it('accepts a coupon without gs1 and without benelux validity information', function (): void { // GIVEN / WHEN $coupon = new RequestedCoupon( name: $this->name, quantity: $this->quantity, diffusion: $this->diffusion, moneyAmount: $this->moneyAmount, processingCode: $this->processingCode, couponValidity: $this->couponValidity, couponValidityInformation: [$this->franceValidityInformation], ); // THEN expect($coupon->gs1)->toBeNull(); }); });