Add unit tests for PerChannelPromotionActionCommand and PerChannelRuleChecker

This commit is contained in:
Tomasz Kaliński 2026-06-25 13:31:50 +02:00
parent 32f003d5da
commit bdbf5d9578
2 changed files with 225 additions and 0 deletions

View file

@ -0,0 +1,126 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Tests\Sylius\Component\Core\Promotion\Action;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Promotion\Action\PerChannelPromotionActionCommand;
use Sylius\Component\Promotion\Action\PromotionActionCommandInterface;
use Sylius\Component\Promotion\Model\PromotionInterface;
use Sylius\Component\Promotion\Model\PromotionSubjectInterface;
use Sylius\Resource\Exception\UnexpectedTypeException;
#[CoversClass(PerChannelPromotionActionCommand::class)]
final class PerChannelPromotionActionCommandTest extends TestCase
{
private MockObject&PromotionActionCommandInterface $decorated;
private ChannelInterface&MockObject $channel;
private MockObject&OrderInterface $order;
private MockObject&PromotionInterface $promotion;
private PerChannelPromotionActionCommand $command;
protected function setUp(): void
{
$this->decorated = $this->createMock(PromotionActionCommandInterface::class);
$this->channel = $this->createMock(ChannelInterface::class);
$this->order = $this->createMock(OrderInterface::class);
$this->promotion = $this->createMock(PromotionInterface::class);
$this->command = new PerChannelPromotionActionCommand($this->decorated);
}
public function testShouldImplementPromotionActionCommandInterface(): void
{
$this->assertInstanceOf(PromotionActionCommandInterface::class, $this->command);
}
public function testShouldExecuteDecoratedCommandWithTheChannelConfiguration(): void
{
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
$this->decorated->expects($this->once())
->method('execute')
->with($this->order, ['percentage' => 0.2], $this->promotion)
->willReturn(true)
;
$this->assertTrue($this->command->execute($this->order, ['WEB_US' => ['percentage' => 0.2]], $this->promotion));
}
public function testShouldNotExecuteDecoratedCommandIfThereIsNoConfigurationForTheOrderChannel(): void
{
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
$this->decorated->expects($this->never())->method('execute');
$this->assertFalse($this->command->execute($this->order, ['WEB_EU' => ['percentage' => 0.2]], $this->promotion));
}
public function testShouldNotExecuteDecoratedCommandWhenOrderHasNoChannel(): void
{
$this->order->expects($this->once())->method('getChannel')->willReturn(null);
$this->decorated->expects($this->never())->method('execute');
$this->assertFalse($this->command->execute($this->order, ['WEB_US' => ['percentage' => 0.2]], $this->promotion));
}
public function testShouldThrowExceptionWhenExecutingIfPromotionSubjectIsNotOrder(): void
{
$this->expectException(UnexpectedTypeException::class);
$this->command->execute($this->createMock(PromotionSubjectInterface::class), [], $this->promotion);
}
public function testShouldRevertDecoratedCommandWithTheChannelConfiguration(): void
{
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
$this->decorated->expects($this->once())
->method('revert')
->with($this->order, ['percentage' => 0.2], $this->promotion)
;
$this->command->revert($this->order, ['WEB_US' => ['percentage' => 0.2]], $this->promotion);
}
public function testShouldNotRevertDecoratedCommandIfThereIsNoConfigurationForTheOrderChannel(): void
{
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
$this->decorated->expects($this->never())->method('revert');
$this->command->revert($this->order, ['WEB_EU' => ['percentage' => 0.2]], $this->promotion);
}
public function testShouldNotRevertDecoratedCommandWhenOrderHasNoChannel(): void
{
$this->order->expects($this->once())->method('getChannel')->willReturn(null);
$this->decorated->expects($this->never())->method('revert');
$this->command->revert($this->order, ['WEB_US' => ['percentage' => 0.2]], $this->promotion);
}
public function testShouldThrowExceptionWhenRevertingIfPromotionSubjectIsNotOrder(): void
{
$this->expectException(UnexpectedTypeException::class);
$this->command->revert($this->createMock(PromotionSubjectInterface::class), [], $this->promotion);
}
}

View file

@ -0,0 +1,99 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Tests\Sylius\Component\Core\Promotion\Checker\Rule;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Promotion\Checker\Rule\PerChannelRuleChecker;
use Sylius\Component\Promotion\Checker\Rule\RuleCheckerInterface;
use Sylius\Component\Promotion\Exception\UnsupportedTypeException;
use Sylius\Component\Promotion\Model\PromotionSubjectInterface;
#[CoversClass(PerChannelRuleChecker::class)]
final class PerChannelRuleCheckerTest extends TestCase
{
private MockObject&RuleCheckerInterface $decorated;
private ChannelInterface&MockObject $channel;
private MockObject&OrderInterface $order;
private PerChannelRuleChecker $ruleChecker;
protected function setUp(): void
{
$this->decorated = $this->createMock(RuleCheckerInterface::class);
$this->channel = $this->createMock(ChannelInterface::class);
$this->order = $this->createMock(OrderInterface::class);
$this->ruleChecker = new PerChannelRuleChecker($this->decorated);
}
public function testShouldImplementRuleCheckerInterface(): void
{
$this->assertInstanceOf(RuleCheckerInterface::class, $this->ruleChecker);
}
public function testShouldDelegateToDecoratedCheckerWithTheChannelConfiguration(): void
{
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
$this->decorated->expects($this->once())
->method('isEligible')
->with($this->order, ['nth' => 5])
->willReturn(true)
;
$this->assertTrue($this->ruleChecker->isEligible($this->order, ['WEB_US' => ['nth' => 5]]));
}
public function testShouldReturnDecoratedCheckerResultForTheOrderChannel(): void
{
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
$this->decorated->expects($this->once())
->method('isEligible')
->with($this->order, ['nth' => 5])
->willReturn(false)
;
$this->assertFalse($this->ruleChecker->isEligible($this->order, ['WEB_US' => ['nth' => 5]]));
}
public function testShouldReturnFalseAndNotDelegateIfThereIsNoConfigurationForTheOrderChannel(): void
{
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
$this->decorated->expects($this->never())->method('isEligible');
$this->assertFalse($this->ruleChecker->isEligible($this->order, ['WEB_EU' => ['nth' => 5]]));
}
public function testShouldReturnFalseAndNotDelegateWhenOrderHasNoChannel(): void
{
$this->order->expects($this->once())->method('getChannel')->willReturn(null);
$this->decorated->expects($this->never())->method('isEligible');
$this->assertFalse($this->ruleChecker->isEligible($this->order, ['WEB_US' => ['nth' => 5]]));
}
public function testShouldThrowExceptionIfPromotionSubjectIsNotOrder(): void
{
$this->expectException(UnsupportedTypeException::class);
$this->ruleChecker->isEligible($this->createMock(PromotionSubjectInterface::class), []);
}
}