Merge pull request #21657 from totten/master-wfvn
[civicrm-core.git] / tests / phpunit / CRM / Utils / RuleTest.php
1 <?php
2
3 /**
4 * Class CRM_Utils_RuleTest
5 * @group headless
6 */
7 class CRM_Utils_RuleTest extends CiviUnitTestCase {
8
9 /**
10 * @dataProvider integerDataProvider
11 * @param $inputData
12 * @param $expectedResult
13 */
14 public function testInteger($inputData, $expectedResult): void {
15 $this->assertEquals($expectedResult, CRM_Utils_Rule::integer($inputData));
16 }
17
18 /**
19 * @return array
20 */
21 public function integerDataProvider() {
22 return [
23 [10, TRUE],
24 ['145E+3', FALSE],
25 ['10', TRUE],
26 [-10, TRUE],
27 ['-10', TRUE],
28 ['-10foo', FALSE],
29 ];
30 }
31
32 /**
33 * @dataProvider positiveDataProvider
34 * @param $inputData
35 * @param $expectedResult
36 */
37 public function testPositive($inputData, $expectedResult): void {
38 $this->assertEquals($expectedResult, CRM_Utils_Rule::positiveInteger($inputData));
39 }
40
41 /**
42 * @return array
43 */
44 public function positiveDataProvider() {
45 return [
46 [10, TRUE],
47 ['145.0E+3', FALSE],
48 ['10', TRUE],
49 [-10, FALSE],
50 ['-10', FALSE],
51 ['-10foo', FALSE],
52 ];
53 }
54
55 /**
56 * @dataProvider numericDataProvider
57 * @param $inputData
58 * @param $expectedResult
59 */
60 public function testNumeric($inputData, $expectedResult): void {
61 $this->assertEquals($expectedResult, CRM_Utils_Rule::numeric($inputData));
62 }
63
64 /**
65 * @return array
66 */
67 public function numericDataProvider() {
68 return [
69 [10, TRUE],
70 ['145.0E+3', FALSE],
71 ['10', TRUE],
72 [-10, TRUE],
73 ['-10', TRUE],
74 ['-10foo', FALSE],
75 ];
76 }
77
78 /**
79 * @dataProvider booleanDataProvider
80 * @param $inputData
81 * @param $expectedResult
82 */
83 public function testBoolean($inputData, $expectedResult): void {
84 $this->assertEquals($expectedResult, CRM_Utils_Rule::boolean($inputData));
85 }
86
87 /**
88 * @return array
89 */
90 public function booleanDataProvider() {
91 return [
92 [TRUE, TRUE],
93 ['TRUE', TRUE],
94 [FALSE, TRUE],
95 ['false', TRUE],
96 ['banana', FALSE],
97 ];
98 }
99
100 /**
101 * @dataProvider moneyDataProvider
102 * @param $inputData
103 * @param $decimalPoint
104 * @param $thousandSeparator
105 * @param $currency
106 * @param $expectedResult
107 */
108 public function testMoney($inputData, $decimalPoint, $thousandSeparator, $currency, $expectedResult): void {
109 $this->setDefaultCurrency($currency);
110 $this->setMonetaryDecimalPoint($decimalPoint);
111 $this->setMonetaryThousandSeparator($thousandSeparator);
112 $this->assertEquals($expectedResult, CRM_Utils_Rule::money($inputData));
113 }
114
115 /**
116 * @return array
117 */
118 public function moneyDataProvider() {
119 return [
120 [10, '.', ',', 'USD', TRUE],
121 ['145.0E+3', '.', ',', 'USD', FALSE],
122 ['10', '.', ',', 'USD', TRUE],
123 [-10, '.', ',', 'USD', TRUE],
124 ['-10', '.', ',', 'USD', TRUE],
125 ['-10foo', '.', ',', 'USD', FALSE],
126 ['-10.0345619', '.', ',', 'USD', TRUE],
127 ['-10.010,4345619', '.', ',', 'USD', TRUE],
128 ['10.0104345619', '.', ',', 'USD', TRUE],
129 ['-0', '.', ',', 'USD', TRUE],
130 ['-.1', '.', ',', 'USD', TRUE],
131 ['.1', '.', ',', 'USD', TRUE],
132 // Test currency symbols too, default locale uses $, so if we wanted to test others we'd need to reconfigure locale
133 ['$1,234,567.89', '.', ',', 'USD', TRUE],
134 ['-$1,234,567.89', '.', ',', 'USD', TRUE],
135 ['$-1,234,567.89', '.', ',', 'USD', TRUE],
136 // This is the float format. Encapsulated in strings
137 ['1234567.89', '.', ',', 'USD', TRUE],
138 // This is the float format.
139 [1234567.89, '.', ',', 'USD', TRUE],
140 // Test EURO currency
141 ['€1,234,567.89', '.', ',', 'EUR', TRUE],
142 ['-€1,234,567.89', '.', ',', 'EUR', TRUE],
143 ['€-1,234,567.89', '.', ',', 'EUR', TRUE],
144 // This is the float format. Encapsulated in strings
145 ['1234567.89', '.', ',', 'EUR', TRUE],
146 // This is the float format.
147 [1234567.89, '.', ',', 'EUR', TRUE],
148 // Test Norwegian KR currency
149 ['kr1,234,567.89', '.', ',', 'NOK', TRUE],
150 ['kr 1,234,567.89', '.', ',', 'NOK', TRUE],
151 ['-kr1,234,567.89', '.', ',', 'NOK', TRUE],
152 ['-kr 1,234,567.89', '.', ',', 'NOK', TRUE],
153 ['kr-1,234,567.89', '.', ',', 'NOK', TRUE],
154 ['kr -1,234,567.89', '.', ',', 'NOK', TRUE],
155 // This is the float format. Encapsulated in strings
156 ['1234567.89', '.', ',', 'NOK', TRUE],
157 // This is the float format.
158 [1234567.89, '.', ',', 'NOK', TRUE],
159 // Test different localization options: , as decimal separator and dot as thousand separator
160 ['$1.234.567,89', ',', '.', 'USD', TRUE],
161 ['-$1.234.567,89', ',', '.', 'USD', TRUE],
162 ['$-1.234.567,89', ',', '.', 'USD', TRUE],
163 ['1.234.567,89', ',', '.', 'USD', TRUE],
164 // This is the float format. Encapsulated in strings
165 ['1234567.89', ',', '.', 'USD', TRUE],
166 // This is the float format.
167 [1234567.89, ',', '.', 'USD', TRUE],
168 ['$1,234,567.89', ',', '.', 'USD', FALSE],
169 ['-$1,234,567.89', ',', '.', 'USD', FALSE],
170 ['$-1,234,567.89', ',', '.', 'USD', FALSE],
171 // Now with a space as thousand separator
172 ['$1 234 567,89', ',', ' ', 'USD', TRUE],
173 ['-$1 234 567,89', ',', ' ', 'USD', TRUE],
174 ['$-1 234 567,89', ',', ' ', 'USD', TRUE],
175 ['1 234 567,89', ',', ' ', 'USD', TRUE],
176 // This is the float format. Encapsulated in strings
177 ['1234567.89', ',', ' ', 'USD', TRUE],
178 // This is the float format.
179 [1234567.89, ',', ' ', 'USD', TRUE],
180 ];
181 }
182
183 /**
184 * @dataProvider colorDataProvider
185 * @param $inputData
186 * @param $expectedResult
187 */
188 public function testColor($inputData, $expectedResult): void {
189 $this->assertEquals($expectedResult, CRM_Utils_Rule::color($inputData));
190 }
191
192 /**
193 * @return array
194 */
195 public function colorDataProvider() {
196 return [
197 ['#000000', TRUE],
198 ['#ffffff', TRUE],
199 ['#123456', TRUE],
200 ['#00aaff', TRUE],
201 // Some of these are valid css colors but we reject anything that doesn't conform to the html5 spec for <input type="color">
202 ['#ffffff00', FALSE],
203 ['#fff', FALSE],
204 ['##000000', FALSE],
205 ['ffffff', FALSE],
206 ['red', FALSE],
207 ['#orange', FALSE],
208 ['', FALSE],
209 ['rgb(255, 255, 255)', FALSE],
210 ];
211 }
212
213 /**
214 * @return array
215 */
216 public function extenionKeyTests() {
217 $keys = [];
218 $keys[] = ['org.civicrm.multisite', TRUE];
219 $keys[] = ['au.org.contribute2016', TRUE];
220 $keys[] = ['%3Csvg%20onload=alert(0)%3E', FALSE];
221 return $keys;
222 }
223
224 /**
225 * @param $key
226 * @param $expectedResult
227 * @dataProvider extenionKeyTests
228 */
229 public function testExtenionKeyValid($key, $expectedResult): void {
230 $this->assertEquals($expectedResult, CRM_Utils_Rule::checkExtensionKeyIsValid($key));
231 }
232
233 /**
234 * @return array
235 */
236 public function alphanumericData() {
237 $expectTrue = [
238 0,
239 999,
240 -5,
241 '',
242 'foo',
243 '0',
244 '-',
245 '_foo',
246 'one-two',
247 'f00',
248 ];
249 $expectFalse = [
250 ' ',
251 5.7,
252 'one two',
253 'one.two',
254 'A<B',
255 "<script>alert('XSS');</script>",
256 '(foo)',
257 'foo;',
258 '[foo]',
259 ];
260 $data = [];
261 foreach ($expectTrue as $value) {
262 $data[] = [$value, TRUE];
263 }
264 foreach ($expectFalse as $value) {
265 $data[] = [$value, FALSE];
266 }
267 return $data;
268 }
269
270 /**
271 * @dataProvider alphanumericData
272 * @param $value
273 * @param $expected
274 */
275 public function testAlphanumeric($value, $expected): void {
276 $this->assertEquals($expected, CRM_Utils_Rule::alphanumeric($value));
277 }
278
279 /**
280 * Test Credit Cards
281 * @return array
282 */
283 public static function creditCards(): array {
284 $cases = [];
285 $cases[] = ['4111 1111 1111 1111', 'VISA'];
286 $cases[] = ['4111-1111-1111-1111', 'VISA'];
287 $cases[] = ['4111111111111111', 'VISA'];
288 $cases[] = ['5500 0000 0000 0004', 'MasterCard'];
289 $cases[] = ['2223000048400011', 'MasterCard'];
290 $cases[] = ['3400 0000 0000 009', 'AMEX'];
291 $cases[] = ['3088 0000 0000 0009', 'JCB'];
292 $cases[] = ['2014 0000 0000 009', 'ENROUTE'];
293 $cases[] = ['6011 0000 0000 0004', 'DISCOVER'];
294 $cases[] = ['3000 0000 0000 04', 'DINERSCLUB'];
295 return $cases;
296 }
297
298 /**
299 * Test Credit Card Validation
300 * @param string $number CreditCard number for testing
301 * @param string $type CreditCard type to match against.
302 * @dataProvider creditCards
303 */
304 public function testCreditCardValidation($number, $type): void {
305 $this->assertTrue(CRM_Utils_Rule::creditCardNumber($number, $type));
306 }
307
308 /**
309 * Test cvvs.
310 *
311 * @return array
312 */
313 public static function cvvs(): array {
314 $cases = [];
315 $cases[] = ['1', 'visa', FALSE];
316 $cases[] = ['23', 'visa', FALSE];
317 $cases[] = ['111', 'visa', TRUE];
318 $cases[] = ['123', 'visa', TRUE];
319 $cases[] = ['13', 'visa', FALSE];
320 $cases[] = ['1234', 'visa', FALSE];
321 $cases[] = ['897', 'mastercard', TRUE];
322 $cases[] = ['123', 'jcb', FALSE];
323 $cases[] = ['8765', 'jcb', FALSE];
324 $cases[] = ['8765', '', FALSE];
325 $cases[] = ['1234', 'amex', TRUE];
326 $cases[] = ['465', 'amex', FALSE];
327 $cases[] = ['10O7', 'amex', FALSE];
328 $cases[] = ['abc', 'visa', FALSE];
329 $cases[] = ['123.0', 'visa', FALSE];
330 $cases[] = ['1.2', 'visa', FALSE];
331 $cases[] = ['123', 'discover', TRUE];
332 $cases[] = ['4429', 'discover', FALSE];
333 return $cases;
334 }
335
336 /**
337 * Test CVV rule
338 * @param string $cvv cvv for testing
339 * @param string $type card type for testing
340 * @param bool $expected expected outcome of the rule validation
341 * @dataProvider cvvs
342 */
343 public function testCvvRule($cvv, $type, $expected): void {
344 $this->assertEquals($expected, CRM_Utils_Rule::cvv($cvv, $type));
345 }
346
347 /**
348 * Test CVV rule
349 *
350 * @param string $email
351 * @param bool $expected expected outcome of the rule validation
352 *
353 * @dataProvider emails
354 */
355 public function testEmailRule(string $email, bool $expected): void {
356 $this->assertEquals($expected, CRM_Utils_Rule::email($email));
357 }
358
359 /**
360 * Test emails.
361 *
362 * @return array
363 */
364 public static function emails(): array {
365 $cases = [];
366 $cases['name.-o-.i.10@example.com'] = ['name.-o-.i.10@example.com', TRUE];
367 $cases['test@ēxāmplē.co.nz'] = ['test@ēxāmplē.co.nz', TRUE];
368 $cases['test@localhost'] = ['test@localhost', TRUE];
369 $cases['test@ēxāmplē.co'] = ['test@exāmple', FALSE];
370 return $cases;
371 }
372
373 }