ldc-mesbr-app/tests/Unit/Application/UseCases/Campaign/Update/AutoUnpublishCampaignTest.php

171 lines
7.2 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Unit\Application\UseCases\Campaign\Update;
use Application\UseCases\Campaign\Outputs\CampaignNotFound;
use Application\UseCases\Campaign\Update\AutoUnpublishCampaign;
use Application\UseCases\Campaign\Update\Inputs\AutoUnpublishCampaignInput;
use Application\UseCases\Campaign\Update\Outputs\CampaignStatusUpdated;
use Application\UseCases\Campaign\Update\Outputs\CampaignUnpublicationSkipped;
use Domain\Models\Entities\Campaign;
use Domain\Models\ValueObjects\Campaign\CampaignCode;
use Domain\Models\ValueObjects\Coupon\CouponCode;
use Domain\Ports\Repositories\CampaignRepository;
use Domain\Ports\Repositories\CouponRepository;
use Domain\Services\Campaign\CampaignAvailabilityChecker;
use Tests\Fixtures\Campaign\CampaignFactory;
use Tests\Fixtures\Coupon\CouponFactory;
covers(
AutoUnpublishCampaign::class,
AutoUnpublishCampaignInput::class,
CampaignStatusUpdated::class,
CampaignUnpublicationSkipped::class,
CampaignNotFound::class,
);
describe('auto unpublish campaign use case', function (): void {
it('returns CampaignNotFound when the campaign does not exist', function (): void {
// GIVEN
$code = CampaignCode::generate();
$repository = \Mockery::mock(CampaignRepository::class);
$repository->shouldReceive('findByCode')->once()->with($code)->andReturn(null);
$repository->shouldNotReceive('save');
$couponRepository = \Mockery::mock(CouponRepository::class);
$couponRepository->shouldNotReceive('findByCodes');
$useCase = new AutoUnpublishCampaign($repository, new CampaignAvailabilityChecker($couponRepository));
// WHEN
$result = $useCase->execute(new AutoUnpublishCampaignInput($code));
// THEN
expect($result)->toBeInstanceOf(CampaignNotFound::class);
});
it('skips an already unpublished campaign without querying coupons', function (): void {
// GIVEN
$campaign = CampaignFactory::hydrated(published: false);
$repository = \Mockery::mock(CampaignRepository::class);
$repository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign);
$repository->shouldNotReceive('save');
$couponRepository = \Mockery::mock(CouponRepository::class);
$couponRepository->shouldNotReceive('findByCodes');
$useCase = new AutoUnpublishCampaign($repository, new CampaignAvailabilityChecker($couponRepository));
// WHEN
$result = $useCase->execute(new AutoUnpublishCampaignInput($campaign->code));
// THEN
expect($result)->toBeInstanceOf(CampaignUnpublicationSkipped::class);
});
it('skips a published campaign that still has an active coupon', function (): void {
// GIVEN
$couponCode = CouponCode::generate();
$campaign = CampaignFactory::hydrated(published: true, couponCodes: [$couponCode]);
$repository = \Mockery::mock(CampaignRepository::class);
$repository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign);
$repository->shouldNotReceive('save');
$couponRepository = \Mockery::mock(CouponRepository::class);
$couponRepository->shouldReceive('findByCodes')->once()->andReturn([CouponFactory::make()]);
$useCase = new AutoUnpublishCampaign($repository, new CampaignAvailabilityChecker($couponRepository));
// WHEN
$result = $useCase->execute(new AutoUnpublishCampaignInput($campaign->code));
// THEN
expect($result)->toBeInstanceOf(CampaignUnpublicationSkipped::class);
});
it('skips a published campaign with one active and one expired coupon', function (): void {
// GIVEN
$campaign = CampaignFactory::hydrated(published: true, couponCodes: [CouponCode::generate(), CouponCode::generate()]);
$repository = \Mockery::mock(CampaignRepository::class);
$repository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign);
$repository->shouldNotReceive('save');
$couponRepository = \Mockery::mock(CouponRepository::class);
$couponRepository->shouldReceive('findByCodes')->once()->andReturn([
CouponFactory::expired(),
CouponFactory::make(),
]);
$useCase = new AutoUnpublishCampaign($repository, new CampaignAvailabilityChecker($couponRepository));
// WHEN
$result = $useCase->execute(new AutoUnpublishCampaignInput($campaign->code));
// THEN
expect($result)->toBeInstanceOf(CampaignUnpublicationSkipped::class);
});
it('unpublishes a published campaign when every coupon is not available', function (): void {
// GIVEN
$couponCode1 = CouponCode::generate();
$couponCode2 = CouponCode::generate();
$campaign = CampaignFactory::hydrated(published: true, couponCodes: [$couponCode1->value, $couponCode2->value]);
$repository = \Mockery::mock(CampaignRepository::class);
$repository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign);
$repository->shouldReceive('save')->once()->with(\Mockery::on(
static fn (Campaign $saved): bool => $saved->publication === false
&& $saved->code === $campaign->code
&& $saved->updatedAt() instanceof \DateTimeInterface,
));
$couponRepository = \Mockery::mock(CouponRepository::class);
$couponRepository->shouldReceive('findByCodes')->once()->andReturn([
CouponFactory::expired(),
CouponFactory::upcoming(),
]);
$useCase = new AutoUnpublishCampaign($repository, new CampaignAvailabilityChecker($couponRepository));
// WHEN
$result = $useCase->execute(new AutoUnpublishCampaignInput($campaign->code));
// THEN
expect($result)->toBeInstanceOf(CampaignStatusUpdated::class)
->and($result->publication)->toBeFalse()
->and($result->code)->toBe($campaign->code)
->and($result->name)->toBe($campaign->name)
->and($result->brandCode)->toBe($campaign->brandCode)
->and($result->coupons)->toBe($campaign->coupons);
});
it('unpublishes a published campaign when no coupon is found', function (): void {
// GIVEN
$couponCode = CouponCode::generate();
$campaign = CampaignFactory::hydrated(published: true, couponCodes: [$couponCode]);
$repository = \Mockery::mock(CampaignRepository::class);
$repository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign);
$repository->shouldReceive('save')->once()->with(\Mockery::on(
static fn (Campaign $saved): bool => $saved->publication === false,
));
$couponRepository = \Mockery::mock(CouponRepository::class);
$couponRepository->shouldReceive('findByCodes')->once()->andReturn([]);
$useCase = new AutoUnpublishCampaign($repository, new CampaignAvailabilityChecker($couponRepository));
// WHEN
$result = $useCase->execute(new AutoUnpublishCampaignInput($campaign->code));
// THEN
expect($result)->toBeInstanceOf(CampaignStatusUpdated::class)
->and($result->publication)->toBeFalse();
});
});