ldc-mesbr-app/tests/Unit/Application/UseCases/Coupon/Create/CreateCouponTest.php

151 lines
6.3 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Unit\Application\UseCases\Coupon\Create;
use Application\UseCases\Coupon\Create\CreateCoupon;
use Application\UseCases\Coupon\Create\Input;
use Application\UseCases\Coupon\Create\Output;
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\CouponMovementArray;
use Domain\Models\ValueObjects\Coupon\CouponName;
use Domain\Models\ValueObjects\Coupon\CouponPicture;
use Domain\Models\ValueObjects\Coupon\CouponProcessingCode;
use Domain\Models\ValueObjects\Coupon\CouponProcessingCodeArray;
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\MoneyAmount;
use Domain\Models\ValueObjects\Period;
use Domain\Models\ValueObjects\PicturePath;
use Domain\Ports\Repositories\BrandRepository;
use Domain\Ports\Repositories\CouponRepository;
use Shared\Enums\Country;
use Shared\Enums\Currency;
use Shared\ValueObjects\Money;
covers(CreateCoupon::class, Input::class, Output::class);
describe('create coupon use case', function (): void {
$makeInput = fn (): Input => new Input(
code: new CouponCode('COU01'),
name: new CouponName('Coupon name'),
amount: new MoneyAmount(new Money(Currency::EUR, 100)),
picture: new CouponPicture(
new PicturePath('files/product.jpg'),
new PicturePath('files/thumbnail.jpg'),
new PicturePath('files/mobileThumbnail.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 CouponProcessingCodeArray([
new CouponProcessingCode('5425003944130', Country::FRANCE),
]),
brandCode: new BrandCode('TST89'),
createdBy: ActorId::generate(),
products: new CouponProductArray(),
quantity: new CouponQuantity(1000),
);
it('creates a coupon when the brand exists and the code is unique', function () use ($makeInput): void {
// GIVEN
$input = $makeInput();
$brandRepository = \Mockery::mock(BrandRepository::class);
$brandRepository->shouldReceive('existsByCode')->once()->with($input->brandCode)->andReturn(true);
$couponRepository = \Mockery::mock(CouponRepository::class);
$couponRepository->shouldReceive('existsByCode')->once()->with($input->code)->andReturn(false);
$couponRepository->shouldReceive('save')->once()->with(\Mockery::type(Coupon::class));
$useCase = new CreateCoupon($couponRepository, $brandRepository);
// WHEN
$result = $useCase->execute($input);
// THEN
expect($result)->toBeInstanceOf(Output::class)
->and($result->id)->toBeInstanceOf(CouponId::class)
->and($result->code)->toEqual($input->code)
->and($result->name)->toEqual($input->name)
->and($result->amount)->toEqual($input->amount)
->and($result->picture)->toEqual($input->picture)
->and($result->diffusion)->toEqual($input->diffusion)
->and($result->validityInformations)->toEqual($input->validityInformations)
->and($result->legalInformations)->toEqual($input->legalInformations)
->and($result->processingCode)->toEqual($input->processingCode)
->and($result->brandCode)->toEqual($input->brandCode)
->and($result->createdBy)->toEqual($input->createdBy)
->and($result->products)->toEqual($input->products)
->and($result->movements)->toBeInstanceOf(CouponMovementArray::class)
->and($result->quantity)->toEqual($input->quantity)
->and($result->availabilityCalendar)->toBeNull()
->and($result->createdAt)->toBeInstanceOf(\DateTimeInterface::class);
});
it('throws when the brand does not exist', function () use ($makeInput): void {
// GIVEN
$input = $makeInput();
$brandRepository = \Mockery::mock(BrandRepository::class);
$brandRepository->shouldReceive('existsByCode')->once()->with($input->brandCode)->andReturn(false);
$couponRepository = \Mockery::mock(CouponRepository::class);
$couponRepository->shouldNotReceive('existsByCode');
$couponRepository->shouldNotReceive('save');
$useCase = new CreateCoupon($couponRepository, $brandRepository);
// WHEN
$action = fn (): Output => $useCase->execute($input);
// THEN
expect($action)->toThrow(\DomainException::class, 'Brand code "TST89" was not found.');
});
it('throws when the coupon code already exists', function () use ($makeInput): void {
// GIVEN
$input = $makeInput();
$brandRepository = \Mockery::mock(BrandRepository::class);
$brandRepository->shouldReceive('existsByCode')->once()->with($input->brandCode)->andReturn(true);
$couponRepository = \Mockery::mock(CouponRepository::class);
$couponRepository->shouldReceive('existsByCode')->once()->with($input->code)->andReturn(true);
$couponRepository->shouldNotReceive('save');
$useCase = new CreateCoupon($couponRepository, $brandRepository);
// WHEN
$action = fn (): Output => $useCase->execute($input);
// THEN
expect($action)->toThrow(\DomainException::class, 'Coupon code "COU01" already exists.');
});
});