4 * File for the TestContact class.
8 * @author Walt Haas <walt@dharmatech.org> (801) 534-1262
9 * @copyright Copyright CiviCRM LLC (C) 2009
10 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html
11 * GNU Affero General Public License version 3
12 * @version $Id: ContactTest.php 31254 2010-12-15 10:09:29Z eileen $
15 * This file is part of CiviCRM
17 * CiviCRM is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Affero General Public License
19 * as published by the Free Software Foundation; either version 3 of
20 * the License, or (at your option) any later version.
22 * CiviCRM is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU Affero General Public License for more details.
27 * You should have received a copy of the GNU Affero General Public
28 * License along with this program. If not, see
29 * <http://www.gnu.org/licenses/>.
33 * Include class definitions
35 require_once 'CiviTest/CiviUnitTestCase.php';
39 * Test APIv3 civicrm_contact* functions
41 * @package CiviCRM_APIv3
42 * @subpackage API_Contact
44 class api_v3_ContactTest
extends CiviUnitTestCase
{
45 public $DBResetRequired = FALSE;
46 protected $_apiversion;
50 protected $_contactID;
51 protected $_financialTypeId = 1;
54 * Test setup for every test.
56 * Connect to the database, truncate the tables that will be used
57 * and redirect stdin to a temporary file
59 public function setUp() {
60 // Connect to the database.
62 $this->_apiversion
= 3;
63 $this->_entity
= 'contact';
64 $this->_params
= array(
65 'first_name' => 'abc1',
66 'contact_type' => 'Individual',
67 'last_name' => 'xyz1',
71 public function tearDown() {
72 // truncate a few tables
73 $tablesToTruncate = array(
76 'civicrm_contribution',
79 'civicrm_relationship',
84 $this->quickCleanup($tablesToTruncate, TRUE);
88 * Test civicrm_contact_create.
90 * Verify that attempt to create individual contact with only
91 * first and last names succeeds
93 public function testAddCreateIndividual() {
94 $oldCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
96 'first_name' => 'abc1',
97 'contact_type' => 'Individual',
98 'last_name' => 'xyz1',
101 $contact = $this->callAPISuccess('contact', 'create', $params);
102 $this->assertTrue(is_numeric($contact['id']));
103 $this->assertTrue($contact['id'] > 0);
104 $newCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
105 $this->assertEquals($oldCount +
1, $newCount);
107 $this->assertDBState('CRM_Contact_DAO_Contact',
114 * Test civicrm_contact_create with sub-types.
116 * Verify that sub-types are created successfully and not deleted by subsequent updates.
118 public function testIndividualSubType() {
120 'first_name' => 'test abc',
121 'contact_type' => 'Individual',
122 'last_name' => 'test xyz',
123 'contact_sub_type' => array('Student', 'Staff'),
125 $contact = $this->callAPISuccess('contact', 'create', $params);
126 $cid = $contact['id'];
130 'middle_name' => 'foo',
132 $this->callAPISuccess('contact', 'create', $params);
133 unset($params['middle_name']);
135 $contact = $this->callAPISuccess('contact', 'get', $params);
137 $this->assertEquals(array('Student', 'Staff'), $contact['values'][$cid]['contact_sub_type']);
141 * Verify that attempt to create contact with empty params fails.
143 public function testCreateEmptyContact() {
144 $this->callAPIFailure('contact', 'create', array());
148 * Verify that attempt to create contact with bad contact type fails.
150 public function testCreateBadTypeContact() {
152 'email' => 'man1@yahoo.com',
153 'contact_type' => 'Does not Exist',
155 $this->callAPIFailure('contact', 'create', $params, "'Does not Exist' is not a valid option for field contact_type");
159 * Verify that attempt to create individual contact without required fields fails.
161 public function testCreateBadRequiredFieldsIndividual() {
163 'middle_name' => 'This field is not required',
164 'contact_type' => 'Individual',
166 $this->callAPIFailure('contact', 'create', $params);
170 * Verify that attempt to create household contact without required fields fails.
172 public function testCreateBadRequiredFieldsHousehold() {
174 'middle_name' => 'This field is not required',
175 'contact_type' => 'Household',
177 $this->callAPIFailure('contact', 'create', $params);
181 * Test required field check.
183 * Verify that attempt to create organization contact without required fields fails.
185 public function testCreateBadRequiredFieldsOrganization() {
187 'middle_name' => 'This field is not required',
188 'contact_type' => 'Organization',
191 $this->callAPIFailure('contact', 'create', $params);
195 * Verify that attempt to create individual contact with only an email succeeds.
197 public function testCreateEmailIndividual() {
200 'email' => 'man3@yahoo.com',
201 'contact_type' => 'Individual',
202 'location_type_id' => 1,
205 $contact = $this->callAPISuccess('contact', 'create', $params);
207 $this->assertEquals(1, $contact['id']);
208 $email = $this->callAPISuccess('email', 'get', array('contact_id' => $contact['id']));
209 $this->assertEquals(1, $email['count']);
210 $this->assertEquals('man3@yahoo.com', $email['values'][$email['id']]['email']);
212 $this->callAPISuccess('contact', 'delete', $contact);
216 * Test creating individual by name.
218 * Verify create individual contact with only first and last names succeeds.
220 public function testCreateNameIndividual() {
222 'first_name' => 'abc1',
223 'contact_type' => 'Individual',
224 'last_name' => 'xyz1',
227 $contact = $this->callAPISuccess('contact', 'create', $params);
228 $this->assertEquals(1, $contact['id']);
232 * Test old keys still work.
234 * Verify that attempt to create individual contact with
235 * first and last names and old key values works
237 public function testCreateNameIndividualOldKeys() {
239 'individual_prefix' => 'Dr.',
240 'first_name' => 'abc1',
241 'contact_type' => 'Individual',
242 'last_name' => 'xyz1',
243 'individual_suffix' => 'Jr.',
246 $contact = $this->callAPISuccess('contact', 'create', $params);
247 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
249 $this->assertArrayKeyExists('prefix_id', $result);
250 $this->assertArrayKeyExists('suffix_id', $result);
251 $this->assertArrayKeyExists('gender_id', $result);
252 $this->assertEquals(4, $result['prefix_id']);
253 $this->assertEquals(1, $result['suffix_id']);
257 * Test preferred keys work.
259 * Verify that attempt to create individual contact with
260 * first and last names and old key values works
262 public function testCreateNameIndividualRecommendedKeys2() {
264 'prefix_id' => 'Dr.',
265 'first_name' => 'abc1',
266 'contact_type' => 'Individual',
267 'last_name' => 'xyz1',
268 'suffix_id' => 'Jr.',
269 'gender_id' => 'Male',
272 $contact = $this->callAPISuccess('contact', 'create', $params);
273 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
275 $this->assertArrayKeyExists('prefix_id', $result);
276 $this->assertArrayKeyExists('suffix_id', $result);
277 $this->assertArrayKeyExists('gender_id', $result);
278 $this->assertEquals(4, $result['prefix_id']);
279 $this->assertEquals(1, $result['suffix_id']);
283 * Test household name is sufficient for create.
285 * Verify that attempt to create household contact with only
286 * household name succeeds
288 public function testCreateNameHousehold() {
290 'household_name' => 'The abc Household',
291 'contact_type' => 'Household',
293 $contact = $this->callAPISuccess('contact', 'create', $params);
294 $this->assertEquals(1, $contact['id']);
298 * Test organization name is sufficient for create.
300 * Verify that attempt to create organization contact with only
301 * organization name succeeds.
303 public function testCreateNameOrganization() {
305 'organization_name' => 'The abc Organization',
306 'contact_type' => 'Organization',
308 $contact = $this->callAPISuccess('contact', 'create', $params);
309 $this->assertEquals(1, $contact['id']);
313 * Verify that attempt to create organization contact without organization name fails.
315 public function testCreateNoNameOrganization() {
317 'first_name' => 'The abc Organization',
318 'contact_type' => 'Organization',
320 $this->callAPIFailure('contact', 'create', $params);
324 * Check with complete array + custom field.
326 * Note that the test is written on purpose without any
327 * variables specific to participant so it can be replicated into other entities
328 * and / or moved to the automated test suite
330 public function testCreateWithCustom() {
331 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
333 $params = $this->_params
;
334 $params['custom_' . $ids['custom_field_id']] = "custom string";
335 $description = "This demonstrates setting a custom field through the API.";
336 $result = $this->callAPIAndDocument($this->_entity
, 'create', $params, __FUNCTION__
, __FILE__
, $description);
338 $check = $this->callAPISuccess($this->_entity
, 'get', array(
339 'return.custom_' . $ids['custom_field_id'] => 1,
340 'id' => $result['id'],
342 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
344 $this->customFieldDelete($ids['custom_field_id']);
345 $this->customGroupDelete($ids['custom_group_id']);
349 * CRM-12773 - expectation is that civicrm quietly ignores fields without values.
351 public function testCreateWithNULLCustomCRM12773() {
352 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
353 $params = $this->_params
;
354 $params['custom_' . $ids['custom_field_id']] = NULL;
355 $this->callAPISuccess('contact', 'create', $params);
356 $this->customFieldDelete($ids['custom_field_id']);
357 $this->customGroupDelete($ids['custom_group_id']);
361 * CRM-15792 - create/update datetime field for contact.
363 public function testCreateContactCustomFldDateTime() {
364 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'datetime_test_group'));
365 $dateTime = CRM_Utils_Date
::currentDBDate();
366 //check date custom field is saved along with time when time_format is set
368 'first_name' => 'abc3',
369 'last_name' => 'xyz3',
370 'contact_type' => 'Individual',
371 'email' => 'man3@yahoo.com',
372 'api.CustomField.create' => array(
373 'custom_group_id' => $customGroup['id'],
374 'name' => 'test_datetime',
375 'label' => 'Demo Date',
376 'html_type' => 'Select Date',
377 'data_type' => 'Date',
381 'is_searchable' => 0,
386 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
);
387 $customFldId = $result['values'][$result['id']]['api.CustomField.create']['id'];
388 $this->assertNotNull($result['id'], 'in line ' . __LINE__
);
389 $this->assertNotNull($customFldId, 'in line ' . __LINE__
);
392 'id' => $result['id'],
393 "custom_{$customFldId}" => $dateTime,
394 'api.CustomValue.get' => 1,
397 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
);
398 $this->assertNotNull($result['id'], 'in line ' . __LINE__
);
399 $customFldDate = date("YmdHis", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
400 $this->assertNotNull($customFldDate, 'in line ' . __LINE__
);
401 $this->assertEquals($dateTime, $customFldDate);
402 $customValueId = $result['values'][$result['id']]['api.CustomValue.get']['values'][0]['id'];
403 $dateTime = date('Ymd');
404 //date custom field should not contain time part when time_format is null
406 'id' => $result['id'],
407 'api.CustomField.create' => array(
408 'id' => $customFldId,
409 'html_type' => 'Select Date',
410 'data_type' => 'Date',
413 'api.CustomValue.create' => array(
414 'id' => $customValueId,
415 'entity_id' => $result['id'],
416 "custom_{$customFldId}" => $dateTime,
418 'api.CustomValue.get' => 1,
420 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
);
421 $this->assertNotNull($result['id'], 'in line ' . __LINE__
);
422 $customFldDate = date("Ymd", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
423 $customFldTime = date("His", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
424 $this->assertNotNull($customFldDate, 'in line ' . __LINE__
);
425 $this->assertEquals($dateTime, $customFldDate);
426 $this->assertEquals(000000, $customFldTime);
427 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
);
432 * Test creating a current employer through API.
434 public function testContactCreateCurrentEmployer() {
435 // Here we will just do the get for set-up purposes.
436 $count = $this->callAPISuccess('contact', 'getcount', array(
437 'organization_name' => 'new employer org',
438 'contact_type' => 'Organization',
440 $this->assertEquals(0, $count);
441 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
442 'current_employer' => 'new employer org',
445 // do it again as an update to check it doesn't cause an error
446 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
447 'current_employer' => 'new employer org',
448 'id' => $employerResult['id'],
452 $this->callAPISuccess('contact', 'getcount', array(
453 'organization_name' => 'new employer org',
454 'contact_type' => 'Organization',
458 $result = $this->callAPISuccess('contact', 'getsingle', array(
459 'id' => $employerResult['id'],
462 $this->assertEquals('new employer org', $result['current_employer']);
467 * Test creating a current employer through API.
469 * Check it will re-activate a de-activated employer
471 public function testContactCreateDuplicateCurrentEmployerEnables() {
472 // Set up - create employer relationship.
473 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
474 'current_employer' => 'new employer org',
477 $relationship = $this->callAPISuccess('relationship', 'get', array(
478 'contact_id_a' => $employerResult['id'],
481 //disable & check it is disabled
482 $this->callAPISuccess('relationship', 'create', array('id' => $relationship['id'], 'is_active' => 0));
483 $this->callAPISuccess('relationship', 'getvalue', array(
484 'id' => $relationship['id'],
485 'return' => 'is_active',
488 // Re-set the current employer - thus enabling the relationship.
489 $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
490 'current_employer' => 'new employer org',
491 'id' => $employerResult['id'],
494 //check is_active is now 1
495 $relationship = $this->callAPISuccess('relationship', 'getsingle', array(
496 'return' => 'is_active',
498 $this->assertEquals(1, $relationship['is_active']);
502 * Check deceased contacts are not retrieved.
504 * Note at time of writing the default is to return default. This should possibly be changed & test added.
506 public function testGetDeceasedRetrieved() {
507 $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
508 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
509 'first_name' => 'bb',
510 'last_name' => 'ccc',
511 'contact_type' => 'Individual',
514 $result = $this->callAPISuccess($this->_entity
, 'get', array('is_deceased' => 0));
515 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
519 * Test that sort works - old syntax.
521 public function testGetSort() {
522 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
523 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
524 'first_name' => 'bb',
525 'last_name' => 'ccc',
526 'contact_type' => 'Individual',
528 $result = $this->callAPISuccess($this->_entity
, 'get', array(
529 'sort' => 'first_name ASC',
530 'return.first_name' => 1,
535 $this->assertEquals('abc1', $result['values'][0]['first_name']);
536 $result = $this->callAPISuccess($this->_entity
, 'get', array(
537 'sort' => 'first_name DESC',
538 'return.first_name' => 1,
542 $this->assertEquals('bb', $result['values'][0]['first_name']);
544 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
545 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
549 * Test that we can retrieve contacts using array syntax.
551 * I.e 'id' => array('IN' => array('3,4')).
553 public function testGetINIDArray() {
554 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
555 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
556 'first_name' => 'bb',
557 'last_name' => 'ccc',
558 'contact_type' => 'Individual',
560 $c3 = $this->callAPISuccess($this->_entity
, 'create', array(
561 'first_name' => 'hh',
563 'contact_type' => 'Individual',
565 $result = $this->callAPISuccess($this->_entity
, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
566 $this->assertEquals(2, $result['count']);
567 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
568 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
569 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
570 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c3['id']));
574 * Test variants on deleted behaviour.
576 public function testGetDeleted() {
577 $params = $this->_params
;
578 $contact1 = $this->callAPISuccess('contact', 'create', $params);
579 $params['is_deleted'] = 1;
580 $params['last_name'] = 'bcd';
581 $contact2 = $this->callAPISuccess('contact', 'create', $params);
582 $countActive = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'active'));
583 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all'));
584 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash'));
585 $countDefault = $this->callAPISuccess('contact', 'getcount', array());
586 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
587 'contact_is_deleted' => 1,
589 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
590 'contact_is_deleted' => 0,
592 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
593 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
594 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected in line ' . __LINE__
);
595 $this->assertEquals(1, $countActive);
596 $this->assertEquals(1, $countTrash);
597 $this->assertEquals(2, $countAll);
598 $this->assertEquals(1, $countDeleted);
599 $this->assertEquals(1, $countDefault, 'Only active by default in line ' . __LINE__
);
603 * Test that sort works - new syntax.
605 public function testGetSortNewSyntax() {
606 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
607 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
608 'first_name' => 'bb',
609 'last_name' => 'ccc',
610 'contact_type' => 'Individual',
612 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
613 'return' => 'first_name',
616 'sort' => 'first_name',
619 $this->assertEquals('abc1', $result, 'in line' . __LINE__
);
621 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
622 'return' => 'first_name',
625 'sort' => 'first_name DESC',
628 $this->assertEquals('bb', $result);
630 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
631 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
635 * Test apostrophe works in get & create.
637 public function testGetApostropheCRM10857() {
638 $params = array_merge($this->_params
, array('last_name' => "O'Connor"));
639 $this->callAPISuccess($this->_entity
, 'create', $params);
640 $result = $this->callAPISuccess($this->_entity
, 'getsingle', array(
641 'last_name' => "O'Connor",
644 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__
);
648 * Check with complete array + custom field.
650 * Note that the test is written on purpose without any
651 * variables specific to participant so it can be replicated into other entities
652 * and / or moved to the automated test suite
654 public function testGetWithCustom() {
655 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
657 $params = $this->_params
;
658 $params['custom_' . $ids['custom_field_id']] = "custom string";
659 $description = "This demonstrates setting a custom field through the API.";
660 $subfile = "CustomFieldGet";
661 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
663 $check = $this->callAPIAndDocument($this->_entity
, 'get', array(
664 'return.custom_' . $ids['custom_field_id'] => 1,
665 'id' => $result['id'],
666 ), __FUNCTION__
, __FILE__
, $description, $subfile);
668 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
669 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
670 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
671 $this->customFieldDelete($ids['custom_field_id']);
672 $this->customGroupDelete($ids['custom_group_id']);
676 * Check with complete array + custom field.
678 * Note that the test is written on purpose without any
679 * variables specific to participant so it can be replicated into other entities
680 * and / or moved to the automated test suite
682 public function testGetWithCustomReturnSyntax() {
683 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
685 $params = $this->_params
;
686 $params['custom_' . $ids['custom_field_id']] = "custom string";
687 $description = "This demonstrates setting a custom field through the API.";
688 $subfile = "CustomFieldGetReturnSyntaxVariation";
689 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
690 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
691 $check = $this->callAPIAndDocument($this->_entity
, 'get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
693 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
694 $this->customFieldDelete($ids['custom_field_id']);
695 $this->customGroupDelete($ids['custom_group_id']);
699 * Check that address name is returned if required.
701 public function testGetReturnAddressName() {
702 $contactID = $this->individualCreate();
703 $this->callAPISuccess('address', 'create', array(
704 'contact_id' => $contactID,
705 'address_name' => 'My house',
706 'location_type_id' => 'Home',
707 'street_address' => '1 my road',
709 $result = $this->callAPISuccessGetSingle('contact', array(
710 'return' => 'address_name, street_address',
713 $this->assertEquals('1 my road', $result['street_address']);
714 $this->assertEquals('My house', $result['address_name']);
718 public function testGetGroupIDFromContact() {
719 $groupId = $this->groupCreate();
720 $description = "Get all from group and display contacts.";
721 $subFile = "GroupFilterUsingContactAPI";
723 'email' => 'man2@yahoo.com',
724 'contact_type' => 'Individual',
725 'location_type_id' => 1,
726 'api.group_contact.create' => array('group_id' => $groupId),
729 $this->callAPISuccess('contact', 'create', $params);
730 // testing as integer
732 'filter.group_id' => $groupId,
733 'contact_type' => 'Individual',
735 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
736 $this->assertEquals(1, $result['count']);
737 // group 26 doesn't exist, but we can still search contacts in it.
739 'filter.group_id' => 26,
740 'contact_type' => 'Individual',
742 $this->callAPISuccess('contact', 'get', $params);
745 'filter.group_id' => "$groupId, 26",
746 'contact_type' => 'Individual',
748 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
749 $this->assertEquals(1, $result['count']);
751 'filter.group_id' => "26,27",
752 'contact_type' => 'Individual',
754 $this->callAPISuccess('contact', 'get', $params);
758 'filter.group_id' => array($groupId, 26),
759 'contact_type' => 'Individual',
761 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
762 $this->assertEquals(1, $result['count']);
764 //test in conjunction with other criteria
766 'filter.group_id' => array($groupId, 26),
767 'contact_type' => 'Organization',
769 $this->callAPISuccess('contact', 'get', $params);
771 'filter.group_id' => array(26, 27),
772 'contact_type' => 'Individual',
774 $result = $this->callAPISuccess('contact', 'get', $params);
775 $this->assertEquals(0, $result['count']);
779 * Verify that attempt to create individual contact with two chained websites succeeds.
781 public function testCreateIndividualWithContributionDottedSyntax() {
782 $description = "This demonstrates the syntax to create 2 chained entities.";
783 $subFile = "ChainTwoWebsites";
785 'first_name' => 'abc3',
786 'last_name' => 'xyz3',
787 'contact_type' => 'Individual',
788 'email' => 'man3@yahoo.com',
789 'api.contribution.create' => array(
790 'receive_date' => '2010-01-01',
791 'total_amount' => 100.00,
792 'financial_type_id' => $this->_financialTypeId
,
793 'payment_instrument_id' => 1,
794 'non_deductible_amount' => 10.00,
795 'fee_amount' => 50.00,
796 'net_amount' => 90.00,
798 'invoice_id' => 67990,
800 'contribution_status_id' => 1,
802 'api.website.create' => array(
803 'url' => "http://civicrm.org",
805 'api.website.create.2' => array(
806 'url' => "http://chained.org",
810 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
812 $this->assertEquals(1, $result['id']);
813 // checking child function result not covered in callAPIAndDocument
814 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
815 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url']);
816 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url']);
818 // delete the contact
819 $this->callAPISuccess('contact', 'delete', $result);
823 * Verify that attempt to create individual contact with chained contribution and website succeeds.
825 public function testCreateIndividualWithContributionChainedArrays() {
827 'first_name' => 'abc3',
828 'last_name' => 'xyz3',
829 'contact_type' => 'Individual',
830 'email' => 'man3@yahoo.com',
831 'api.contribution.create' => array(
832 'receive_date' => '2010-01-01',
833 'total_amount' => 100.00,
834 'financial_type_id' => $this->_financialTypeId
,
835 'payment_instrument_id' => 1,
836 'non_deductible_amount' => 10.00,
837 'fee_amount' => 50.00,
838 'net_amount' => 90.00,
840 'invoice_id' => 67890,
842 'contribution_status_id' => 1,
844 'api.website.create' => array(
846 'url' => "http://civicrm.org",
849 'url' => "http://chained.org",
850 'website_type_id' => 2,
855 $description = "Demonstrates creating two websites as an array.";
856 $subfile = "ChainTwoWebsitesSyntax2";
857 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
859 $this->assertEquals(1, $result['id']);
860 // the callAndDocument doesn't check the chained call
861 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error']);
862 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url']);
863 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url']);
865 $this->callAPISuccess('contact', 'delete', $result);
869 * Verify that attempt to create individual contact with first, and last names and email succeeds.
871 public function testCreateIndividualWithNameEmail() {
873 'first_name' => 'abc3',
874 'last_name' => 'xyz3',
875 'contact_type' => 'Individual',
876 'email' => 'man3@yahoo.com',
879 $contact = $this->callAPISuccess('contact', 'create', $params);
880 $this->assertEquals(1, $contact['id']);
882 $this->callAPISuccess('contact', 'delete', $contact);
886 * Verify that attempt to create individual contact with no data fails.
888 public function testCreateIndividualWithOutNameEmail() {
890 'contact_type' => 'Individual',
892 $this->callAPIFailure('contact', 'create', $params);
896 * Test create individual contact with first &last names, email and location type succeeds.
898 public function testCreateIndividualWithNameEmailLocationType() {
900 'first_name' => 'abc4',
901 'last_name' => 'xyz4',
902 'email' => 'man4@yahoo.com',
903 'contact_type' => 'Individual',
904 'location_type_id' => 1,
906 $result = $this->callAPISuccess('contact', 'create', $params);
908 $this->assertEquals(1, $result['id']);
910 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
914 * Verify that when changing employers the old employer relationship becomes inactive.
916 public function testCreateIndividualWithEmployer() {
917 $employer = $this->organizationCreate();
918 $employer2 = $this->organizationCreate();
921 'email' => 'man4@yahoo.com',
922 'contact_type' => 'Individual',
923 'employer_id' => $employer,
926 $result = $this->callAPISuccess('contact', 'create', $params);
927 $relationships = $this->callAPISuccess('relationship', 'get', array(
928 'contact_id_a' => $result['id'],
932 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
934 // Add more random relationships to make the test more realistic
935 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
936 $relTypeId = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
937 $this->callAPISuccess('relationship', 'create', array(
938 'contact_id_a' => $result['id'],
939 'contact_id_b' => $this->organizationCreate(),
941 'relationship_type_id' => $relTypeId,
945 // Add second employer
946 $params['employer_id'] = $employer2;
947 $params['id'] = $result['id'];
948 $result = $this->callAPISuccess('contact', 'create', $params);
950 $relationships = $this->callAPISuccess('relationship', 'get', array(
951 'contact_id_a' => $result['id'],
956 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
960 * Verify that attempt to create household contact with details succeeds.
962 public function testCreateHouseholdDetails() {
964 'household_name' => 'abc8\'s House',
965 'nick_name' => 'x House',
966 'email' => 'man8@yahoo.com',
967 'contact_type' => 'Household',
970 $contact = $this->callAPISuccess('contact', 'create', $params);
972 $this->assertEquals(1, $contact['id']);
974 $this->callAPISuccess('contact', 'delete', $contact);
978 * Verify that attempt to create household contact with inadequate details fails.
980 public function testCreateHouseholdInadequateDetails() {
982 'nick_name' => 'x House',
983 'email' => 'man8@yahoo.com',
984 'contact_type' => 'Household',
986 $this->callAPIFailure('contact', 'create', $params);
990 * Verify successful update of individual contact.
992 public function testUpdateIndividualWithAll() {
993 // Insert a row in civicrm_contact creating individual contact.
994 $op = new PHPUnit_Extensions_Database_Operation_Insert();
995 $op->execute($this->_dbconn
,
996 $this->createXMLDataSet(
997 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1003 'first_name' => 'abcd',
1004 'contact_type' => 'Individual',
1005 'nick_name' => 'This is nickname first',
1006 'do_not_email' => '1',
1007 'do_not_phone' => '1',
1008 'do_not_mail' => '1',
1009 'do_not_trade' => '1',
1010 'legal_identifier' => 'ABC23853ZZ2235',
1011 'external_identifier' => '1928837465',
1012 'image_URL' => 'http://some.url.com/image.jpg',
1013 'home_url' => 'http://www.example.org',
1017 $this->callAPISuccess('Contact', 'Update', $params);
1018 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
1019 unset($params['contact_id']);
1020 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
1021 //reducing this test partially back to api v2 level to get it through
1022 unset($params['home_url']);
1023 foreach ($params as $key => $value) {
1024 $this->assertEquals($value, $getResult['values'][23][$key]);
1026 // Check updated civicrm_contact against expected.
1027 $expected = $this->createXMLDataSet(
1028 dirname(__FILE__
) . '/dataset/contact_ind_upd.xml'
1030 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1033 $actual->addTable('civicrm_contact');
1034 $expected->matches($actual);
1038 * Verify successful update of organization contact.
1040 public function testUpdateOrganizationWithAll() {
1041 // Insert a row in civicrm_contact creating organization contact
1042 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1043 $op->execute($this->_dbconn
,
1044 $this->createXMLDataSet(
1045 dirname(__FILE__
) . '/dataset/contact_org.xml'
1051 'organization_name' => 'WebAccess India Pvt Ltd',
1052 'legal_name' => 'WebAccess',
1053 'sic_code' => 'ABC12DEF',
1054 'contact_type' => 'Organization',
1057 $this->callAPISuccess('Contact', 'Update', $params);
1059 // Check updated civicrm_contact against expected.
1060 $expected = $this->createXMLDataSet(
1061 dirname(__FILE__
) . '/dataset/contact_org_upd.xml'
1063 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1066 $actual->addTable('civicrm_contact');
1067 $expected->matches($actual);
1071 * Verify successful update of household contact.
1073 public function testUpdateHouseholdWithAll() {
1074 // Insert a row in civicrm_contact creating household contact
1075 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1076 $op->execute($this->_dbconn
,
1077 $this->createXMLDataSet(
1078 dirname(__FILE__
) . '/dataset/contact_hld.xml'
1084 'household_name' => 'ABC household',
1085 'nick_name' => 'ABC House',
1086 'contact_type' => 'Household',
1089 $result = $this->callAPISuccess('Contact', 'Update', $params);
1092 'contact_type' => 'Household',
1094 'sort_name' => 'ABC household',
1095 'display_name' => 'ABC household',
1096 'nick_name' => 'ABC House',
1098 $this->getAndCheck($expected, $result['id'], 'contact');
1102 * Test civicrm_update() without contact type.
1104 * Deliberately exclude contact_type as it should still cope using civicrm_api.
1108 public function testUpdateCreateWithID() {
1109 // Insert a row in civicrm_contact creating individual contact.
1110 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1111 $op->execute($this->_dbconn
,
1112 $this->createXMLDataSet(
1113 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1119 'first_name' => 'abcd',
1120 'last_name' => 'wxyz',
1122 $this->callAPISuccess('Contact', 'Update', $params);
1126 * Test civicrm_contact_delete() with no contact ID.
1128 public function testContactDeleteNoID() {
1132 $this->callAPIFailure('contact', 'delete', $params);
1136 * Test civicrm_contact_delete() with error.
1138 public function testContactDeleteError() {
1139 $params = array('contact_id' => 999);
1140 $this->callAPIFailure('contact', 'delete', $params);
1144 * Test civicrm_contact_delete().
1146 public function testContactDelete() {
1147 $contactID = $this->individualCreate();
1151 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__
, __FILE__
);
1155 * Test civicrm_contact_get() return only first name.
1157 public function testContactGetRetFirst() {
1158 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1160 'contact_id' => $contact['id'],
1161 'return_first_name' => TRUE,
1162 'sort' => 'first_name',
1164 $result = $this->callAPISuccess('contact', 'get', $params);
1165 $this->assertEquals(1, $result['count']);
1166 $this->assertEquals($contact['id'], $result['id']);
1167 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1171 * Test civicrm_contact_get() return only first name & last name.
1173 * Use comma separated string return with a space.
1175 public function testContactGetReturnFirstLast() {
1176 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1178 'contact_id' => $contact['id'],
1179 'return' => 'first_name, last_name',
1181 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1182 $this->assertEquals('abc1', $result['first_name']);
1183 $this->assertEquals('xyz1', $result['last_name']);
1184 //check that other defaults not returns
1185 $this->assertArrayNotHasKey('sort_name', $result);
1187 'contact_id' => $contact['id'],
1188 'return' => 'first_name,last_name',
1190 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1191 $this->assertEquals('abc1', $result['first_name']);
1192 $this->assertEquals('xyz1', $result['last_name']);
1193 //check that other defaults not returns
1194 $this->assertArrayNotHasKey('sort_name', $result);
1198 * Test civicrm_contact_get() return only first name & last name.
1200 * Use comma separated string return without a space
1202 public function testContactGetReturnFirstLastNoComma() {
1203 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1205 'contact_id' => $contact['id'],
1206 'return' => 'first_name,last_name',
1208 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1209 $this->assertEquals('abc1', $result['first_name']);
1210 $this->assertEquals('xyz1', $result['last_name']);
1211 //check that other defaults not returns
1212 $this->assertArrayNotHasKey('sort_name', $result);
1216 * Test civicrm_contact_get() with default return properties.
1218 public function testContactGetRetDefault() {
1219 $contactID = $this->individualCreate();
1221 'contact_id' => $contactID,
1222 'sort' => 'first_name',
1224 $result = $this->callAPISuccess('contact', 'get', $params);
1225 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1226 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1230 * Test civicrm_contact_getquick() with empty name param.
1232 public function testContactGetQuick() {
1233 // Insert a row in civicrm_contact creating individual contact.
1234 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1235 $op->execute($this->_dbconn
,
1236 $this->createXMLDataSet(
1237 dirname(__FILE__
) . '/dataset/contact_17.xml'
1240 $op->execute($this->_dbconn
,
1241 $this->createXMLDataSet(
1242 dirname(__FILE__
) . '/dataset/email_contact_17.xml'
1249 $result = $this->callAPISuccess('contact', 'getquick', $params);
1250 $this->assertEquals(17, $result['values'][0]['id']);
1254 * Test civicrm_contact_get) with empty params.
1256 public function testContactGetEmptyParams() {
1257 $this->callAPISuccess('contact', 'get', array());
1261 * Test civicrm_contact_get(,true) with no matches.
1263 public function testContactGetOldParamsNoMatches() {
1264 // Insert a row in civicrm_contact creating contact 17.
1265 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1266 $op->execute($this->_dbconn
,
1267 $this->createXMLDataSet(
1268 dirname(__FILE__
) . '/dataset/contact_17.xml'
1273 'first_name' => 'Fred',
1275 $result = $this->callAPISuccess('contact', 'get', $params);
1276 $this->assertEquals(0, $result['count']);
1280 * Test civicrm_contact_get(,true) with one match.
1282 public function testContactGetOldParamsOneMatch() {
1283 // Insert a row in civicrm_contact creating contact 17
1284 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1285 $op->execute($this->_dbconn
,
1286 $this->createXMLDataSet(dirname(__FILE__
) . '/dataset/contact_17.xml'
1291 'first_name' => 'Test',
1293 $result = $this->callAPISuccess('contact', 'get', $params);
1294 $this->assertEquals(17, $result['values'][17]['contact_id']);
1295 $this->assertEquals(17, $result['id']);
1299 * Test civicrm_contact_search_count().
1301 public function testContactGetEmail() {
1303 'email' => 'man2@yahoo.com',
1304 'contact_type' => 'Individual',
1305 'location_type_id' => 1,
1308 $contact = $this->callAPISuccess('contact', 'create', $params);
1310 $this->assertEquals(1, $contact['id']);
1313 'email' => 'man2@yahoo.com',
1315 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
);
1316 $this->assertEquals(1, $result['values'][1]['contact_id']);
1317 $this->assertEquals('man2@yahoo.com', $result['values'][1]['email']);
1319 // delete the contact
1320 $this->callAPISuccess('contact', 'delete', $contact);
1324 * Test birth date parameters.
1326 * These include value, array & birth_date_high, birth_date_low
1329 public function testContactGetBirthDate() {
1330 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 2 years')));
1331 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 5 years')));
1332 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month -20 years')));
1334 $result = $this->callAPISuccess('contact', 'get', array());
1335 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1336 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1337 $this->assertEquals(1, $result['count']);
1338 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1339 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1340 $this->assertEquals(1, $result['count']);
1341 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1342 $result = $this->callAPISuccess('contact', 'get', array(
1343 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
1344 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
1346 $this->assertEquals(1, $result['count']);
1347 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1348 $result = $this->callAPISuccess('contact', 'get', array(
1349 'birth_date_low' => '-6 years',
1350 'birth_date_high' => '- 3 years',
1352 $this->assertEquals(1, $result['count']);
1353 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1357 * Test Deceased date parameters.
1359 * These include value, array & Deceased_date_high, Deceased date_low
1362 public function testContactGetDeceasedDate() {
1363 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 2 years')));
1364 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 5 years')));
1365 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month -20 years')));
1367 $result = $this->callAPISuccess('contact', 'get', array());
1368 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
1369 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
1370 $this->assertEquals(1, $result['count']);
1371 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1372 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
1373 $this->assertEquals(1, $result['count']);
1374 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
1375 $result = $this->callAPISuccess('contact', 'get', array(
1376 'deceased_date_low' => '-6 years',
1377 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
1379 $this->assertEquals(1, $result['count']);
1380 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1384 * Test for Contact.get id=@user:username.
1386 public function testContactGetByUsername() {
1387 // Setup - create contact with a uf-match.
1388 $cid = $this->individualCreate(array(
1389 'contact_type' => 'Individual',
1390 'first_name' => 'testGetByUsername',
1391 'last_name' => 'testGetByUsername',
1394 $ufMatchParams = array(
1395 'domain_id' => CRM_Core_Config
::domainID(),
1397 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
1398 'contact_id' => $cid,
1400 $ufMatch = CRM_Core_BAO_UFMatch
::create($ufMatchParams);
1401 $this->assertTrue(is_numeric($ufMatch->id
));
1403 // setup - mock the calls to CRM_Utils_System_*::getUfId
1404 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1405 $userSystem->expects($this->once())
1407 ->with($this->equalTo('exampleUser'))
1408 ->will($this->returnValue(99));
1409 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1412 $result = $this->callAPISuccess('Contact', 'get', array(
1413 'id' => '@user:exampleUser',
1415 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
1419 * Test to check return works OK.
1421 public function testContactGetReturnValues() {
1422 $extraParams = array('nick_name' => 'Bob', 'phone' => '456', 'email' => 'e@mail.com');
1423 $contactID = $this->individualCreate($extraParams);
1424 //actually it turns out the above doesn't create a phone
1425 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
1426 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
1427 foreach ($extraParams as $key => $value) {
1428 $this->assertEquals($result[$key], $value);
1430 //now we check they are still returned with 'return' key
1431 $result = $this->callAPISuccess('contact', 'getsingle', array(
1433 'return' => array_keys($extraParams),
1435 foreach ($extraParams as $key => $value) {
1436 $this->assertEquals($result[$key], $value);
1440 public function testCRM13252MultipleChainedPhones() {
1441 $contactID = $this->householdCreate();
1442 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
1444 'contact_id' => $contactID,
1445 'household_name' => 'Household 1',
1446 'contact_type' => 'Household',
1447 'api.phone.create' => array(
1449 'phone' => '111-111-1111',
1450 'location_type_id' => 1,
1451 'phone_type_id' => 1,
1454 'phone' => '222-222-2222',
1455 'location_type_id' => 1,
1456 'phone_type_id' => 2,
1460 $this->callAPISuccess('contact', 'create', $params);
1461 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
1466 * Test for Contact.get id=@user:username (with an invalid username).
1468 public function testContactGetByUnknownUsername() {
1469 // setup - mock the calls to CRM_Utils_System_*::getUfId
1470 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1471 $userSystem->expects($this->once())
1473 ->with($this->equalTo('exampleUser'))
1474 ->will($this->returnValue(NULL));
1475 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1478 $result = $this->callAPIFailure('Contact', 'get', array(
1479 'id' => '@user:exampleUser',
1481 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
1485 * Verify attempt to create individual with chained arrays.
1487 public function testGetIndividualWithChainedArrays() {
1488 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1489 $params['custom_' . $ids['custom_field_id']] = "custom string";
1491 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1492 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
1493 $subfile = "APIChainedArray";
1495 'first_name' => 'abc3',
1496 'last_name' => 'xyz3',
1497 'contact_type' => 'Individual',
1498 'email' => 'man3@yahoo.com',
1499 'api.contribution.create' => array(
1500 'receive_date' => '2010-01-01',
1501 'total_amount' => 100.00,
1502 'financial_type_id' => 1,
1503 'payment_instrument_id' => 1,
1504 'non_deductible_amount' => 10.00,
1505 'fee_amount' => 50.00,
1506 'net_amount' => 90.00,
1508 'invoice_id' => 67890,
1510 'contribution_status_id' => 1,
1512 'api.contribution.create.1' => array(
1513 'receive_date' => '2011-01-01',
1514 'total_amount' => 120.00,
1515 'financial_type_id' => $this->_financialTypeId
= 1,
1516 'payment_instrument_id' => 1,
1517 'non_deductible_amount' => 10.00,
1518 'fee_amount' => 50.00,
1519 'net_amount' => 90.00,
1521 'invoice_id' => 67830,
1523 'contribution_status_id' => 1,
1525 'api.website.create' => array(
1527 'url' => "http://civicrm.org",
1532 $result = $this->callAPISuccess('Contact', 'create', $params);
1534 'id' => $result['id'],
1535 'api.website.get' => array(),
1536 'api.Contribution.get' => array(
1537 'total_amount' => '120.00',
1539 'api.CustomValue.get' => 1,
1540 'api.Note.get' => 1,
1542 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1543 // delete the contact
1544 $this->callAPISuccess('contact', 'delete', $result);
1545 $this->customGroupDelete($ids['custom_group_id']);
1546 $this->customGroupDelete($moreIDs['custom_group_id']);
1547 $this->assertEquals(1, $result['id']);
1548 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
1549 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
1552 public function testGetIndividualWithChainedArraysFormats() {
1553 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
1554 $subfile = "APIChainedArrayFormats";
1555 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1556 $params['custom_' . $ids['custom_field_id']] = "custom string";
1558 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1560 'first_name' => 'abc3',
1561 'last_name' => 'xyz3',
1562 'contact_type' => 'Individual',
1563 'email' => 'man3@yahoo.com',
1564 'api.contribution.create' => array(
1565 'receive_date' => '2010-01-01',
1566 'total_amount' => 100.00,
1567 'financial_type_id' => $this->_financialTypeId
,
1568 'payment_instrument_id' => 1,
1569 'non_deductible_amount' => 10.00,
1570 'fee_amount' => 50.00,
1571 'net_amount' => 90.00,
1573 'contribution_status_id' => 1,
1575 'api.contribution.create.1' => array(
1576 'receive_date' => '2011-01-01',
1577 'total_amount' => 120.00,
1578 'financial_type_id' => $this->_financialTypeId
,
1579 'payment_instrument_id' => 1,
1580 'non_deductible_amount' => 10.00,
1581 'fee_amount' => 50.00,
1582 'net_amount' => 90.00,
1584 'contribution_status_id' => 1,
1586 'api.website.create' => array(
1588 'url' => "http://civicrm.org",
1593 $result = $this->callAPISuccess('Contact', 'create', $params);
1595 'id' => $result['id'],
1596 'api.website.getValue' => array('return' => 'url'),
1597 'api.Contribution.getCount' => array(),
1598 'api.CustomValue.get' => 1,
1599 'api.Note.get' => 1,
1600 'api.Membership.getCount' => array(),
1602 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1603 $this->assertEquals(1, $result['id']);
1604 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
1605 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
1606 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
1608 $this->callAPISuccess('contact', 'delete', $result);
1609 $this->customGroupDelete($ids['custom_group_id']);
1610 $this->customGroupDelete($moreIDs['custom_group_id']);
1614 * Test complex chaining.
1616 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
1617 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1618 $params['custom_' . $ids['custom_field_id']] = "custom string";
1619 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1620 $andMoreIDs = $this->CustomGroupMultipleCreateWithFields(array(
1621 'title' => "another group",
1622 'name' => 'another name',
1624 $description = "This demonstrates the usage of chained api functions with multiple custom fields.";
1625 $subfile = "APIChainedArrayMultipleCustom";
1627 'first_name' => 'abc3',
1628 'last_name' => 'xyz3',
1629 'contact_type' => 'Individual',
1630 'email' => 'man3@yahoo.com',
1631 'api.contribution.create' => array(
1632 'receive_date' => '2010-01-01',
1633 'total_amount' => 100.00,
1634 'financial_type_id' => 1,
1635 'payment_instrument_id' => 1,
1636 'non_deductible_amount' => 10.00,
1637 'fee_amount' => 50.00,
1638 'net_amount' => 90.00,
1640 'invoice_id' => 67890,
1642 'contribution_status_id' => 1,
1644 'api.contribution.create.1' => array(
1645 'receive_date' => '2011-01-01',
1646 'total_amount' => 120.00,
1647 'financial_type_id' => 1,
1648 'payment_instrument_id' => 1,
1649 'non_deductible_amount' => 10.00,
1650 'fee_amount' => 50.00,
1651 'net_amount' => 90.00,
1653 'invoice_id' => 67830,
1655 'contribution_status_id' => 1,
1657 'api.website.create' => array(
1659 'url' => "http://civicrm.org",
1662 'custom_' . $ids['custom_field_id'] => "value 1",
1663 'custom_' . $moreIDs['custom_field_id'][0] => "value 2",
1664 'custom_' . $moreIDs['custom_field_id'][1] => "warm beer",
1665 'custom_' . $andMoreIDs['custom_field_id'][1] => "vegemite",
1668 $result = $this->callAPISuccess('Contact', 'create', $params);
1669 $result = $this->callAPISuccess('Contact', 'create', array(
1670 'contact_type' => 'Individual',
1671 'id' => $result['id'],
1673 $moreIDs['custom_field_id'][0] => "value 3",
1675 $ids['custom_field_id'] => "value 4",
1679 'id' => $result['id'],
1680 'api.website.getValue' => array('return' => 'url'),
1681 'api.Contribution.getCount' => array(),
1682 'api.CustomValue.get' => 1,
1684 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1686 $this->customGroupDelete($ids['custom_group_id']);
1687 $this->customGroupDelete($moreIDs['custom_group_id']);
1688 $this->customGroupDelete($andMoreIDs['custom_group_id']);
1689 $this->assertEquals(1, $result['id']);
1690 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
1691 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
1695 * Test checks usage of $values to pick & choose inputs.
1697 public function testChainingValuesCreate() {
1698 $description = "This demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
1699 2 child functions - one receives values from the parent (Contact) and the other child (Tag).";
1700 $subfile = "APIChainedArrayValuesFromSiblingFunction";
1702 'display_name' => 'batman',
1703 'contact_type' => 'Individual',
1704 'api.tag.create' => array('name' => '$value.id', 'description' => '$value.display_name', 'format.only_id' => 1),
1705 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
1707 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1708 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
1710 $tablesToTruncate = array(
1713 'civicrm_entity_tag',
1716 $this->quickCleanup($tablesToTruncate, TRUE);
1720 * Test TrueFalse format - I couldn't come up with an easy way to get an error on Get.
1722 public function testContactGetFormatIsSuccessTrue() {
1723 $this->createContactFromXML();
1724 $description = "This demonstrates use of the 'format.is_success' param.
1725 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1726 $subfile = "FormatIsSuccess_True";
1727 $params = array('id' => 17, 'format.is_success' => 1);
1728 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1729 $this->assertEquals(1, $result);
1730 $this->callAPISuccess('Contact', 'Delete', $params);
1734 * Test TrueFalse format.
1736 public function testContactCreateFormatIsSuccessFalse() {
1738 $description = "This demonstrates use of the 'format.is_success' param.
1739 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1740 $subfile = "FormatIsSuccess_Fail";
1741 $params = array('id' => 500, 'format.is_success' => 1);
1742 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1743 $this->assertEquals(0, $result);
1747 * Test Single Entity format.
1749 public function testContactGetSingleEntityArray() {
1750 $this->createContactFromXML();
1751 $description = "This demonstrates use of the 'format.single_entity_array' param.
1752 This param causes the only contact to be returned as an array without the other levels.
1753 It will be ignored if there is not exactly 1 result";
1754 $subfile = "GetSingleContact";
1755 $params = array('id' => 17);
1756 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1757 $this->assertEquals('Test Contact', $result['display_name']);
1758 $this->callAPISuccess('Contact', 'Delete', $params);
1762 * Test Single Entity format.
1764 public function testContactGetFormatCountOnly() {
1765 $this->createContactFromXML();
1766 $description = "This demonstrates use of the 'getCount' action.
1767 This param causes the count of the only function to be returned as an integer.";
1768 $subfile = "GetCountContact";
1769 $params = array('id' => 17);
1770 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__
, __FILE__
, $description,
1771 $subfile, 'getcount');
1772 $this->assertEquals('1', $result);
1773 $this->callAPISuccess('Contact', 'Delete', $params);
1777 * Test id only format.
1779 public function testContactGetFormatIDOnly() {
1780 $this->createContactFromXML();
1781 $description = "This demonstrates use of the 'format.id_only' param.
1782 This param causes the id of the only entity to be returned as an integer.
1783 It will be ignored if there is not exactly 1 result";
1784 $subfile = "FormatOnlyID";
1785 $params = array('id' => 17, 'format.only_id' => 1);
1786 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1787 $this->assertEquals('17', $result);
1788 $this->callAPISuccess('Contact', 'Delete', $params);
1792 * Test id only format.
1794 public function testContactGetFormatSingleValue() {
1795 $this->createContactFromXML();
1796 $description = "This demonstrates use of the 'format.single_value' param.
1797 This param causes only a single value of the only entity to be returned as an string.
1798 It will be ignored if there is not exactly 1 result";
1799 $subFile = "FormatSingleValue";
1800 $params = array('id' => 17, 'return' => 'display_name');
1801 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
1802 $this->assertEquals('Test Contact', $result);
1803 $this->callAPISuccess('Contact', 'Delete', $params);
1807 * Test that permissions are respected when creating contacts.
1809 public function testContactCreationPermissions() {
1811 'contact_type' => 'Individual',
1812 'first_name' => 'Foo',
1813 'last_name' => 'Bear',
1814 'check_permissions' => TRUE,
1816 $config = CRM_Core_Config
::singleton();
1817 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1818 $result = $this->callAPIFailure('contact', 'create', $params);
1819 $this->assertEquals('API permission check failed for Contact/create call; insufficient permission: require access CiviCRM and add contacts', $result['error_message'], 'lacking permissions should not be enough to create a contact');
1821 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'add contacts', 'import contacts');
1822 $this->callAPISuccess('contact', 'create', $params, NULL, 'overfluous permissions should be enough to create a contact');
1826 * Test update with check permissions set.
1828 public function testContactUpdatePermissions() {
1830 'contact_type' => 'Individual',
1831 'first_name' => 'Foo',
1832 'last_name' => 'Bear',
1833 'check_permissions' => TRUE,
1835 $result = $this->callAPISuccess('contact', 'create', $params);
1836 $config = CRM_Core_Config
::singleton();
1838 'id' => $result['id'],
1839 'contact_type' => 'Individual',
1840 'last_name' => 'Bar',
1841 'check_permissions' => TRUE,
1844 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1845 $result = $this->callAPIFailure('contact', 'update', $params);
1846 $this->assertEquals('API permission check failed for Contact/update call; insufficient permission: require access CiviCRM and edit all contacts', $result['error_message'], 'lacking permissions should not be enough to update a contact');
1848 $config->userPermissionClass
->permissions
= array(
1851 'view all contacts',
1852 'edit all contacts',
1855 $this->callAPISuccess('contact', 'update', $params, NULL, 'overfluous permissions should be enough to update a contact');
1859 * Set up helper to create a contact.
1861 public function createContactFromXML() {
1862 // Insert a row in civicrm_contact creating contact 17.
1863 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1864 $op->execute($this->_dbconn
,
1865 $this->createXMLDataSet(
1866 dirname(__FILE__
) . '/dataset/contact_17.xml'
1872 * Test contact proximity api.
1874 public function testContactProximity() {
1875 // first create a contact with a SF location with a specific
1877 $contactID = $this->organizationCreate();
1879 // now create the address
1881 'street_address' => '123 Main Street',
1882 'city' => 'San Francisco',
1884 'country_id' => 1228,
1885 'state_province_id' => 1004,
1886 'geo_code_1' => '37.79',
1887 'geo_code_2' => '-122.40',
1888 'location_type_id' => 1,
1889 'contact_id' => $contactID,
1892 $result = $this->callAPISuccess('address', 'create', $params);
1893 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1895 // now do a proximity search with a close enough geocode and hope to match
1896 // that specific contact only!
1897 $proxParams = array(
1899 'longitude' => -122.3,
1903 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
1904 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1908 * Test that Ajax API permission is sufficient to access getquick api.
1910 * (note that getquick api is required for autocomplete & has ACL permissions applied)
1912 public function testGetquickPermissionCRM13744() {
1913 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviEvent');
1914 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1915 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
1916 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1917 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access AJAX API');
1918 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1922 * Test get ref api - gets a list of references to an entity.
1924 public function testGetReferenceCounts() {
1925 $result = $this->callAPISuccess('Contact', 'create', array(
1926 'first_name' => 'Testily',
1927 'last_name' => 'McHaste',
1928 'contact_type' => 'Individual',
1929 'api.Address.replace' => array(
1930 'values' => array(),
1932 'api.Email.replace' => array(
1935 'email' => 'spam@dev.null',
1937 'location_type_id' => 1,
1941 'api.Phone.replace' => array(
1944 'phone' => '234-567-0001',
1946 'location_type_id' => 1,
1949 'phone' => '234-567-0002',
1951 'location_type_id' => 1,
1957 //$dao = new CRM_Contact_BAO_Contact();
1958 //$dao->id = $result['id'];
1959 //$this->assertTrue((bool) $dao->find(TRUE));
1961 //$refCounts = $dao->getReferenceCounts();
1962 //$this->assertTrue(is_array($refCounts));
1963 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
1965 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
1966 'id' => $result['id'],
1968 $refCountsIdx = CRM_Utils_Array
::index(array('name'), $refCounts['values']);
1970 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
1971 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
1972 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
1973 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
1974 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
1977 public function testSQLOperatorsOnContactAPI() {
1978 $this->individualCreate();
1979 $this->organizationCreate();
1980 $this->householdCreate();
1981 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
1982 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
1983 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
1984 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
1988 * CRM-14743 - test api respects search operators.
1990 public function testGetModifiedDateByOperators() {
1991 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1992 $contact1 = $this->individualCreate();
1993 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
1994 CRM_Core_DAO
::executeQuery($sql);
1995 $contact2 = $this->individualCreate();
1996 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
1997 CRM_Core_DAO
::executeQuery($sql);
1998 $contact3 = $this->householdCreate();
1999 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
2000 CRM_Core_DAO
::executeQuery($sql);
2001 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
2002 $this->assertEquals($contacts['count'], 3);
2003 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
2004 $this->assertEquals($contacts['count'], $preExistingContactCount);
2008 * CRM-14743 - test api respects search operators.
2010 public function testGetCreatedDateByOperators() {
2011 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
2012 $contact1 = $this->individualCreate();
2013 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
2014 CRM_Core_DAO
::executeQuery($sql);
2015 $contact2 = $this->individualCreate();
2016 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
2017 CRM_Core_DAO
::executeQuery($sql);
2018 $contact3 = $this->householdCreate();
2019 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
2020 CRM_Core_DAO
::executeQuery($sql);
2021 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
2022 $this->assertEquals($contacts['count'], 3);
2023 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
2024 $this->assertEquals($contacts['count'], $preExistingContactCount);
2028 * CRM-14263 check that API is not affected by search profile related bug.
2030 public function testReturnCityProfile() {
2031 $contactID = $this->individualCreate();
2032 CRM_Core_Config
::singleton()->defaultSearchProfileID
= 1;
2033 $this->callAPISuccess('address', 'create', array(
2034 'contact_id' => $contactID,
2035 'city' => 'Cool City',
2036 'location_type_id' => 1,
2038 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
2039 $this->assertEquals(1, $result['count']);
2043 * CRM-15443 - ensure getlist api does not return deleted contacts
2045 public function testGetlistExcludeConditions() {
2046 $name = md5(time());
2047 $contact = $this->individualCreate(array('last_name' => $name));
2048 $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
2049 $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
2050 // We should get all but the deleted contact.
2051 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
2052 $this->assertEquals(2, $result['count'], 'In line ' . __LINE__
);
2053 // Force-exclude the deceased contact.
2054 $result = $this->callAPISuccess('contact', 'getlist', array(
2056 'params' => array('is_deceased' => 0),
2058 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
2059 $this->assertEquals($contact, $result['values'][0]['id'], 'In line ' . __LINE__
);
2063 * Test contact getactions.
2065 public function testGetActions() {
2066 $description = "Getting the available actions for an entity.";
2067 $result = $this->callAPIAndDocument($this->_entity
, 'getactions', array(), __FUNCTION__
, __FILE__
, $description);
2087 $deprecated = array(
2091 foreach ($expected as $action) {
2092 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
2094 foreach ($deprecated as $action) {
2095 $this->assertArrayKeyExists($action, $result['deprecated']);