Skip to content

Commit

Permalink
Merge pull request #12 from JakobTolkemit/fix_date_overlap_validator
Browse files Browse the repository at this point in the history
Fix date overlap validator
  • Loading branch information
JakobTolkemit authored Aug 13, 2020
2 parents 1f4d812 + 910e418 commit b04407f
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 32 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
"psr-4": {
"Brille24\\SyliusSpecialPricePlugin\\": "src/",
"Tests\\Brille24\\SyliusSpecialPricePlugin\\": "tests/",
"Tests\\Application\\SyliusSpecialPricePlugin\\": "tests/Application/src/"
"Tests\\Application\\SyliusSpecialPricePlugin\\": "tests/Application/src/",
"spec\\Brille24\\SyliusSpecialPricePlugin\\": "spec/"
}
},
"autoload-dev": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Brille24\SyliusSpecialPricePlugin\Entity\ChannelSpecialPricing;
use Brille24\SyliusSpecialPricePlugin\Validator\ProductVariantChannelSpecialPriceDateOverlapConstraint;
use Brille24\SyliusSpecialPricePlugin\Validator\ProductVariantChannelSpecialPriceDateOverlapValidator;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
Expand All @@ -17,7 +18,7 @@

class ProductVariantChannelSpecialPriceDateOverlapValidatorSpec extends ObjectBehavior
{
function let(
public function let(
ExecutionContextInterface $context,
ConstraintViolationBuilderInterface $violationBuilder
): void {
Expand All @@ -27,63 +28,85 @@ function let(
$this->initialize($context);
}

function it_is_initializable()
public function it_is_initializable()
{
$this->shouldHaveType(ProductVariantChannelSpecialPriceDateOverlapValidator::class);
}

function it_is_a_validator()
public function it_is_a_validator()
{
$this->shouldBeAnInstanceOf(ConstraintValidator::class);
}

function it_does_not_add_violation_if_dates_dont_overlap(
public function it_does_not_add_violation_if_dates_dont_overlap(
ProductVariant $productVariant,
ProductVariantChannelSpecialPriceDateOverlapConstraint $constraint,
ExecutionContextInterface $context,
ConstraintViolationBuilderInterface $violationBuilder
): void {
$firstPrice = new ChannelSpecialPricing();
$firstPrice->setStartsAt(new \DateTime('2 days ago'));
$firstPrice->setEndsAt(new \DateTime('yesterday'));
$firstPrice->setChannelCode('FIRST');

$secondPrice = new ChannelSpecialPricing();
$secondPrice->setStartsAt(new \DateTime('now'));
$secondPrice->setEndsAt(new \DateTime('tomorrow'));
$secondPrice->setChannelCode('FIRST');

$productVariant->getChannelSpecialPricings()->willReturn(new ArrayCollection([$firstPrice, $secondPrice]));
foreach ($this->notOverlappingDatesProvider() as $dates) {
$productVariant->getChannelSpecialPricings()->willReturn(new ArrayCollection($this->getChannelPrices($dates)));

$context->buildViolation(Argument::any())->shouldNotBeCalled();
$violationBuilder->atPath(Argument::any())->shouldNotBeCalled();
$violationBuilder->addViolation()->shouldNotBeCalled();
$context->buildViolation(Argument::any())->shouldNotBeCalled();
$violationBuilder->atPath(Argument::any())->shouldNotBeCalled();
$violationBuilder->addViolation()->shouldNotBeCalled();

$this->validate($productVariant, $constraint);
$this->validate($productVariant, $constraint);
}
}

function it_adds_violation_if_dates_overlap(
public function it_adds_violation_if_dates_overlap(
ProductVariant $productVariant,
ProductVariantChannelSpecialPriceDateOverlapConstraint $constraint,
ExecutionContextInterface $context,
ConstraintViolationBuilderInterface $violationBuilder
): void {
foreach ($this->overlappingDatesProvider() as $dates) {
$productVariant->getChannelSpecialPricings()->willReturn(new ArrayCollection($this->getChannelPrices($dates)));

$context->buildViolation(Argument::any())->shouldBeCalled();
$violationBuilder->atPath(Argument::any())->shouldBeCalled();
$violationBuilder->addViolation()->shouldBeCalled();

$this->validate($productVariant, $constraint);
}
}

private function getChannelPrices(array $dates): array
{
[$firstStart, $firstEnd, $secondStart, $secondEnd] = $dates;

$firstPrice = new ChannelSpecialPricing();
$firstPrice->setStartsAt(new \DateTime('2 days ago'));
$firstPrice->setEndsAt(new \DateTime('tomorrow'));
$firstPrice->setStartsAt($firstStart);
$firstPrice->setEndsAt($firstEnd);
$firstPrice->setChannelCode('FIRST');

$secondPrice = new ChannelSpecialPricing();
$secondPrice->setStartsAt(new \DateTime('now'));
$secondPrice->setEndsAt(new \DateTime('tomorrow'));
$secondPrice->setStartsAt($secondStart);
$secondPrice->setEndsAt($secondEnd);
$secondPrice->setChannelCode('FIRST');

$productVariant->getChannelSpecialPricings()->willReturn(new ArrayCollection([$firstPrice, $secondPrice]));
return [$firstPrice, $secondPrice];
}

$context->buildViolation(Argument::any())->shouldBeCalled();
$violationBuilder->atPath(Argument::any())->shouldBeCalled();
$violationBuilder->addViolation()->shouldBeCalled();
private function overlappingDatesProvider(): array
{
return [
[null, null, null, null],
[null, null, null, new \DateTime('now')],
[null, null, new \DateTime('now'), null],
[new \DateTime('now'), new \DateTime('tomorrow'), new \DateTime('yesterday'), new \DateTime('tomorrow')],
[new \DateTime('now'), new \DateTime('tomorrow'), new \DateTime('yesterday'), null],
[new \DateTime('now'), new \DateTime('tomorrow'), null, new \DateTime('tomorrow')],
[new \DateTime('now'), null, null, new \DateTime('tomorrow')],
];
}

$this->validate($productVariant, $constraint);
private function notOverlappingDatesProvider(): array
{
return [
[new \DateTime('tomorrow'), null, null, new \DateTime('now')],
[new \DateTime('yesterday'), new \DateTime('now'), new \DateTime('+1 minute'), new \DateTime('tomorrow')],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ private function overlapWithNullValues(ChannelSpecialPricingInterface $a, Channe

// Start null = active till end
if ($a->getStartsAt() === null) {
if ($b->getStartsAt() < $a->getEndsAt() || $b->getEndsAt() < $a->getEndsAt()) {
if ($b->getStartsAt() < $a->getEndsAt()) {
return true;
}
}

// End null = active since start
if ($a->getEndsAt() === null) {
if ($b->getStartsAt() > $a->getStartsAt() || $b->getEndsAt() > $a->getStartsAt()) {
if ($b->getEndsAt() > $a->getStartsAt()) {
return true;
}
}
Expand Down

0 comments on commit b04407f

Please sign in to comment.