4 * Class CRM_Utils_RuleTest
7 class CRM_Utils_RuleTest
extends CiviUnitTestCase
{
10 * @dataProvider integerDataProvider
12 * @param $expectedResult
14 public function testInteger($inputData, $expectedResult): void
{
15 $this->assertEquals($expectedResult, CRM_Utils_Rule
::integer($inputData));
21 public function integerDataProvider() {
33 * @dataProvider positiveDataProvider
35 * @param $expectedResult
37 public function testPositive($inputData, $expectedResult): void
{
38 $this->assertEquals($expectedResult, CRM_Utils_Rule
::positiveInteger($inputData));
44 public function positiveDataProvider() {
56 * @dataProvider numericDataProvider
58 * @param $expectedResult
60 public function testNumeric($inputData, $expectedResult): void
{
61 $this->assertEquals($expectedResult, CRM_Utils_Rule
::numeric($inputData));
67 public function numericDataProvider() {
79 * @dataProvider booleanDataProvider
81 * @param $expectedResult
83 public function testBoolean($inputData, $expectedResult): void
{
84 $this->assertEquals($expectedResult, CRM_Utils_Rule
::boolean($inputData));
90 public function booleanDataProvider() {
101 * @dataProvider moneyDataProvider
103 * @param $decimalPoint
104 * @param $thousandSeparator
106 * @param $expectedResult
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));
118 public function moneyDataProvider() {
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],
184 * @dataProvider colorDataProvider
186 * @param $expectedResult
188 public function testColor($inputData, $expectedResult): void
{
189 $this->assertEquals($expectedResult, CRM_Utils_Rule
::color($inputData));
195 public function colorDataProvider() {
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],
209 ['rgb(255, 255, 255)', FALSE],
216 public function extenionKeyTests() {
218 $keys[] = ['org.civicrm.multisite', TRUE];
219 $keys[] = ['au.org.contribute2016', TRUE];
220 $keys[] = ['%3Csvg%20onload=alert(0)%3E', FALSE];
226 * @param $expectedResult
227 * @dataProvider extenionKeyTests
229 public function testExtenionKeyValid($key, $expectedResult): void
{
230 $this->assertEquals($expectedResult, CRM_Utils_Rule
::checkExtensionKeyIsValid($key));
236 public function alphanumericData() {
255 "<script>alert('XSS');</script>",
261 foreach ($expectTrue as $value) {
262 $data[] = [$value, TRUE];
264 foreach ($expectFalse as $value) {
265 $data[] = [$value, FALSE];
271 * @dataProvider alphanumericData
275 public function testAlphanumeric($value, $expected): void
{
276 $this->assertEquals($expected, CRM_Utils_Rule
::alphanumeric($value));
283 public static function creditCards(): array {
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'];
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
304 public function testCreditCardValidation($number, $type): void
{
305 $this->assertTrue(CRM_Utils_Rule
::creditCardNumber($number, $type));
313 public static function cvvs(): array {
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];
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
343 public function testCvvRule($cvv, $type, $expected): void
{
344 $this->assertEquals($expected, CRM_Utils_Rule
::cvv($cvv, $type));
350 * @param string $email
351 * @param bool $expected expected outcome of the rule validation
353 * @dataProvider emails
355 public function testEmailRule(string $email, bool $expected): void
{
356 $this->assertEquals($expected, CRM_Utils_Rule
::email($email));
364 public static function emails(): array {
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];