Skip to content

Commit d54cd13

Browse files
committed
fix: handle coupon code type compatibility between Magento 2.4.4 and 2.4.8
1 parent b766c7d commit d54cd13

File tree

4 files changed

+194
-11
lines changed

4 files changed

+194
-11
lines changed

Model/SalesRuleValidator.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ public function __construct(Request $request, SystemConfig $systemConfig)
3333

3434
/**
3535
* @param Rule $rule
36-
* @param array $couponCode
36+
* @param string|array $couponCode
3737
* @return bool
3838
*/
39-
public function isValid(Rule $rule, array $couponCode): bool
39+
public function isValid(Rule $rule, $couponCode): bool
4040
{
4141
$code = $rule->getPrimaryCoupon()->getCode();
42+
$couponCodes = is_array($couponCode) ? $couponCode : [$couponCode];
4243

43-
if ($code !== null && $rule->getData('is_grin_only') && in_array($code, $couponCode)) {
44+
if ($code !== null && $rule->getData('is_grin_only') && in_array($code, $couponCodes)) {
4445
return $this->request->getHeader(self::TOKEN_HEADER) === $this->systemConfig->getSalesRuleToken();
4546
}
4647

Plugin/Magento/SalesRule/Model/RulesApplier/ValidateByToken.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,12 @@ public function aroundApplyRules(
4040
$skipValidation,
4141
$couponCode
4242
): array {
43-
// Convert string coupon code to array for consistent handling
44-
$couponCodes = is_array($couponCode) ? $couponCode : [$couponCode];
45-
4643
foreach ($rules as $rule) {
47-
if (!$this->salesRuleValidator->isValid($rule, $couponCodes)) {
48-
return $proceed($item, [], $skipValidation, $couponCodes);
44+
if (!$this->salesRuleValidator->isValid($rule, $couponCode)) {
45+
return $proceed($item, [], $skipValidation, $couponCode);
4946
}
5047
}
5148

52-
return $proceed($item, $rules, $skipValidation, $couponCodes);
49+
return $proceed($item, $rules, $skipValidation, $couponCode);
5350
}
5451
}
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Grin\Module\Test\Unit\Model;
6+
7+
use Grin\Module\Model\SalesRuleValidator;
8+
use Grin\Module\Model\SystemConfig;
9+
use Magento\Framework\HTTP\PhpEnvironment\Request;
10+
use Magento\SalesRule\Model\Rule;
11+
use Magento\SalesRule\Model\Coupon;
12+
use PHPUnit\Framework\TestCase;
13+
use PHPUnit\Framework\MockObject\MockObject;
14+
15+
class SalesRuleValidatorTest extends TestCase
16+
{
17+
/**
18+
* @var Request&MockObject
19+
*/
20+
private Request&MockObject $request;
21+
22+
/**
23+
* @var SystemConfig&MockObject
24+
*/
25+
private SystemConfig&MockObject $systemConfig;
26+
27+
/**
28+
* @var SalesRuleValidator
29+
*/
30+
private SalesRuleValidator $salesRuleValidator;
31+
32+
/**
33+
* @return void
34+
*/
35+
protected function setUp(): void
36+
{
37+
$this->request = $this->createMock(Request::class);
38+
$this->systemConfig = $this->createMock(SystemConfig::class);
39+
$this->salesRuleValidator = new SalesRuleValidator($this->request, $this->systemConfig);
40+
}
41+
42+
/**
43+
* @dataProvider couponCodeProvider
44+
*/
45+
public function testIsValidWithNonGrinRule(mixed $couponCode): void
46+
{
47+
/** @var Rule&MockObject $rule */
48+
$rule = $this->createMock(Rule::class);
49+
/** @var Coupon&MockObject $coupon */
50+
$coupon = $this->createMock(Coupon::class);
51+
52+
$rule->expects($this->once())
53+
->method('getPrimaryCoupon')
54+
->willReturn($coupon);
55+
56+
$coupon->expects($this->once())
57+
->method('getCode')
58+
->willReturn('TEST123');
59+
60+
$rule->expects($this->once())
61+
->method('getData')
62+
->with('is_grin_only')
63+
->willReturn(0);
64+
65+
$this->assertTrue($this->salesRuleValidator->isValid($rule, $couponCode));
66+
}
67+
68+
/**
69+
* @dataProvider couponCodeProvider
70+
*/
71+
public function testIsValidWithGrinRuleAndValidToken(mixed $couponCode): void
72+
{
73+
/** @var Rule&MockObject $rule */
74+
$rule = $this->createMock(Rule::class);
75+
/** @var Coupon&MockObject $coupon */
76+
$coupon = $this->createMock(Coupon::class);
77+
78+
$rule->expects($this->once())
79+
->method('getPrimaryCoupon')
80+
->willReturn($coupon);
81+
82+
$coupon->expects($this->once())
83+
->method('getCode')
84+
->willReturn('TEST123');
85+
86+
$rule->expects($this->once())
87+
->method('getData')
88+
->with('is_grin_only')
89+
->willReturn(1);
90+
91+
$this->request->expects($this->once())
92+
->method('getHeader')
93+
->with('Validation-Grin-Token')
94+
->willReturn('valid-token');
95+
96+
$this->systemConfig->expects($this->once())
97+
->method('getSalesRuleToken')
98+
->willReturn('valid-token');
99+
100+
$this->assertTrue($this->salesRuleValidator->isValid($rule, $couponCode));
101+
}
102+
103+
/**
104+
* @dataProvider couponCodeProvider
105+
*/
106+
public function testIsValidWithGrinRuleAndInvalidToken(mixed $couponCode): void
107+
{
108+
/** @var Rule&MockObject $rule */
109+
$rule = $this->createMock(Rule::class);
110+
/** @var Coupon&MockObject $coupon */
111+
$coupon = $this->createMock(Coupon::class);
112+
113+
$rule->expects($this->once())
114+
->method('getPrimaryCoupon')
115+
->willReturn($coupon);
116+
117+
$coupon->expects($this->once())
118+
->method('getCode')
119+
->willReturn('TEST123');
120+
121+
$rule->expects($this->once())
122+
->method('getData')
123+
->with('is_grin_only')
124+
->willReturn(1);
125+
126+
$this->request->expects($this->once())
127+
->method('getHeader')
128+
->with('Validation-Grin-Token')
129+
->willReturn('invalid-token');
130+
131+
$this->systemConfig->expects($this->once())
132+
->method('getSalesRuleToken')
133+
->willReturn('valid-token');
134+
135+
$this->assertFalse($this->salesRuleValidator->isValid($rule, $couponCode));
136+
}
137+
138+
/**
139+
* @dataProvider emptyCouponCodeProvider
140+
*/
141+
public function testIsValidWithEmptyCouponCode(mixed $couponCode): void
142+
{
143+
/** @var Rule&MockObject $rule */
144+
$rule = $this->createMock(Rule::class);
145+
/** @var Coupon&MockObject $coupon */
146+
$coupon = $this->createMock(Coupon::class);
147+
148+
$rule->expects($this->once())
149+
->method('getPrimaryCoupon')
150+
->willReturn($coupon);
151+
152+
$coupon->expects($this->once())
153+
->method('getCode')
154+
->willReturn('TEST123');
155+
156+
$rule->expects($this->once())
157+
->method('getData')
158+
->with('is_grin_only')
159+
->willReturn(1);
160+
161+
$this->assertTrue($this->salesRuleValidator->isValid($rule, $couponCode));
162+
}
163+
164+
/**
165+
* @return array<string, array<mixed>>
166+
*/
167+
public static function couponCodeProvider(): array
168+
{
169+
return [
170+
'string coupon code' => ['TEST123'],
171+
'array coupon code' => [['TEST123', 'TEST456']],
172+
];
173+
}
174+
175+
/**
176+
* @return array<string, array<mixed>>
177+
*/
178+
public static function emptyCouponCodeProvider(): array
179+
{
180+
return [
181+
'empty array' => [[]],
182+
'null' => [null],
183+
];
184+
}
185+
}

Test/Unit/Plugin/Magento/SalesRule/Model/RulesApplier/ValidateByTokenTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function testAroundApplyRules(mixed $couponCode): void
5151

5252
$this->salesRuleValidator->expects($this->once())
5353
->method('isValid')
54-
->with($rule, is_array($couponCode) ? $couponCode : [$couponCode])
54+
->with($rule, $couponCode)
5555
->willReturn(true);
5656

5757
$result = $this->validateByToken->aroundApplyRules(
@@ -98,7 +98,7 @@ public function testAroundApplyRulesWithInvalidRule(mixed $couponCode): void
9898

9999
$this->salesRuleValidator->expects($this->once())
100100
->method('isValid')
101-
->with($rule, is_array($couponCode) ? $couponCode : [$couponCode])
101+
->with($rule, $couponCode)
102102
->willReturn(false);
103103

104104
$result = $this->validateByToken->aroundApplyRules(

0 commit comments

Comments
 (0)