195 lines
8.1 KiB
PHP
195 lines
8.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\Application\UseCases\Coupon\Update;
|
|
|
|
use Application\UseCases\Coupon\Update\Input;
|
|
use Application\UseCases\Coupon\Update\Output\CouponNotFound;
|
|
use Application\UseCases\Coupon\Update\Output\CouponUpdated;
|
|
use Application\UseCases\Coupon\Update\UpdateCoupon;
|
|
use DateTime;
|
|
use Domain\Models\Entities\Coupon;
|
|
use Domain\Models\ValueObjects\Actor\ActorId;
|
|
use Domain\Models\ValueObjects\Brand\BrandCode;
|
|
use Domain\Models\ValueObjects\Coupon\CouponCode;
|
|
use Domain\Models\ValueObjects\Coupon\CouponDiffusion;
|
|
use Domain\Models\ValueObjects\Coupon\CouponId;
|
|
use Domain\Models\ValueObjects\Coupon\CouponLegalInformation;
|
|
use Domain\Models\ValueObjects\Coupon\CouponLegalInformationArray;
|
|
use Domain\Models\ValueObjects\Coupon\CouponMovement;
|
|
use Domain\Models\ValueObjects\Coupon\CouponMovementArray;
|
|
use Domain\Models\ValueObjects\Coupon\CouponName;
|
|
use Domain\Models\ValueObjects\Coupon\CouponPicture;
|
|
use Domain\Models\ValueObjects\Coupon\CouponProductArray;
|
|
use Domain\Models\ValueObjects\Coupon\CouponQuantity;
|
|
use Domain\Models\ValueObjects\Coupon\CouponValidityInformation;
|
|
use Domain\Models\ValueObjects\Coupon\CouponValidityInformationArray;
|
|
use Domain\Models\ValueObjects\IncoCode;
|
|
use Domain\Models\ValueObjects\MoneyAmount;
|
|
use Domain\Models\ValueObjects\Period;
|
|
use Domain\Models\ValueObjects\PicturePath;
|
|
use Domain\Models\ValueObjects\ProcessingCode;
|
|
use Domain\Models\ValueObjects\ProcessingCodeArray;
|
|
use Domain\Ports\Repositories\CouponRepository;
|
|
use Shared\Enums\Country;
|
|
use Shared\Enums\Currency;
|
|
use Shared\ValueObjects\Money;
|
|
|
|
covers(UpdateCoupon::class, Input::class, CouponUpdated::class, CouponNotFound::class);
|
|
|
|
describe('update coupon use case', function (): void {
|
|
$makeCoupon = static fn (): Coupon => 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),
|
|
]),
|
|
quantity: new CouponQuantity(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->quantity === $coupon->quantity
|
|
&& $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)
|
|
->and($result->updatedAt)->not->toBeNull();
|
|
});
|
|
|
|
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);
|
|
});
|
|
});
|