From 86624a75865dab7e80734cabc520a643fc634f00 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Mon, 25 Oct 2021 12:27:26 +1300 Subject: [PATCH] [NFC] [REF] Test class cleanup The driver for this was to remove uses of the DAO->createTestObject methods which were creating individuals with data invalid for them. However, this is a full 'margin cleanup' and standardises the test. I think the whole createTestObject approach is best viewed as an early attempt to get lots of entities testable quickly but it's overwraught for creating contacts (and generally a bit flakey) --- .../CRM/Contact/BAO/GroupContactCacheTest.php | 353 ++++++++---------- 1 file changed, 165 insertions(+), 188 deletions(-) diff --git a/tests/phpunit/CRM/Contact/BAO/GroupContactCacheTest.php b/tests/phpunit/CRM/Contact/BAO/GroupContactCacheTest.php index 41cdc5ea91..0583354b4e 100644 --- a/tests/phpunit/CRM/Contact/BAO/GroupContactCacheTest.php +++ b/tests/phpunit/CRM/Contact/BAO/GroupContactCacheTest.php @@ -9,6 +9,8 @@ +--------------------------------------------------------------------+ */ +use Civi\Api4\Group; + /** * Test class for CRM_Contact_BAO_GroupContact BAO * @@ -29,19 +31,19 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { // Add $n1 to $g $this->callAPISuccess('GroupContact', 'create', [ - 'contact_id' => $living[0]->id, + 'contact_id' => $living[0], 'group_id' => $group->id, ]); CRM_Contact_BAO_GroupContactCache::load($group); $this->assertCacheMatches( - [$deceased[0]->id, $deceased[1]->id, $deceased[2]->id, $living[0]->id], - $group->id + [$deceased[0], $deceased[1], $deceased[2], $living[0]], + $this->ids['Group'][0] ); // Remove $y1 from $g $this->callAPISuccess('group_contact', 'create', [ - 'contact_id' => $deceased[0]->id, + 'contact_id' => $deceased[0], 'group_id' => $group->id, 'status' => 'Removed', ]); @@ -49,9 +51,9 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { CRM_Contact_BAO_GroupContactCache::load($group); $this->assertCacheMatches( [ - $deceased[1]->id, - $deceased[2]->id, - $living[0]->id, + $deceased[1], + $deceased[2], + $living[0], ], $group->id ); @@ -61,12 +63,15 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { * Allow removing contact from a parent group even if contact is in a child * group. (CRM-8858). * + * @throws \API_Exception * @throws \CRM_Core_Exception + * @throws \CiviCRM_API3_Exception */ public function testRemoveFromParentSmartGroup(): void { // Create $c1, $c2, $c3 - $deceased = $this->createTestObject('CRM_Contact_DAO_Contact', ['is_deceased' => 1], 3); - + $deceased[] = $this->individualCreate(['is_deceased' => 1]); + $deceased[] = $this->individualCreate(['is_deceased' => 1]); + $deceased[] = $this->individualCreate(['is_deceased' => 1]); // Create smart group $parent $params = [ 'name' => 'Deceased Contacts', @@ -74,36 +79,33 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { 'is_active' => 1, 'formValues' => ['is_deceased' => 1], ]; - $parent = CRM_Contact_BAO_Group::createSmartGroup($params); - $this->registerTestObjects([$parent]); + $parent = $this->createSmartGroup($params); // Create group $child in $parent - $params = [ + $child = $this->callAPISuccess('Group', 'create', [ 'name' => 'Child Group', 'title' => 'Child Group', 'is_active' => 1, 'parents' => [$parent->id => 1], - ]; - $child = CRM_Contact_BAO_Group::create($params); - $this->registerTestObjects([$child]); + ]); // Add $c1, $c2, $c3 to $child foreach ($deceased as $contact) { $this->callAPISuccess('group_contact', 'create', [ - 'contact_id' => $contact->id, - 'group_id' => $child->id, + 'contact_id' => $contact, + 'group_id' => $child['id'], ]); } CRM_Contact_BAO_GroupContactCache::load($parent); $this->assertCacheMatches( - [$deceased[0]->id, $deceased[1]->id, $deceased[2]->id], + [$deceased[0], $deceased[1], $deceased[2]], $parent->id ); // Remove $c1 from $parent $this->callAPISuccess('GroupContact', 'create', [ - 'contact_id' => $deceased[0]->id, + 'contact_id' => $deceased[0], 'group_id' => $parent->id, 'status' => 'Removed', ]); @@ -112,8 +114,8 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { CRM_Contact_BAO_GroupContactCache::load($parent); $this->assertCacheMatches( [ - $deceased[1]->id, - $deceased[2]->id, + $deceased[1], + $deceased[2], ], $parent->id ); @@ -122,8 +124,8 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { $this->assertDBQuery(1, 'select count(*) from civicrm_group_contact where group_id=%1 and contact_id=%2 and status=%3', [ - 1 => [$child->id, 'Integer'], - 2 => [$deceased[0]->id, 'Integer'], + 1 => [$child['id'], 'Integer'], + 2 => [$deceased[0], 'Integer'], 3 => ['Added', 'String'], ] ); @@ -136,7 +138,7 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { * Array(int). * @param int $groupId */ - public function assertCacheMatches($expectedContactIds, $groupId): void { + public function assertCacheMatches(array $expectedContactIds, int $groupId): void { $sql = 'SELECT contact_id FROM civicrm_group_contact_cache WHERE group_id = %1'; $params = [1 => [$groupId, 'Integer']]; $dao = CRM_Core_DAO::executeQuery($sql, $params); @@ -153,68 +155,74 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { /** * Test the opportunistic refresh cache function does not touch non-expired entries. */ - public function testOpportunisticRefreshCacheNoChangeIfNotExpired() { - [$group, $living, $deceased] = $this->setupSmartGroup(); - $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0]->id, 'is_deceased' => 0]); + public function testOpportunisticRefreshCacheNoChangeIfNotExpired(): void { + [$group, , $deceased] = $this->setupSmartGroup(); + $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0], 'is_deceased' => 0]); $this->assertCacheMatches( - [$deceased[0]->id, $deceased[1]->id, $deceased[2]->id], + [$deceased[0], $deceased[1], $deceased[2]], $group->id ); CRM_Contact_BAO_GroupContactCache::opportunisticCacheFlush(); - $this->assertCacheNotRefreshed($deceased, $group); + $this->assertCacheNotRefreshed($deceased, $group->id, $group->cache_date); } /** * Test the opportunistic refresh cache function does refresh stale entries. */ - public function testOpportunisticRefreshChangeIfCacheDateFieldStale() { - [$group, $living, $deceased] = $this->setupSmartGroup(); - $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0]->id, 'is_deceased' => 0]); + public function testOpportunisticRefreshChangeIfCacheDateFieldStale(): void { + [$group, , $deceased] = $this->setupSmartGroup(); + $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0], 'is_deceased' => 0]); CRM_Core_DAO::executeQuery('UPDATE civicrm_group SET cache_date = DATE_SUB(NOW(), INTERVAL 7 MINUTE) WHERE id = ' . $group->id); $group->find(TRUE); Civi::$statics['CRM_Contact_BAO_GroupContactCache']['is_refresh_init'] = FALSE; sleep(1); CRM_Contact_BAO_GroupContactCache::opportunisticCacheFlush(); - $this->assertCacheRefreshed($group); + $this->assertCacheRefreshed($this->ids['Group'][0]); } /** - * Test the opportunistic refresh cache function does refresh expired entries if mode is deterministic. + * Test the opportunistic refresh cache function does refresh expired entries + * if mode is deterministic. + * + * @throws \API_Exception */ - public function testOpportunisticRefreshNoChangeWithDeterministicSetting() { - [$group, $living, $deceased] = $this->setupSmartGroup(); + public function testOpportunisticRefreshNoChangeWithDeterministicSetting(): void { + [, , $deceased] = $this->setupSmartGroup(); $this->callAPISuccess('Setting', 'create', ['smart_group_cache_refresh_mode' => 'deterministic']); - $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0]->id, 'is_deceased' => 0]); - $this->makeCacheStale($group); + $this->callAPISuccess('Contact', 'create', ['id' => $this->ids['Contact']['dead1'], 'is_deceased' => 0]); + $this->makeCacheStale($this->ids['Group'][0]); + $cacheDate = Group::get() + ->addWhere('id', '=', $this->ids['Group'][0]) + ->addSelect('cache_date')->execute()->first()['cache_date']; CRM_Contact_BAO_GroupContactCache::opportunisticCacheFlush(); - $this->assertCacheNotRefreshed($deceased, $group); + $this->assertCacheNotRefreshed($deceased, $this->ids['Group'][0], $cacheDate); $this->callAPISuccess('Setting', 'create', ['smart_group_cache_refresh_mode' => 'opportunistic']); } /** * Test the deterministic cache function refreshes with the deterministic setting. */ - public function testDeterministicRefreshChangeWithDeterministicSetting() { - [$group, $living, $deceased] = $this->setupSmartGroup(); + public function testDeterministicRefreshChangeWithDeterministicSetting(): void { + $this->setupSmartGroup(); $this->callAPISuccess('Setting', 'create', ['smart_group_cache_refresh_mode' => 'deterministic']); - $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0]->id, 'is_deceased' => 0]); - $this->makeCacheStale($group); + $this->callAPISuccess('Contact', 'create', ['id' => $this->ids['Contact']['dead1'], 'is_deceased' => 0]); + $this->makeCacheStale($this->ids['Group'][0]); CRM_Contact_BAO_GroupContactCache::deterministicCacheFlush(); - $this->assertCacheRefreshed($group); + $this->assertCacheRefreshed($this->ids['Group'][0]); $this->callAPISuccess('Setting', 'create', ['smart_group_cache_refresh_mode' => 'opportunistic']); } /** * Test the deterministic cache function refresh doesn't mess up non-expired. */ - public function testDeterministicRefreshChangeDoesNotTouchNonExpired() { - [$group, $living, $deceased] = $this->setupSmartGroup(); + public function testDeterministicRefreshChangeDoesNotTouchNonExpired(): void { + [$group, , $deceased] = $this->setupSmartGroup(); $this->callAPISuccess('Setting', 'create', ['smart_group_cache_refresh_mode' => 'deterministic']); - $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0]->id, 'is_deceased' => 0]); + $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0], 'is_deceased' => 0]); CRM_Contact_BAO_GroupContactCache::deterministicCacheFlush(); - $this->assertCacheNotRefreshed($deceased, $group); + $this->assertCacheNotRefreshed($deceased, $group->id, $group->cache_date); $this->callAPISuccess('Setting', 'create', ['smart_group_cache_refresh_mode' => 'opportunistic']); } @@ -223,97 +231,37 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { * * (hey it's an opportunity!). */ - public function testDeterministicRefreshChangeWithOpportunisticSetting() { - [$group, $living, $deceased] = $this->setupSmartGroup(); + public function testDeterministicRefreshChangeWithOpportunisticSetting(): void { + [, , $deceased] = $this->setupSmartGroup(); $this->callAPISuccess('Setting', 'create', ['smart_group_cache_refresh_mode' => 'opportunistic']); - $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0]->id, 'is_deceased' => 0]); - $this->makeCacheStale($group); + $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0], 'is_deceased' => 0]); + $this->makeCacheStale($this->ids['Group'][0]); CRM_Contact_BAO_GroupContactCache::deterministicCacheFlush(); - $this->assertCacheRefreshed($group); + $this->assertCacheRefreshed($this->ids['Group'][0]); } /** * Test the api job wrapper around the deterministic refresh works. */ - public function testJobWrapper() { - [$group, $living, $deceased] = $this->setupSmartGroup(); + public function testJobWrapper(): void { + $this->setupSmartGroup(); $this->callAPISuccess('Setting', 'create', ['smart_group_cache_refresh_mode' => 'opportunistic']); - $this->callAPISuccess('Contact', 'create', ['id' => $deceased[0]->id, 'is_deceased' => 0]); - $this->makeCacheStale($group); + $this->callAPISuccess('Contact', 'create', ['id' => $this->ids['Contact']['dead1'], 'is_deceased' => 0]); + $this->makeCacheStale($this->ids['Group'][0]); $this->callAPISuccess('Job', 'group_cache_flush', []); - $this->assertCacheRefreshed($group); + $this->assertCacheRefreshed($this->ids['Group'][0]); } // *** Everything below this should be moved to parent class **** - /** - * @var array - * (DAO_Name => array(int)) List of items to garbage-collect during tearDown - */ - private $_testObjects; - /** * Tears down the fixture, for example, closes a network connection. * * This method is called after a test is executed. */ protected function tearDown(): void { + $this->quickCleanup(['civicrm_contact', 'civicrm_group', 'civicrm_saved_search', 'civicrm_group_contact']); parent::tearDown(); - $this->deleteTestObjects(); - } - - /** - * This is a wrapper for CRM_Core_DAO::createTestObject which tracks created entities. - * - * @see CRM_Core_DAO::createTestObject - * - * @param string $daoName - * @param array $params - * @param int $numObjects - * @param bool $createOnly - * - * @return array|NULL|object - */ - public function createTestObject($daoName, $params = [], $numObjects = 1, $createOnly = FALSE) { - $objects = CRM_Core_DAO::createTestObject($daoName, $params, $numObjects, $createOnly); - if (is_array($objects)) { - $this->registerTestObjects($objects); - } - else { - $this->registerTestObjects([$objects]); - } - return $objects; - } - - /** - * Register test objects. - * - * @param array $objects - * DAO or BAO objects. - */ - public function registerTestObjects($objects) { - foreach ($objects as $object) { - $daoName = preg_replace('/_BAO_/', '_DAO_', get_class($object)); - $this->_testObjects[$daoName][] = $object->id; - } - } - - /** - * Delete test objects. - * - * Note: You might argue that the FK relations between test - * objects could make this problematic; however, it should - * behave intuitively as long as we mentally split our - * test-objects between the "manual/primary records" - * and the "automatic/secondary records" - */ - public function deleteTestObjects() { - foreach ($this->_testObjects as $daoName => $daoIds) { - foreach ($daoIds as $daoId) { - CRM_Core_DAO::deleteTestObjects($daoName, ['id' => $daoId]); - } - } - $this->_testObjects = []; } /** @@ -322,85 +270,84 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { * @return array */ protected function setupSmartGroup(): array { - // Create contacts $y1, $y2, $y3 which do match $g; create $n1, $n2, $n3 which do not match $g - $living = $this->createTestObject('CRM_Contact_DAO_Contact', ['is_deceased' => 0], 3); - $deceased = $this->createTestObject('CRM_Contact_DAO_Contact', ['is_deceased' => 1], 3); - $this->assertCount(3, $deceased); - $this->assertCount(3, $living); - - $params = [ - 'name' => 'Deceased Contacts', - 'title' => 'Deceased Contacts', - 'is_active' => 1, - 'formValues' => ['is_deceased' => 1], - ]; - $group = CRM_Contact_BAO_Group::createSmartGroup($params); - $this->registerTestObjects([$group]); - - // Assert: $g cache has exactly $y1, $y2, $y3 - CRM_Contact_BAO_GroupContactCache::load($group); - $group->find(TRUE); - $this->assertCacheMatches( - [$deceased[0]->id, $deceased[1]->id, $deceased[2]->id], - $group->id - ); - // Reload the group so we have the cache_date & refresh_date. - return [$group, $living, $deceased]; + try { + // Create contacts $y1, $y2, $y3 which do match $g; create $n1, $n2, $n3 which do not match $g + [$living, $deceased] = $this->createLivingDead(); + + $params = [ + 'name' => 'Deceased Contacts', + 'title' => 'Deceased Contacts', + 'is_active' => 1, + 'formValues' => ['is_deceased' => 1], + ]; + $group = $this->createSmartGroup($params); + $this->ids['Group'][0] = $group->id; + // Assert: $g cache has exactly $y1, $y2, $y3 + CRM_Contact_BAO_GroupContactCache::load($group); + $group->find(TRUE); + $this->assertCacheMatches( + [$deceased[0], $deceased[1], $deceased[2]], + $group->id + ); + return [$group, $living, $deceased]; + } + catch (CRM_Core_Exception | API_Exception | CiviCRM_API3_Exception $e) { + $this->fail('failed test setup' . $e->getMessage()); + } + // unreachable but it cheers up IDE analysis. + return []; } /** - * @param $deceased - * @param $group - * - * @throws \Exception + * @param array $deceased + * @param int $groupID + * @param string $cacheDate */ - protected function assertCacheNotRefreshed($deceased, $group) { + protected function assertCacheNotRefreshed(array $deceased, int $groupID, string $cacheDate): void { $this->assertCacheMatches( - [$deceased[0]->id, $deceased[1]->id, $deceased[2]->id], - $group->id + [$deceased[0], $deceased[1], $deceased[2]], + $groupID ); - $afterGroup = $this->callAPISuccessGetSingle('Group', ['id' => $group->id]); - $this->assertEquals($group->cache_date, $afterGroup['cache_date']); + $afterGroup = $this->callAPISuccessGetSingle('Group', ['id' => $groupID]); + $this->assertEquals($cacheDate, $afterGroup['cache_date']); } /** * Make the cache for the group stale, resetting it to before the timeout period. * - * @param CRM_Contact_BAO_Group $group + * @param int $groupID */ - protected function makeCacheStale(&$group) { - CRM_Core_DAO::executeQuery('UPDATE civicrm_group SET cache_date = DATE_SUB(NOW(), INTERVAL 7 MINUTE) WHERE id = ' . $group->id); - unset($group->cache_date); - $group->find(TRUE); + protected function makeCacheStale(int $groupID): void { + CRM_Core_DAO::executeQuery('UPDATE civicrm_group SET cache_date = DATE_SUB(NOW(), INTERVAL 7 MINUTE) WHERE id = ' . $groupID); Civi::$statics['CRM_Contact_BAO_GroupContactCache']['is_refresh_init'] = FALSE; } /** - * @param $group - * - * @throws \Exception + * @param int $groupID */ - protected function assertCacheRefreshed($group) { + protected function assertCacheRefreshed(int $groupID): void { $this->assertCacheMatches( [], - $group->id + $groupID ); - $afterGroup = $this->callAPISuccessGetSingle('Group', ['id' => $group->id]); - $this->assertTrue(empty($afterGroup['cache_date']), 'cache date should not be set as the cache is not built'); + $afterGroup = $this->callAPISuccessGetSingle('Group', ['id' => $groupID]); + $this->assertArrayNotHasKey('cache_date', $afterGroup, 'cache date should not be set as the cache is not built'); } /** * Test Smart group search + * + * @throws \CRM_Core_Exception */ - public function testSmartGroupSearchBuilder() { + public function testSmartGroupSearchBuilder(): void { $returnProperties = [ 'contact_type' => 1, 'contact_sub_type' => 1, 'sort_name' => 1, 'group' => 1, ]; - [$group, $living, $deceased] = $this->setupSmartGroup(); + [$group] = $this->setupSmartGroup(); $params = [ 'name' => 'Living Contacts', @@ -408,7 +355,7 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { 'is_active' => 1, 'formValues' => ['is_deceased' => 0], ]; - $group2 = CRM_Contact_BAO_Group::createSmartGroup($params); + $group2 = $this->createSmartGroup($params); //Filter on smart group with =, !=, IN and NOT IN operator. $params = [['group', '=', $group2->id, 1, 0]]; @@ -418,14 +365,14 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { FALSE, FALSE, FALSE ); - $ids = $query->searchQuery(0, 0, NULL, + $query->searchQuery(0, 0, NULL, FALSE, FALSE, FALSE, - TRUE, FALSE + TRUE ); $key = $query->getGroupCacheTableKeys()[0]; - $expectedWhere = "civicrm_group_contact_cache_{$key}.group_id IN (\"{$group2->id}\")"; + $expectedWhere = "civicrm_group_contact_cache_$key.group_id IN (\"$group2->id\")"; $this->assertStringContainsString($expectedWhere, $query->_whereClause); - $this->_assertContactIds($query, "group_id = {$group2->id}"); + $this->assertContactIDsAreInCache($query, "group_id = $group2->id"); $params = [['group', '!=', $group->id, 1, 0]]; $query = new CRM_Contact_BAO_Query( @@ -436,9 +383,9 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { ); $key = $query->getGroupCacheTableKeys()[0]; //Assert if proper where clause is present. - $expectedWhere = "civicrm_group_contact_{$key}.group_id != {$group->id} AND civicrm_group_contact_cache_{$key}.group_id IS NULL OR ( civicrm_group_contact_cache_{$key}.contact_id NOT IN (SELECT contact_id FROM civicrm_group_contact_cache cgcc WHERE cgcc.group_id IN ( {$group->id} ) ) )"; + $expectedWhere = "civicrm_group_contact_$key.group_id != $group->id AND civicrm_group_contact_cache_$key.group_id IS NULL OR ( civicrm_group_contact_cache_$key.contact_id NOT IN (SELECT contact_id FROM civicrm_group_contact_cache cgcc WHERE cgcc.group_id IN ( $group->id ) ) )"; $this->assertStringContainsString($expectedWhere, $query->_whereClause); - $this->_assertContactIds($query, "group_id != {$group->id}"); + $this->assertContactIDsAreInCache($query, "group_id != $group->id"); $params = [['group', 'IN', [$group->id, $group2->id], 1, 0]]; $query = new CRM_Contact_BAO_Query( @@ -448,9 +395,9 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { FALSE, FALSE ); $key = $query->getGroupCacheTableKeys()[0]; - $expectedWhere = "civicrm_group_contact_cache_{$key}.group_id IN (\"{$group->id}\", \"{$group2->id}\")"; + $expectedWhere = "civicrm_group_contact_cache_$key.group_id IN (\"$group->id\", \"$group2->id\")"; $this->assertStringContainsString($expectedWhere, $query->_whereClause); - $this->_assertContactIds($query, "group_id IN ({$group->id}, {$group2->id})"); + $this->assertContactIDsAreInCache($query, "group_id IN ($group->id, $group2->id)"); $params = [['group', 'NOT IN', [$group->id], 1, 0]]; $query = new CRM_Contact_BAO_Query( @@ -460,21 +407,24 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { FALSE, FALSE ); $key = $query->getGroupCacheTableKeys()[0]; - $expectedWhere = "civicrm_group_contact_{$key}.group_id NOT IN ( {$group->id} ) AND civicrm_group_contact_cache_{$key}.group_id IS NULL OR ( civicrm_group_contact_cache_{$key}.contact_id NOT IN (SELECT contact_id FROM civicrm_group_contact_cache cgcc WHERE cgcc.group_id IN ( {$group->id} ) ) )"; + $expectedWhere = "civicrm_group_contact_$key.group_id NOT IN ( $group->id ) AND civicrm_group_contact_cache_$key.group_id IS NULL OR ( civicrm_group_contact_cache_$key.contact_id NOT IN (SELECT contact_id FROM civicrm_group_contact_cache cgcc WHERE cgcc.group_id IN ( $group->id ) ) )"; $this->assertStringContainsString($expectedWhere, $query->_whereClause); - $this->_assertContactIds($query, "group_id NOT IN ({$group->id})"); + $this->assertContactIDsAreInCache($query, "group_id NOT IN ($group->id)"); $this->callAPISuccess('group', 'delete', ['id' => $group->id]); $this->callAPISuccess('group', 'delete', ['id' => $group2->id]); } - public function testMultipleGroupWhereClause() { + /** + * @throws \CRM_Core_Exception + */ + public function testMultipleGroupWhereClause(): void { $returnProperties = [ 'contact_type' => 1, 'contact_sub_type' => 1, 'sort_name' => 1, 'group' => 1, ]; - [$group, $living, $deceased] = $this->setupSmartGroup(); + [$group] = $this->setupSmartGroup(); $params = [ 'name' => 'Living Contacts', @@ -482,7 +432,7 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { 'is_active' => 1, 'formValues' => ['is_deceased' => 0], ]; - $group2 = CRM_Contact_BAO_Group::createSmartGroup($params); + $group2 = $this->createSmartGroup($params); //Filter on smart group with =, !=, IN and NOT IN operator. $params = [['group', '=', $group2->id, 1, 0], ['group', '=', $group->id, 1, 0]]; @@ -492,12 +442,12 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { FALSE, FALSE, FALSE ); - $ids = $query->searchQuery(0, 0, NULL, + $query->searchQuery(0, 0, NULL, FALSE, FALSE, FALSE, - TRUE, FALSE + TRUE ); - $key1 = $query->getGroupCacheTableKeys()[0]; - $key2 = $query->getGroupCacheTableKeys()[1]; + [$key1, $key2] = $query->getGroupCacheTableKeys(); + $expectedWhere = 'civicrm_group_contact_cache_' . $key1 . '.group_id IN ("' . $group2->id . '") ) ) AND ( ( civicrm_group_contact_cache_' . $key2 . '.group_id IN ("' . $group->id . '")'; $this->assertStringContainsString($expectedWhere, $query->_whereClause); // Check that we have 3 joins to the group contact cache 1 for each of the group where clauses and 1 for the fact we are returning groups in the select. @@ -512,20 +462,47 @@ class CRM_Contact_BAO_GroupContactCacheTest extends CiviUnitTestCase { /** * Check if contact ids are fetched correctly. * - * @param object $query + * @param \CRM_Contact_BAO_Query $query * @param string $groupWhereClause */ - public function _assertContactIds($query, $groupWhereClause) { + public function assertContactIDsAreInCache(CRM_Contact_BAO_Query $query, string $groupWhereClause): void { $contactIds = explode(',', $query->searchQuery(0, 0, NULL, FALSE, FALSE, FALSE, - TRUE, FALSE + TRUE )); $expectedContactIds = []; - $groupDAO = CRM_Core_DAO::executeQuery("SELECT contact_id FROM civicrm_group_contact_cache WHERE {$groupWhereClause}"); + $groupDAO = CRM_Core_DAO::executeQuery("SELECT contact_id FROM civicrm_group_contact_cache WHERE $groupWhereClause"); while ($groupDAO->fetch()) { $expectedContactIds[] = $groupDAO->contact_id; } $this->assertEquals(sort($expectedContactIds), sort($contactIds)); } + /** + * @return array[] + */ + protected function createLivingDead(): array { + $living[] = $this->individualCreate(); + $living[] = $this->individualCreate(); + $living[] = $this->individualCreate(); + $deceased[] = $this->ids['Contact']['dead1'] = $this->individualCreate(['is_deceased' => 1]); + $deceased[] = $this->ids['Contact']['dead2'] = $this->individualCreate(['is_deceased' => 1]); + $deceased[] = $this->ids['Contact']['dead3'] = $this->individualCreate(['is_deceased' => 1]); + return [$living, $deceased]; + } + + /** + * Creates two entities: a Group and a SavedSearch + * + * @param array $params + * + * @return CRM_Contact_BAO_Group + */ + protected function createSmartGroup(array $params): CRM_Contact_BAO_Group { + $ssParams = ['form_values' => $params['formValues'], 'is_active' => 1]; + $savedSearch = CRM_Contact_BAO_SavedSearch::create($ssParams); + $params['saved_search_id'] = $savedSearch->id; + return CRM_Contact_BAO_Group::create($params); + } + } -- 2.25.1