tag = Tag::hydrate( TagId::generate(), new TagName('Tag A'), ); }); afterEach(function (): void { CarbonImmutable::setTestNow(); }); it('creates a campaign', function (): void { // GIVEN $id = CampaignId::generate(); $code = new CampaignCode('Camp100'); $name = new CampaignName('Name'); $publication = \boolval(0); $printAllAtOnce = \boolval(1); $availableIn = Country::FRANCE; $coupons = [ new CampaignCoupon( new ProcessingCode('PC1'), StockId::generate(), new WarningThresholdQuantity(100), new PrintRules(maxPerCustomer: 3) ) ]; $brand = new BrandCode('AAA01'); // WHEN $campaign = Campaign::hydrate( $id, $code, $this->tag, $name, $publication, $printAllAtOnce, $availableIn, $coupons, $brand, ); // THEN expect($campaign->id())->toBe($id) ->and($campaign->code)->toBe($code) ->and($campaign->tag)->toBe($this->tag) ->and($campaign->name)->toBe($name) ->and($campaign->publication)->toBe($publication) ->and($campaign->printAllAtOnce)->toBe($printAllAtOnce) ->and($campaign->availableIn)->toBe($availableIn) ->and($campaign->coupons)->toBe($coupons) ->and($campaign->brand)->toBe($brand) ->and($campaign->updatedAt)->toBeNull() ->and($campaign->updatedAt())->toBeNull(); }); it('creates a campaign without coupon', function (): void { // GIVEN $id = CampaignId::generate(); $code = new CampaignCode('Camp100'); $name = new CampaignName('Name'); $publication = \boolval(0); $printAllAtOnce = \boolval(1); $availableIn = Country::FRANCE; $coupons = []; $brand = new BrandCode('AAA01'); // WHEN $campaign = Campaign::hydrate( $id, $code, $this->tag, $name, $publication, $printAllAtOnce, $availableIn, $coupons, $brand, ); // THEN expect($campaign->coupons)->toBe([]); }); it('creates a coupon with an explicit updatedAt date', function (): void { // GIVEN $id = CampaignId::generate(); $code = new CampaignCode('Camp100'); $name = new CampaignName('Name'); $publication = \boolval(0); $printAllAtOnce = \boolval(1); $availableIn = Country::FRANCE; $coupons = [ new CampaignCoupon( new ProcessingCode('PC1'), StockId::generate(), new WarningThresholdQuantity(100), new PrintRules(maxPerCustomer: 3) ) ]; $brand = new BrandCode('AAA01'); $updatedAt = new \DateTimeImmutable('2026-09-22 10:00:00', new \DateTimeZone('UTC')); // WHEN $campaign = Campaign::hydrate( $id, $code, $this->tag, $name, $publication, $printAllAtOnce, $availableIn, $coupons, $brand, $updatedAt ); // THEN expect($campaign->updatedAt)->toBe($updatedAt) ->and($campaign->updatedAt())->toBe($updatedAt); }); it('creates a new campaign with a freshly generated id', function (): void { // GIVEN $code = new CampaignCode('Camp100'); $name = new CampaignName('Name'); $publication = \boolval(0); $printAllAtOnce = \boolval(1); $availableIn = Country::FRANCE; $coupons = [ new CampaignCoupon( new ProcessingCode('PC1'), StockId::generate(), new WarningThresholdQuantity(100), new PrintRules(maxPerCustomer: 3) ) ]; $brand = new BrandCode('AAA01'); // WHEN $campaign = Campaign::create( $code, $this->tag, $name, $publication, $printAllAtOnce, $availableIn, $coupons, $brand ); // THEN expect($campaign->id())->toBeInstanceOf(CampaignId::class) ->and($campaign->code)->toBe($code) ->and($campaign->tag)->toBe($this->tag) ->and($campaign->name)->toBe($name) ->and($campaign->publication)->toBe($publication) ->and($campaign->printAllAtOnce)->toBe($printAllAtOnce) ->and($campaign->availableIn)->toBe($availableIn) ->and($campaign->coupons)->toBe($coupons) ->and($campaign->brand)->toBe($brand) ->and($campaign->updatedAt)->toBeNull() ->and($campaign->updatedAt())->toBeNull(); }); it('generates a different id for each created campaign', function (): void { // GIVEN $code = new CampaignCode('Camp100'); $name = new CampaignName('Name'); $publication = \boolval(0); $printAllAtOnce = \boolval(1); $availableIn = Country::FRANCE; $coupons = [ new CampaignCoupon( new ProcessingCode('PC1'), StockId::generate(), new WarningThresholdQuantity(100), new PrintRules(maxPerCustomer: 3) ) ]; $brand = new BrandCode('AAA01'); // WHEN $firstCampaign = Campaign::create( $code, $this->tag, $name, $publication, $printAllAtOnce, $availableIn, $coupons, $brand ); $secondCampaign = Campaign::create( $code, $this->tag, $name, $publication, $printAllAtOnce, $availableIn, $coupons, $brand ); // THEN expect($firstCampaign->id()->equals($secondCampaign->id()))->toBeFalse(); }); it('returns the creation date extracted from the id', function (): void { // GIVEN $expected = new \DateTimeImmutable('2024-06-15 12:34:56.789000', new \DateTimeZone('UTC')); $id = new CampaignId(Uuid::uuid7($expected)); $campaign = Campaign::hydrate( $id, new CampaignCode('Camp100'), $this->tag, new CampaignName('Name'), \boolval(0), \boolval(1), Country::FRANCE, [ new CampaignCoupon( new ProcessingCode('PC1'), StockId::generate(), new WarningThresholdQuantity(100), new PrintRules(maxPerCustomer: 3) ) ], new BrandCode('AAA01') ); // WHEN $result = $campaign->createdAt(); // THEN expect($result->format('Y-m-d H:i:s.v'))->toBe($expected->format('Y-m-d H:i:s.v')); }); it('rejects a campaign with a non-coupon element', function (): void { // GIVEN $id = CampaignId::generate(); $code = new CampaignCode('Camp100'); $name = new CampaignName('Name'); $publication = \boolval(0); $printAllAtOnce = \boolval(1); $availableIn = Country::FRANCE; $coupons = ['PC1']; $brand = new BrandCode('AAA01'); // WHEN / THEN expect(fn (): Campaign => Campaign::hydrate( $id, $code, $this->tag, $name, $publication, $printAllAtOnce, $availableIn, $coupons, $brand ))->toThrow(\DomainException::class, 'Campaign coupons must be CampaignCoupon instances.'); }); });