Skip to content

Commit f035811

Browse files
committed
Add phone tests
isValidPhone test phone handling in request data phone exceptions
1 parent f04420f commit f035811

File tree

4 files changed

+638
-13
lines changed

4 files changed

+638
-13
lines changed

tests/Integration/API/Mocks/MockedApi.php

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@
44

55
namespace Mollie\WooCommerceTests\Integration\API\Mocks;
66

7+
use Mollie\Api\Endpoints\ChargebackEndpoint;
8+
use Mollie\Api\Endpoints\CustomerEndpoint;
9+
use Mollie\Api\Endpoints\InvoiceEndpoint;
10+
use Mollie\Api\Endpoints\MandateEndpoint;
11+
use Mollie\Api\Endpoints\MethodEndpoint;
12+
use Mollie\Api\Endpoints\OrderEndpoint;
13+
use Mollie\Api\Endpoints\OrganizationEndpoint;
14+
use Mollie\Api\Endpoints\PaymentEndpoint;
15+
use Mollie\Api\Endpoints\PermissionEndpoint;
16+
use Mollie\Api\Endpoints\ProfileEndpoint;
17+
use Mollie\Api\Endpoints\RefundEndpoint;
18+
use Mollie\Api\Endpoints\SettlementsEndpoint;
19+
use Mollie\Api\Endpoints\SubscriptionEndpoint;
720
use Mollie\WooCommerce\SDK\Api;
821
use Mollie\Api\MollieApiClient;
922
use Mockery;
@@ -51,19 +64,19 @@ protected function setupMockedApiClient(): void
5164
{
5265
$this->mockedApiClient = Mockery::mock(MollieApiClient::class);
5366

54-
$this->mockedApiClient->payments = Mockery::mock('PaymentEndpoint');
55-
$this->mockedApiClient->methods = Mockery::mock('MethodEndpoint');
56-
$this->mockedApiClient->customers = Mockery::mock('CustomerEndpoint');
57-
$this->mockedApiClient->orders = Mockery::mock('OrderEndpoint');
58-
$this->mockedApiClient->refunds = Mockery::mock('RefundEndpoint');
59-
$this->mockedApiClient->subscriptions = Mockery::mock('SubscriptionEndpoint');
60-
$this->mockedApiClient->mandates = Mockery::mock('MandateEndpoint');
61-
$this->mockedApiClient->profiles = Mockery::mock('ProfileEndpoint');
62-
$this->mockedApiClient->organizations = Mockery::mock('OrganizationEndpoint');
63-
$this->mockedApiClient->permissions = Mockery::mock('PermissionEndpoint');
64-
$this->mockedApiClient->invoices = Mockery::mock('InvoiceEndpoint');
65-
$this->mockedApiClient->settlements = Mockery::mock('SettlementsEndpoint');
66-
$this->mockedApiClient->chargebacks = Mockery::mock('ChargebackEndpoint');
67+
$this->mockedApiClient->payments = Mockery::mock(PaymentEndpoint::class);
68+
$this->mockedApiClient->methods = Mockery::mock(MethodEndpoint::class);
69+
$this->mockedApiClient->customers = Mockery::mock(CustomerEndpoint::class);
70+
$this->mockedApiClient->orders = Mockery::mock(OrderEndpoint::class);
71+
$this->mockedApiClient->refunds = Mockery::mock(RefundEndpoint::class);
72+
$this->mockedApiClient->subscriptions = Mockery::mock(SubscriptionEndpoint::class);
73+
$this->mockedApiClient->mandates = Mockery::mock(MandateEndpoint::class);
74+
$this->mockedApiClient->profiles = Mockery::mock(ProfileEndpoint::class);
75+
$this->mockedApiClient->organizations = Mockery::mock(OrganizationEndpoint::class);
76+
$this->mockedApiClient->permissions = Mockery::mock(PermissionEndpoint::class);
77+
$this->mockedApiClient->invoices = Mockery::mock(InvoiceEndpoint::class);
78+
$this->mockedApiClient->settlements = Mockery::mock(SettlementsEndpoint::class);
79+
$this->mockedApiClient->chargebacks = Mockery::mock(ChargebackEndpoint::class);
6780
}
6881

