Coupon::hydrate( id: CouponId::generate(), code: new CouponCode('COU01'), name: new CouponName('Coupon name'), amount: new MoneyAmount(new Money(Currency::EUR, 100)), picture: new CouponPicture( new PicturePath('files/decoration-old.jpg'), new PicturePath('files/thumbnail-old.jpg'), new PicturePath('files/mobile-thumbnail-old.jpg'), ), diffusion: new CouponDiffusion( new Period( new DateTime('2026-01-01'), new DateTime('2026-02-01'), ), ), validityInformations: new CouponValidityInformationArray([ new CouponValidityInformation( 'Lorem ipsum dolor sit amet consectetur adipiscing elit.', Country::FRANCE, ), ]), legalInformations: new CouponLegalInformationArray([ new CouponLegalInformation( 'Lorem ipsum dolor sit amet consectetur adipiscing elit.', Country::FRANCE, ), ]), processingCode: new ProcessingCodeArray([ new ProcessingCode('5425003944130', Country::FRANCE), ]), brandCode: new BrandCode('AAA01'), createdBy: ActorId::generate(), products: new CouponProductArray([ new IncoCode(35784), new IncoCode(15522), ]), movements: new CouponMovementArray([ new CouponMovement(1000), ]), ); it('updates the picture and keeps the other fields', function () use ($makeCoupon): void { // GIVEN $coupon = $makeCoupon(); $newPicture = new CouponPicture( new PicturePath('files/decoration-new.jpg'), new PicturePath('files/thumbnail-new.jpg'), new PicturePath('files/mobile-thumbnail-new.jpg'), ); $input = new Input(code: $coupon->code, picture: $newPicture); $repository = \Mockery::mock(CouponRepository::class); $repository->shouldReceive('findByCode')->once()->with($coupon->code)->andReturn($coupon); $repository->shouldReceive('save')->once()->with(\Mockery::on( fn (Coupon $saved): bool => $saved->picture === $newPicture && $saved->id === $coupon->id && $saved->code === $coupon->code && $saved->name === $coupon->name && $saved->amount === $coupon->amount && $saved->diffusion === $coupon->diffusion && $saved->updatedAt instanceof \DateTimeInterface, )); $useCase = new UpdateCoupon($repository); // WHEN $result = $useCase->execute($input); // THEN expect($result)->toBeInstanceOf(CouponUpdated::class) ->and($result->code)->toBe($coupon->code) ->and($result->picture)->toBe($newPicture); }); it('returns CouponNotFound when the coupon does not exist', function (): void { // GIVEN $code = new CouponCode('COU01'); $input = new Input( code: $code, picture: new CouponPicture( new PicturePath('files/decoration-new.jpg'), new PicturePath('files/thumbnail-new.jpg'), new PicturePath('files/mobile-thumbnail-new.jpg'), ), ); $repository = \Mockery::mock(CouponRepository::class); $repository->shouldReceive('findByCode')->once()->with($code)->andReturn(null); $repository->shouldNotReceive('save'); $useCase = new UpdateCoupon($repository); // WHEN $result = $useCase->execute($input); // THEN expect($result)->toBeInstanceOf(CouponNotFound::class); }); it('updates the legal and validity information and keeps the other fields', function () use ($makeCoupon): void { // GIVEN $coupon = $makeCoupon(); $newValidityInformations = new CouponValidityInformationArray([ new CouponValidityInformation('New validity information.', Country::FRANCE), ]); $newLegalInformations = new CouponLegalInformationArray([ new CouponLegalInformation('New legal information.', Country::FRANCE), ]); $input = new Input( code: $coupon->code, validityInformations: $newValidityInformations, legalInformations: $newLegalInformations, ); $repository = \Mockery::mock(CouponRepository::class); $repository->shouldReceive('findByCode')->once()->with($coupon->code)->andReturn($coupon); $repository->shouldReceive('save')->once()->with(\Mockery::on( fn (Coupon $saved): bool => $saved->validityInformations === $newValidityInformations && $saved->legalInformations === $newLegalInformations && $saved->id === $coupon->id && $saved->name === $coupon->name && $saved->amount === $coupon->amount && $saved->picture === $coupon->picture && $saved->diffusion === $coupon->diffusion && $saved->movements === $coupon->movements && $saved->updatedAt instanceof \DateTimeInterface, )); $useCase = new UpdateCoupon($repository); // WHEN $result = $useCase->execute($input); // THEN expect($result)->toBeInstanceOf(CouponUpdated::class) ->and($result->validityInformations)->toBe($newValidityInformations) ->and($result->legalInformations)->toBe($newLegalInformations); }); it('rejects an input with nothing to update', function (): void { // GIVEN $code = new CouponCode('COU01'); // WHEN $action = fn (): Input => new Input(code: $code); // THEN expect($action)->toThrow(\InvalidArgumentException::class); }); });