Test - fix contributionTest to validate contributions
[civicrm-core.git] / tests / phpunit / api / v3 / OptionValueTest.php
CommitLineData
6a488035 1<?php
972322c5 2/*
3 +--------------------------------------------------------------------+
7d61e75f
TO
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
e70a7fc0 10 */
6a488035 11
e9479dcf
EM
12/**
13 * Class api_v3_OptionValueTest
acb109b7 14 * @group headless
e9479dcf 15 */
6a488035 16class api_v3_OptionValueTest extends CiviUnitTestCase {
972322c5 17 protected $_apiversion = 3;
b7c9bc4c 18
5d345864 19 public function setUp(): void {
6a488035 20 parent::setUp();
a73525a7 21 $this->useTransaction(TRUE);
6a488035
TO
22 }
23
972322c5 24 public function testGetCount() {
9099cab3 25 $result = $this->callAPISuccess('option_value', 'getcount', []);
972322c5 26 $this->assertGreaterThan(100, $result);
27 }
28
6a488035 29 public function testGetOptionValueByID() {
9099cab3 30 $result = $this->callAPISuccess('option_value', 'get', ['id' => 1]);
ba4a1892
TM
31 $this->assertEquals(1, $result['count']);
32 $this->assertEquals(1, $result['id']);
6a488035
TO
33 }
34
35 public function testGetOptionValueByValue() {
9099cab3 36 $result = $this->callAPISuccess('option_value', 'get', ['option_group_id' => 1, 'value' => '1']);
ba4a1892
TM
37 $this->assertEquals(1, $result['count']);
38 $this->assertEquals(1, $result['id']);
6a488035
TO
39 }
40
41 /**
eceb18cc 42 * Test limit param.
6a488035 43 */
00be9182 44 public function testGetOptionValueLimit() {
9099cab3 45 $params = [];
972322c5 46 $result = $this->callAPISuccess('option_value', 'get', $params);
47 $this->assertGreaterThan(1, $result['count'], "Check more than one exists In line " . __LINE__);
6a488035 48 $params['options']['limit'] = 1;
972322c5 49 $result = $this->callAPISuccess('option_value', 'get', $params);
50 $this->assertEquals(1, $result['count'], "Check only 1 retrieved " . __LINE__);
6a488035
TO
51 }
52
53 /**
eceb18cc 54 * Test offset param.
6a488035 55 */
00be9182 56 public function testGetOptionValueOffSet() {
6a488035 57
9099cab3 58 $result = $this->callAPISuccess('option_value', 'get', [
6a488035 59 'option_group_id' => 1,
5896d037 60 'value' => '1',
9099cab3
CW
61 ]);
62 $result2 = $this->callAPISuccess('option_value', 'get', [
6a488035 63 'option_group_id' => 1,
5896d037 64 'value' => '1',
9099cab3
CW
65 'options' => ['offset' => 1],
66 ]);
972322c5 67 $this->assertGreaterThan($result2['count'], $result['count']);
6a488035
TO
68 }
69
70 /**
eceb18cc 71 * Test offset param.
6a488035 72 */
00be9182 73 public function testGetSingleValueOptionValueSort() {
5c49fee0 74 $description = "Demonstrates use of Sort param (available in many api functions). Also, getsingle.";
5896d037 75 $subfile = 'SortOption';
9099cab3 76 $result = $this->callAPISuccess('option_value', 'getsingle', [
6c6e6187 77 'option_group_id' => 1,
9099cab3 78 'options' => [
5896d037
TO
79 'sort' => 'label ASC',
80 'limit' => 1,
9099cab3
CW
81 ],
82 ]);
83 $params = [
6c6e6187 84 'option_group_id' => 1,
9099cab3 85 'options' => [
6a488035
TO
86 'sort' => 'label DESC',
87 'limit' => 1,
9099cab3
CW
88 ],
89 ];
972322c5 90 $result2 = $this->callAPIAndDocument('option_value', 'getsingle', $params, __FUNCTION__, __FILE__, $description, $subfile);
6a488035
TO
91 $this->assertGreaterThan($result['label'], $result2['label']);
92 }
93
94 /**
95 * Try to emulate a pagination: fetch the first page of 10 options, then fetch the second page with an offset of 9 (instead of 10) and check the start of the second page is the end of the 1st one.
96 */
00be9182 97 public function testGetValueOptionPagination() {
6a488035 98 $pageSize = 10;
9099cab3
CW
99 $page1 = $this->callAPISuccess('option_value', 'get', ['options' => ['limit' => $pageSize]]);
100 $page2 = $this->callAPISuccess('option_value', 'get', [
101 'options' => [
5896d037
TO
102 'limit' => $pageSize,
103 // if you use it for pagination, option.offset=pageSize*pageNumber
104 'offset' => $pageSize - 1,
9099cab3
CW
105 ],
106 ]);
6a488035
TO
107 $this->assertEquals($pageSize, $page1['count'], "Check only 10 retrieved in the 1st page " . __LINE__);
108 $this->assertEquals($pageSize, $page2['count'], "Check only 10 retrieved in the 2nd page " . __LINE__);
109
110 $last = array_pop($page1['values']);
111 $first = array_shift($page2['values']);
112
113 $this->assertEquals($first, $last, "the first item of the second page should be the last of the 1st page" . __LINE__);
114 }
115
116 public function testGetOptionGroup() {
9099cab3 117 $params = ['option_group_id' => 1];
972322c5 118 $result = $this->callAPIAndDocument('option_value', 'get', $params, __FUNCTION__, __FILE__);
ba4a1892 119 $this->assertGreaterThan(1, $result['count']);
6a488035 120 }
6a488035 121
c490a46a 122 /**
100fef9d 123 * Test that using option_group_name returns more than 1 & less than all
c490a46a 124 */
6a488035 125 public function testGetOptionGroupByName() {
9099cab3
CW
126 $activityTypesParams = ['option_group_name' => 'activity_type', 'option.limit' => 100];
127 $params = ['option.limit' => 100];
972322c5 128 $activityTypes = $this->callAPISuccess('option_value', 'get', $activityTypesParams);
129 $result = $this->callAPISuccess('option_value', 'get', $params);
ba4a1892
TM
130 $this->assertGreaterThan(1, $activityTypes['count']);
131 $this->assertGreaterThan($activityTypes['count'], $result['count']);
6a488035 132 }
c490a46a 133
6a488035 134 public function testGetOptionDoesNotExist() {
9099cab3 135 $result = $this->callAPISuccess('option_value', 'get', ['label' => 'FSIGUBSFGOMUUBSFGMOOUUBSFGMOOBUFSGMOOIIB']);
ba4a1892 136 $this->assertEquals(0, $result['count']);
6a488035 137 }
c490a46a
CW
138
139 /**
fe482240 140 * Check that domain_id is honoured.
c490a46a 141 */
6a488035 142 public function testCreateOptionSpecifyDomain() {
9099cab3 143 $result = $this->callAPISuccess('option_group', 'get', [
6a488035
TO
144 'name' => 'from_email_address',
145 'sequential' => 1,
9099cab3
CW
146 'api.option_value.create' => ['domain_id' => 2, 'name' => 'my@y.com', 'value' => '10'],
147 ]);
972322c5 148
6a488035 149 $optionValueId = $result['values'][0]['api.option_value.create']['id'];
9099cab3 150 $domain_id = $this->callAPISuccess('option_value', 'getvalue', [
6a488035 151 'id' => $optionValueId,
6a488035 152 'return' => 'domain_id',
9099cab3 153 ]);
6a488035 154 $this->assertEquals(2, $domain_id);
9099cab3 155 $this->callAPISuccess('option_value', 'delete', ['id' => $optionValueId]);
c87bbced 156 }
c490a46a
CW
157
158 /**
fe482240 159 * Check that component_id is honoured.
c490a46a 160 */
c87bbced 161 public function testCreateOptionSpecifyComponentID() {
9099cab3 162 $result = $this->callAPISuccess('option_group', 'get', [
c87bbced 163 'name' => 'from_email_address',
6c6e6187 164 'sequential' => 1,
9099cab3
CW
165 'api.option_value.create' => ['component_id' => 2, 'name' => 'my@y.com'],
166 ]);
c87bbced 167 $this->assertAPISuccess($result);
168 $optionValueId = $result['values'][0]['api.option_value.create']['id'];
9099cab3 169 $component_id = $this->callAPISuccess('option_value', 'getvalue', [
6c6e6187 170 'id' => $optionValueId,
5896d037 171 'return' => 'component_id',
9099cab3 172 ]);
c87bbced 173 $this->assertEquals(2, $component_id);
9099cab3 174 $this->callAPISuccess('option_value', 'delete', ['id' => $optionValueId]);
c87bbced 175 }
c490a46a
CW
176
177 /**
7ba24c5a 178 * Check that component string is honoured.
c490a46a 179 */
7ba24c5a 180 public function testCreateOptionSpecifyComponentString() {
9099cab3 181 $result = $this->callAPISuccess('option_group', 'get', [
c87bbced 182 'name' => 'from_email_address',
6c6e6187 183 'sequential' => 1,
9099cab3 184 'api.option_value.create' => [
c87bbced 185 'component_id' => 'CiviContribute',
21dfd5f5 186 'name' => 'my@y.com',
9099cab3
CW
187 ],
188 ]);
c87bbced 189 $this->assertAPISuccess($result);
190 $optionValueId = $result['values'][0]['api.option_value.create']['id'];
9099cab3 191 $component_id = $this->callAPISuccess('option_value', 'getvalue', [
6c6e6187 192 'id' => $optionValueId,
5896d037 193 'return' => 'component_id',
9099cab3 194 ]);
c87bbced 195 $this->assertEquals(2, $component_id);
9099cab3 196 $this->callAPISuccess('option_value', 'delete', ['id' => $optionValueId]);
c87bbced 197 }
c490a46a
CW
198
199 /**
7ba24c5a 200 * Check that component is honoured when fetching options.
c490a46a 201 */
7ba24c5a 202 public function testGetOptionWithComponent() {
98d41b7d
CW
203 $components = Civi::settings()->get('enable_components');
204 CRM_Core_BAO_ConfigSetting::enableComponent('CiviContribute');
9099cab3 205 $this->callAPISuccess('option_group', 'get', [
7ba24c5a 206 'name' => 'gender',
9099cab3 207 'api.option_value.create' => [
c87bbced 208 'component_id' => 'CiviContribute',
7ba24c5a 209 'name' => 'Contrib',
9099cab3
CW
210 ],
211 ]);
7ba24c5a 212 // Verify new option is present
9099cab3 213 $genders = $this->callAPISuccess('contact', 'getoptions', [
7ba24c5a
CW
214 'field' => 'gender_id',
215 'context' => 'create',
9099cab3 216 ]);
7ba24c5a 217 $this->assertContains('Contrib', $genders['values']);
98d41b7d 218
7ba24c5a
CW
219 // Disable relevant component
220 CRM_Core_BAO_ConfigSetting::disableComponent('CiviContribute');
221 CRM_Core_PseudoConstant::flush();
222 // New option should now be hidden for "create" context
9099cab3 223 $genders = $this->callAPISuccess('contact', 'getoptions', [
7ba24c5a
CW
224 'field' => 'gender_id',
225 'context' => 'create',
9099cab3 226 ]);
7ba24c5a
CW
227 $this->assertNotContains('Contrib', $genders['values']);
228 // New option should be visible for "get" context even with component disabled
9099cab3 229 $genders = $this->callAPISuccess('contact', 'getoptions', [
7ba24c5a
CW
230 'field' => 'gender_id',
231 'context' => 'get',
9099cab3 232 ]);
7ba24c5a 233 $this->assertContains('Contrib', $genders['values']);
98d41b7d
CW
234
235 // Now disable all components and ensure we can still fetch options with no errors
9099cab3 236 CRM_Core_BAO_ConfigSetting::setEnabledComponents([]);
98d41b7d
CW
237 CRM_Core_PseudoConstant::flush();
238 // New option should still be hidden for "create" context
9099cab3 239 $genders = $this->callAPISuccess('contact', 'getoptions', [
98d41b7d
CW
240 'field' => 'gender_id',
241 'context' => 'create',
9099cab3 242 ]);
98d41b7d
CW
243 $this->assertNotContains('Contrib', $genders['values']);
244
245 // Restore original state
246 CRM_Core_BAO_ConfigSetting::setEnabledComponents($components);
c87bbced 247 }
c490a46a
CW
248
249 /**
fe482240 250 * Check that domain_id is honoured.
c490a46a 251 */
c87bbced 252 public function testCRM12133CreateOptionWeightNoValue() {
972322c5 253 $optionGroup = $this->callAPISuccess(
9099cab3 254 'option_group', 'get', [
5896d037
TO
255 'name' => 'gender',
256 'sequential' => 1,
9099cab3 257 ]
e70a7fc0 258 );
c87bbced 259 $this->assertAPISuccess($optionGroup);
9099cab3 260 $params = [
c87bbced 261 'option_group_id' => $optionGroup['id'],
6c6e6187 262 'label' => 'my@y.com',
5896d037 263 'weight' => 3,
9099cab3 264 ];
6c6e6187 265 $optionValue = $this->callAPISuccess('option_value', 'create', $params);
c87bbced 266 $this->assertAPISuccess($optionValue);
267 $params['weight'] = 4;
5896d037 268 $optionValue2 = $this->callAPISuccess('option_value', 'create', $params);
c87bbced 269 $this->assertAPISuccess($optionValue2);
9099cab3 270 $options = $this->callAPISuccess('option_value', 'get', ['option_group_id' => $optionGroup['id']]);
c87bbced 271 $this->assertNotEquals($options['values'][$optionValue['id']]['value'], $options['values'][$optionValue2['id']]['value']);
272
6c6e6187 273 //cleanup
9099cab3
CW
274 $this->callAPISuccess('option_value', 'delete', ['id' => $optionValue['id']]);
275 $this->callAPISuccess('option_value', 'delete', ['id' => $optionValue2['id']]);
6a488035
TO
276 }
277
c490a46a 278 /**
fe482240 279 * Check that domain_id is honoured.
c490a46a 280 */
6a488035 281 public function testCreateOptionNoName() {
9099cab3 282 $optionGroup = $this->callAPISuccess('option_group', 'get', [
6a488035 283 'name' => 'gender',
5896d037 284 'sequential' => 1,
9099cab3 285 ]);
6a488035 286
9099cab3 287 $params = ['option_group_id' => $optionGroup['id'], 'label' => 'my@y.com'];
6c6e6187 288 $optionValue = $this->callAPISuccess('option_value', 'create', $params);
6a488035
TO
289 $this->assertAPISuccess($optionValue);
290 $this->getAndCheck($params, $optionValue['id'], 'option_value');
291 }
a4a33486
CW
292
293 /**
fe482240 294 * Check that pseudoconstant reflects new value added.
a4a33486 295 */
6a488035 296 public function testCRM11876CreateOptionPseudoConstantUpdated() {
9099cab3 297 $optionGroupID = $this->callAPISuccess('option_group', 'getvalue', [
5896d037 298 'name' => 'payment_instrument',
a4a33486 299 'return' => 'id',
9099cab3 300 ]);
a4a33486 301 $newOption = (string) time();
9099cab3 302 $apiResult = $this->callAPISuccess('option_value', 'create', [
a4a33486
CW
303 'option_group_id' => $optionGroupID,
304 'label' => $newOption,
9099cab3 305 ]);
6a488035 306
9099cab3 307 $fields = $this->callAPISuccess('contribution', 'getoptions', ['field' => 'payment_instrument_id']);
a4a33486
CW
308 $this->assertTrue(in_array($newOption, $fields['values']));
309
9099cab3 310 $this->callAPISuccess('option_value', 'delete', ['id' => $apiResult['id']]);
a4a33486 311
9099cab3 312 $fields = $this->callAPISuccess('contribution', 'getoptions', ['field' => 'payment_instrument_id']);
a4a33486 313 $this->assertFalse(in_array($newOption, $fields['values']));
6a488035 314 }
6a488035 315
c490a46a 316 /**
e4f46be0 317 * Update option value with 'id' parameter and the value to update
89ab5601
PJ
318 * and not passing option group id
319 */
320 public function testUpdateOptionValueNoGroupId() {
321 // create a option group
9099cab3 322 $og = $this->callAPISuccess('option_group', 'create', ['name' => 'our test Option Group', 'is_active' => 1]);
89ab5601
PJ
323 // create a option value
324 $ov = $this->callAPISuccess('option_value', 'create',
9099cab3 325 ['option_group_id' => $og['id'], 'label' => 'test option value']
89ab5601
PJ
326 );
327 // update option value without 'option_group_id'
9099cab3
CW
328 $res = $this->callAPISuccess('option_value', 'create', ['id' => $ov['id'], 'is_active' => 0]);
329 $val = $this->callAPISuccess('option_value', 'getvalue', [
6c6e6187 330 'id' => $ov['id'],
5896d037 331 'return' => 'is_active',
9099cab3 332 ]);
89ab5601
PJ
333 $this->assertEquals($val, 0, "update with no group id is not proper" . __LINE__);
334 }
335
c490a46a 336 /**
e4f46be0 337 * Update option value with 'id' parameter and the value to update
89ab5601
PJ
338 * and as well as option group id
339 */
340 public function testUpdateOptionValueWithGroupId() {
341 // create a option group
9099cab3 342 $og = $this->callAPISuccess('option_group', 'create', [
92915c55
TO
343 'name' => 'our test Option Group for with group id',
344 'is_active' => 1,
9099cab3 345 ]);
89ab5601
PJ
346 // create a option value
347 $ov = $this->callAPISuccess('option_value', 'create',
9099cab3 348 ['option_group_id' => $og['id'], 'label' => 'test option value']
89ab5601
PJ
349 );
350 // update option value without 'option_group_id'
9099cab3 351 $this->callAPISuccess('option_value', 'create', [
92915c55
TO
352 'id' => $ov['id'],
353 'option_group_id' => $og['id'],
354 'is_active' => 0,
9099cab3
CW
355 ]);
356 $val = $this->callAPISuccess('option_value', 'getvalue', [
6c6e6187 357 'id' => $ov['id'],
5896d037 358 'return' => 'is_active',
9099cab3 359 ]);
89ab5601
PJ
360 $this->assertEquals($val, 0, "update with group id is not proper " . __LINE__);
361 }
96025800 362
e5720c45 363 /**
d0488daf 364 * CRM-19346 Ensure that Option Values cannot share same value in the same option value group
e5720c45
SL
365 */
366 public function testCreateOptionValueWithSameValue() {
9099cab3 367 $og = $this->callAPISuccess('option_group', 'create', [
e5720c45
SL
368 'name' => 'our test Option Group for with group id',
369 'is_active' => 1,
9099cab3 370 ]);
e5720c45
SL
371 // create a option value
372 $ov = $this->callAPISuccess('option_value', 'create',
9099cab3 373 ['option_group_id' => $og['id'], 'label' => 'test option value']
e5720c45
SL
374 );
375 // update option value without 'option_group_id'
d0488daf 376 $this->callAPIFailure('option_value', 'create',
9099cab3 377 ['option_group_id' => $og['id'], 'label' => 'Test 2nd option value', 'value' => $ov['values'][$ov['id']]['value']]
e5720c45
SL
378 );
379 }
380
d0488daf 381 /**
382 * CRM-21737 Ensure that language Option Values CAN share same value.
383 */
384 public function testCreateOptionValueWithSameValueLanguagesException() {
385 $this->callAPISuccess('option_value', 'create',
386 ['option_group_id' => 'languages', 'label' => 'Quasi English', 'name' => 'en_Qu', 'value' => 'en']
387 );
388 $this->callAPISuccess('option_value', 'create',
389 ['option_group_id' => 'languages', 'label' => 'Semi English', 'name' => 'en_Se', 'value' => 'en']
390 );
391
392 }
393
e5720c45 394 public function testCreateOptionValueWithSameValueDiffOptionGroup() {
9099cab3 395 $og = $this->callAPISuccess('option_group', 'create', [
6ebc7a89 396 'name' => 'our test Option Group',
e5720c45 397 'is_active' => 1,
9099cab3 398 ]);
e5720c45
SL
399 // create a option value
400 $ov = $this->callAPISuccess('option_value', 'create',
9099cab3 401 ['option_group_id' => $og['id'], 'label' => 'test option value']
e5720c45 402 );
9099cab3 403 $og2 = $this->callAPISuccess('option_group', 'create', [
6ebc7a89 404 'name' => 'our test Option Group 2',
e5720c45 405 'is_active' => 1,
9099cab3 406 ]);
e5720c45
SL
407 // update option value without 'option_group_id'
408 $ov2 = $this->callAPISuccess('option_value', 'create',
9099cab3 409 ['option_group_id' => $og2['id'], 'label' => 'Test 2nd option value', 'value' => $ov['values'][$ov['id']]['value']]
e5720c45
SL
410 );
411 }
412
2ef8ea5a
PN
413 /**
414 * Test to create and update payment method with financial account.
415 */
416 public function testCreateUpdateOptionValueForPaymentInstrument() {
417 $assetFinancialAccountId = $this->callAPISuccessGetValue('FinancialAccount', [
418 'return' => "id",
419 'financial_account_type_id' => "Asset",
420 'options' => ['limit' => 1],
421 ]);
422 // create new payment method with financial account
423 $ov = $this->callAPISuccess('OptionValue', 'create', [
424 'financial_account_id' => $assetFinancialAccountId,
425 'option_group_id' => "payment_instrument",
426 'label' => "Dummy Payment Method",
427 ]);
428
429 //check if relationship is created between Payment method and Financial Account
430 $this->checkPaymentMethodFinancialAccountRelationship($ov['id'], $assetFinancialAccountId);
431
432 // update payment method to have different non-asset financial Account
433 $nonAssetFinancialAccountId = $this->callAPISuccessGetValue('FinancialAccount', [
434 'return' => "id",
435 'financial_account_type_id' => ['NOT IN' => ["Asset"]],
436 'options' => ['limit' => 1],
437 ]);
438 try {
439 $result = $this->callAPISuccess('OptionValue', 'create', [
440 'financial_account_id' => $nonAssetFinancialAccountId,
441 'id' => $ov['id'],
442 ]);
443 throw new API_Exception(ts('Should throw error.'));
444 }
445 catch (Exception $e) {
446 try {
447 $assetAccountRelValue = $this->callAPISuccessGetValue('EntityFinancialAccount', [
448 'return' => "account_relationship",
449 'entity_table' => "civicrm_option_value",
450 'entity_id' => $ov['id'],
451 'financial_account_id' => $nonAssetFinancialAccountId,
452 ]);
453 throw new API_Exception(ts('Should throw error.'));
454 }
455 catch (Exception $e) {
456 $this->checkPaymentMethodFinancialAccountRelationship($ov['id'], $assetFinancialAccountId);
457 }
458 }
459 // update payment method to have different asset financial Account
460 $assetFinancialAccountId = $this->callAPISuccessGetValue('FinancialAccount', [
461 'return' => "id",
462 'financial_account_type_id' => "Asset",
463 'options' => ['limit' => 1],
464 'id' => ['NOT IN' => [$assetFinancialAccountId]],
465 ]);
466 $result = $this->callAPISuccess('OptionValue', 'create', [
467 'financial_account_id' => $assetFinancialAccountId,
468 'id' => $ov['id'],
469 ]);
470 //check if relationship is updated between Payment method and Financial Account
471 $this->checkPaymentMethodFinancialAccountRelationship($ov['id'], $assetFinancialAccountId);
472 }
473
474 /**
475 * Function to check relationship between FA and Payment method.
476 *
477 * @param int $paymentMethodId
478 * @param int $financialAccountId
479 */
480 protected function checkPaymentMethodFinancialAccountRelationship($paymentMethodId, $financialAccountId) {
481 $assetAccountRelValue = $this->callAPISuccessGetValue('EntityFinancialAccount', [
482 'return' => "account_relationship",
483 'entity_table' => "civicrm_option_value",
484 'entity_id' => $paymentMethodId,
485 'financial_account_id' => $financialAccountId,
486 ]);
487 $checkAssetAccountIs = $this->callAPISuccessGetValue('OptionValue', [
488 'return' => "id",
489 'option_group_id' => "account_relationship",
490 'name' => "Asset Account is",
491 'value' => $assetAccountRelValue,
492 ]);
493 }
494
e9479dcf 495}