6982
/**
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Mollie\WooCommerce\Tests\Integration\spec\Gateway;
6+
7+
use Mollie\WooCommerce\Gateway\GatewayModule;
8+
use Mollie\WooCommerceTests\Integration\IntegrationMockedTestCase;
9+
10+
class PaymentMethodPhoneValidationTest extends IntegrationMockedTestCase
11+
{
12+
private GatewayModule $gatewayModule;
13+
private \WP_Error $mockErrors;
14+
15+
public function setUp(): void
16+
{
17+
parent::setUp();
18+
$this->gatewayModule = new GatewayModule();
19+
$this->mockErrors = $this->createMock(\WP_Error::class);
20+
21+
// Clear POST data before each test
22+
$_POST = [];
23+
}
24+
25+
public function tearDown(): void
26+
{
27+
// Clean up POST data after each test
28+
$_POST = [];
29+
parent::tearDown();
30+
}
31+
32+
/**
33+
* Test that validation is skipped when payment method doesn't match
34+
*/
35+
public function test_skips_validation_when_wrong_payment_method()
36+
{
37+
$fields = [
38+
'payment_method' => 'different_gateway',
39+
'billing_phone' => 'invalid_phone'
40+
];
41+
42+
$result = $this->gatewayModule->addPaymentMethodMandatoryFieldsPhoneVerification(
43+
$fields,
44+
'mollie_wc_gateway_in3',
45+
'billing_phone_in3',
46+
'Phone',
47+
$this->mockErrors
48+
);
49+
50+
// Should return unchanged when payment method doesn't match
51+
$this->assertEquals($fields, $result);
52+
$this->assertEquals('invalid_phone', $result['billing_phone']);
53+
}
54+
55+
/**
56+
* Phone validation regex explanation:
57+
*
58+
* The regex `/^\+[1-9]\d{10,13}$|^[1-9]\d{9,13}$|^06\d{9,13}$/` validates three phone number formats:
59+
*
60+
* 1. International format: `^\+[1-9]\d{10,13}$`
61+
* - Must start with '+' followed by a digit 1-9 (no leading zeros after country code)
62+
* - Followed by 10-13 additional digits
63+
* - Total length: 12-15 characters (including the '+')
64+
* - Examples: +31612345678, +1234567890123
65+
*
66+
* 2. National format: `^[1-9]\d{9,13}$`
67+
* - Must start with a digit 1-9 (no leading zeros)
68+
* - Followed by 9-13 additional digits
69+
* - Total length: 10-14 digits
70+
* - Examples: 1234567890, 12345678901234
71+
*
72+
* 3. Dutch mobile format: `^06\d{9,13}$`
73+
* - Must start with '06' (Dutch mobile prefix)
74+
* - Followed by 9-13 additional digits
75+
* - Total length: 11-15 digits
76+
* - Examples: 06123456789, 061234567890123
77+
*
78+
* Invalid examples:
79+
* - Empty strings, non-numeric characters
80+
* - Numbers starting with 0 (except 06 format)
81+
* - Numbers too short or too long for their format
82+
* - International format starting with +0
83+
*/
84+
public function test_keeps_valid_phone_numbers()
85+
{
86+
$validPhones = [
87+
'+31612345678', // International format
88+
'+49123456789012', // International (longer)
89+
'+1234567890123', // International (max length)
90+
'612345678901', // National format
91+
'12345678901234', // National format Max length 14
92+
'06123456789', // 06 format (min)
93+
'061234567890123' // 06 format (max)
94+
];
95+
96+
foreach ($validPhones as $phone) {
97+
$fields = [
98+
'payment_method' => 'mollie_wc_gateway_in3',
99+
'billing_phone' => $phone
100+
];
101+
102+
$result = $this->gatewayModule->addPaymentMethodMandatoryFieldsPhoneVerification(
103+
$fields,
104+
'mollie_wc_gateway_in3',
105+
'billing_phone_in3',
106+
'Phone',
107+
$this->mockErrors
108+
);
109+
110+
$this->assertEquals($phone, $result['billing_phone'], "Valid phone should be kept: $phone");
111+
}
112+
}
113+
114+
/**
115+
* Test invalid phone numbers that should be set to null
116+
*/
117+
public function test_nullifies_invalid_phone_numbers()
118+
{
119+
$invalidPhones = [
120+
'+0612345678', // Invalid: 0 after +
121+
'+123456789', // Too short for international
122+
'+123456789012345', // Too long for international
123+
'0123456789', // Invalid: starts with 0 (not 06)
124+
'12345678', // Too short for national
125+
'123456789012345678', // Too long for national
126+
'06123', // Too short for 06 format
127+
'invalid', // Non-numeric
128+
'+abc123456789', // Non-numeric after +
129+
'++31612345678', // Double +
130+
'+31-612345678', // Contains dash
131+
'+31 612345678', // Contains space
132+
];
133+
134+
foreach ($invalidPhones as $phone) {
135+
$fields = [
136+
'payment_method' => 'mollie_wc_gateway_in3',
137+
'billing_phone' => $phone
138+
];
139+
140+
$result = $this->gatewayModule->addPaymentMethodMandatoryFieldsPhoneVerification(
141+
$fields,
142+
'mollie_wc_gateway_in3',
143+
'billing_phone_in3',
144+
'Phone',
145+
$this->mockErrors
146+
);
147+
148+
$this->assertNull($result['billing_phone'], "Invalid phone should be null: $phone");
149+
}
150+
}
151+
152+
/**
153+
* Test edge cases with empty/null phone values
154+
*/
155+
public function test_handles_empty_phone_values()
156+
{
157+
$emptyCases = [
158+
'', // Empty string
159+
null, // Null value
160+
' ', // Whitespace only
161+
];
162+
163+
foreach ($emptyCases as $phone) {
164+
$fields = [
165+
'payment_method' => 'mollie_wc_gateway_in3',
166+
'billing_phone' => $phone
167+
];
168+
169+
$result = $this->gatewayModule->addPaymentMethodMandatoryFieldsPhoneVerification(
170+
$fields,
171+
'mollie_wc_gateway_in3',
172+
'billing_phone_in3',
173+
'Phone',
174+
$this->mockErrors
175+
);
176+
177+
$this->assertNull($result['billing_phone'], "Empty phone should result in null");
178+
}
179+
}
180+
181+
/**
182+
* Test POST field fallback when billing_phone is empty
183+
*/
184+
public function test_post_field_fallback_with_invalid_phone()
185+
{
186+
// Set up POST data
187+
$_POST['billing_phone_in3'] = 'invalid_phone';
188+
189+
$fields = [
190+
'payment_method' => 'mollie_wc_gateway_in3',
191+
'billing_phone' => ''
192+
];
193+
194+
$result = $this->gatewayModule->addPaymentMethodMandatoryFieldsPhoneVerification(
195+
$fields,
196+
'mollie_wc_gateway_in3',
197+
'billing_phone_in3',
198+
'Phone',
199+
$this->mockErrors
200+
);
201+
202+
$this->assertNull($result['billing_phone']);
203+
}
204+
205+
/**
206+
* Test POST field fallback when billing_phone is empty and POST has valid phone
207+
*/
208+
public function test_post_field_fallback_with_valid_phone()
209+
{
210+
// Set up POST data with valid phone
211+
$_POST['billing_phone_in3'] = '+31612345678';
212+
213+
$fields = [
214+
'payment_method' => 'mollie_wc_gateway_in3',
215+
'billing_phone' => ''
216+
];
217+
218+
$result = $this->gatewayModule->addPaymentMethodMandatoryFieldsPhoneVerification(
219+
$fields,
220+
'mollie_wc_gateway_in3',
221+
'billing_phone_in3',
222+
'Phone',
223+
$this->mockErrors
224+
);
225+
226+
$this->assertEquals('+31612345678', $result['billing_phone']);
227+
}
228+
229+
/**
230+
* Test no POST field available
231+
*/
232+
public function test_no_post_field_available()
233+
{
234+
// No POST data set
235+
$fields = [
236+
'payment_method' => 'mollie_wc_gateway_in3',
237+
'billing_phone' => ''
238+
];
239+
240+
$result = $this->gatewayModule->addPaymentMethodMandatoryFieldsPhoneVerification(
241+
$fields,
242+
'mollie_wc_gateway_in3',
243+
'billing_phone_in3',
244+
'Phone',
245+
$this->mockErrors
246+
);
247+
248+
$this->assertNull($result['billing_phone']);
249+
}
250+
251+
/**
252+
* Test method works with different gateway names
253+
*/
254+
public function test_works_with_different_gateways()
255+
{
256+
$gateways = [
257+
'mollie_wc_gateway_in3',
258+
'mollie_wc_gateway_riverty',
259+
'mollie_wc_gateway_other'
260+
];
261+
262+
foreach ($gateways as $gateway) {
263+
$fields = [
264+
'payment_method' => $gateway,
265+
'billing_phone' => '+31612345678'
266+
];
267+
268+
$result = $this->gatewayModule->addPaymentMethodMandatoryFieldsPhoneVerification(
269+
$fields,
270+
$gateway,
271+
'billing_phone_' . str_replace('mollie_wc_gateway_', '', $gateway),
272+
'Phone',
273+
$this->mockErrors
274+
);
275+
276+
$this->assertEquals('+31612345678', $result['billing_phone'], "Should work with gateway: $gateway");
277+
}
278+
}
279+
}

0 commit comments

Comments
 (0)