From 4ac6bdf3ddb3a17e0eb8448cbc81e704bb2ce7a4 Mon Sep 17 00:00:00 2001 From: eileen Date: Thu, 21 Jul 2016 16:02:20 +1200 Subject: [PATCH] CRM-19074 attempt to replicate the bug in a test I didn't actually succeed in replicating it - although I increased coverage. The issue is that when there is no consistent differentiation between a custom checkbox field which is no set vs one that has been set to empty(unchecked). There is an inconsistent data storage difference whereby it is sometimes stored as an empty string & sometimes as NULL but this does not seem to be something that is deliberate. --- .../phpunit/api/v3/JobTestCustomDataTest.php | 454 +++++++++--------- 1 file changed, 226 insertions(+), 228 deletions(-) diff --git a/tests/phpunit/api/v3/JobTestCustomDataTest.php b/tests/phpunit/api/v3/JobTestCustomDataTest.php index 794bf5f01c..504619d0b5 100644 --- a/tests/phpunit/api/v3/JobTestCustomDataTest.php +++ b/tests/phpunit/api/v3/JobTestCustomDataTest.php @@ -48,7 +48,6 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { protected $_apiversion = 3; public $_entity = 'Job'; - public $_params = array(); /** * Custom group ID. @@ -57,6 +56,27 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { */ public $customFieldID = NULL; + /** + * ID of a custom field of integer type. + * + * @var int + */ + public $customIntFieldID = NULL; + + /** + * ID of a custom field of integer type. + * + * @var int + */ + public $customBoolFieldID = NULL; + + /** + * ID of a custom field of integer type. + * + * @var int + */ + public $customStringCheckboxID = NULL; + /** * Custom Field ID. * @@ -66,16 +86,40 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { public function setUp() { parent::setUp(); - $this->_params = array( - 'sequential' => 1, - 'name' => 'API_Test_Job', - 'description' => 'A long description written by hand in cursive', - 'run_frequency' => 'Daily', - 'api_entity' => 'ApiTestEntity', - 'api_action' => 'apitestaction', - 'parameters' => 'Semi-formal explanation of runtime job parameters', - 'is_active' => 1, - ); + $customGroup = $this->customGroupCreate(); + $this->customGroupID = $customGroup['id']; + $customField = $this->customFieldCreate(array( + 'custom_group_id' => $this->customGroupID, + 'data_type' => 'Date', + 'html_type' => 'Select Date', + 'default_value' => '', + )); + $this->customFieldID = $customField['id']; + $customField = $this->customFieldCreate(array( + 'custom_group_id' => $this->customGroupID, + 'data_type' => 'Integer', + 'html_type' => 'Text', + 'default_value' => '', + 'label' => 'Int Field', + )); + $this->customIntFieldID = $customField['id']; + $customField = $this->customFieldCreate(array( + 'custom_group_id' => $this->customGroupID, + 'data_type' => 'Boolean', + 'html_type' => 'Radio', + 'default_value' => '', + 'label' => 'Radio Field', + )); + $this->customBoolFieldID = $customField['id']; + $customField = $this->customFieldCreate(array( + 'custom_group_id' => $this->customGroupID, + 'data_type' => 'String', + 'html_type' => 'CheckBox', + 'default_value' => NULL, + 'label' => 'checkbox Field', + 'option_values' => array('black' => 'black', 'white' => 'white'), + )); + $this->customStringCheckboxID = $customField['id']; } /** @@ -86,21 +130,100 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { parent::tearDown(); } + /** + * Test the batch merge does not bork on custom date fields. + * + * @dataProvider getCheckboxData + * + * Test CRM-19074 checkbox field handling. + * + * Given a custom field with 2 checkboxes (black & white) possible values are: + * 1) SEPARATOR + black + SEPARATOR + * 2) SEPARATOR + white + SEPARATOR + * 3) SEPARATOR + black + SEPARATOR + white + SEPARATOR + * 3) '' (ie empty string means both set to 0) + * 4) NULL (ie not set) + * - in safe mode NULL is not a conflict with any option but the other + * combos are a conflict. + */ + public function testBatchMergeCheckboxCustomFieldHandling($dataSet) { + $customFieldLabel = 'custom_' . $this->customStringCheckboxID; + $contact1Params = is_array($dataSet['contacts'][0]) ? array($customFieldLabel => $dataSet['contacts'][0]) : array(); + $contact2Params = is_array($dataSet['contacts'][1]) ? array($customFieldLabel => $dataSet['contacts'][1]) : array(); + $contactID = $this->individualCreate($contact1Params); + $this->individualCreate($contact2Params); + $result = $this->callAPISuccess('Job', 'process_batch_merge', array('mode' => $dataSet['mode'])); + $this->assertEquals($dataSet['merged'], count($result['values']['merged'])); + $this->assertEquals($dataSet['skipped'], count($result['values']['skipped'])); + $contact = $this->callAPISuccess('Contact', 'getsingle', array('id' => $contactID, 'return' => $customFieldLabel)); + $this->assertEquals($dataSet['expected'], $contact[$customFieldLabel]); + } + + /** + * Get the various data combinations for a checkbox field. + * + * @return array + */ + public function getCheckboxData() { + $data = array( + array( + 'null_merges_with_set' => array( + 'mode' => 'safe', + 'contacts' => array( + NULL, + array('black'), + ), + 'skipped' => 0, + 'merged' => 1, + 'expected' => array('black'), + ), + ), + array( + 'null_merges_with_set_reverse' => array( + 'mode' => 'safe', + 'contacts' => array( + array('black'), + NULL, + ), + 'skipped' => 0, + 'merged' => 1, + 'expected' => array('black'), + + ), + ), + array( + 'empty_conflicts_with_set' => array( + 'mode' => 'safe', + 'contacts' => array( + array('white'), + array('black'), + ), + 'skipped' => 1, + 'merged' => 0, + 'expected' => array('white'), + ), + ), + array( + 'empty_conflicts_with_set' => array( + 'mode' => 'aggressive', + 'contacts' => array( + array('white'), + array('black'), + ), + 'skipped' => 0, + 'merged' => 1, + 'expected' => array('white'), + ), + ), + ); + return $data; + } /** * Test the batch merge does not bork on custom date fields. * * Test CRM-18674 date custom field handling. */ public function testBatchMergeDateCustomFieldHandling() { - $customGroup = $this->customGroupCreate(); - $this->customGroupID = $customGroup['id']; - $customField = $this->customFieldCreate(array( - 'custom_group_id' => $this->customGroupID, - 'data_type' => 'Date', - 'html_type' => 'Select Date', - 'default_value' => '', - )); - $this->customFieldID = $customField['id']; $customFieldLabel = 'custom_' . $this->customFieldID; $contactID = $this->individualCreate(); $this->individualCreate(array($customFieldLabel => '2012-12-03')); @@ -116,38 +239,23 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { * Test CRM-18674 date custom field handling. */ public function testBatchMergeDateCustomFieldHandlingIsView() { - $customGroup = $this->customGroupCreate(); - $this->customGroupID = $customGroup['id']; - $customField = $this->customFieldCreate(array( - 'custom_group_id' => $this->customGroupID, - 'data_type' => 'Date', - 'html_type' => 'Select Date', - 'default_value' => '', + $this->customFieldCreate(array( + 'id' => $this->customFieldID, 'is_view' => 1, )); - $this->customFieldID = $customField['id']; $customFieldLabel = 'custom_' . $this->customFieldID; $contactID = $this->individualCreate(); $this->individualCreate(array($customFieldLabel => '2012-11-03')); $result = $this->callAPISuccess('Job', 'process_batch_merge', array()); $this->assertEquals(1, count($result['values']['merged'])); $contact = $this->callAPISuccess('Contact', 'getsingle', array('id' => $contactID, 'return' => $customFieldLabel)); - $this->assertEquals('2012-11-03 00:00:00', $contact[$customFieldLabel]); + $this->assertEquals('2012-11-03', $contact[$customFieldLabel]); } /** * Check we get a conflict on the custom field. */ public function testBatchMergeDateCustomFieldConflict() { - $customGroup = $this->customGroupCreate(); - $this->customGroupID = $customGroup['id']; - $customField = $this->customFieldCreate(array( - 'custom_group_id' => $this->customGroupID, - 'data_type' => 'Date', - 'html_type' => 'Select Date', - 'default_value' => '', - )); - $this->customFieldID = $customField['id']; $customFieldLabel = 'custom_' . $this->customFieldID; $contactID = $this->individualCreate(array($customFieldLabel => '2012-11-03')); $this->individualCreate(array($customFieldLabel => '2013-11-03')); @@ -162,15 +270,6 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { * Check we get a conflict on the custom field. */ public function testBatchMergeDateCustomFieldNoConflict() { - $customGroup = $this->customGroupCreate(); - $this->customGroupID = $customGroup['id']; - $customField = $this->customFieldCreate(array( - 'custom_group_id' => $this->customGroupID, - 'data_type' => 'Date', - 'html_type' => 'Select Date', - 'default_value' => '', - )); - $this->customFieldID = $customField['id']; $customFieldLabel = 'custom_' . $this->customFieldID; $contactID = $this->individualCreate(array($customFieldLabel => '2012-11-03')); $this->individualCreate(array($customFieldLabel => '2012-11-03')); @@ -185,16 +284,7 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { * Check we get a no conflict on the custom field & integer merges. */ public function testBatchMergeIntCustomFieldNoConflict() { - $customGroup = $this->customGroupCreate(); - $this->customGroupID = $customGroup['id']; - $customField = $this->customFieldCreate(array( - 'custom_group_id' => $this->customGroupID, - 'data_type' => 'Integer', - 'html_type' => 'Text', - 'default_value' => '', - )); - $this->customFieldID = $customField['id']; - $customFieldLabel = 'custom_' . $this->customFieldID; + $customFieldLabel = 'custom_' . $this->customIntFieldID; $contactID = $this->individualCreate(array()); $this->individualCreate(array($customFieldLabel => 20)); $result = $this->callAPISuccess('Job', 'process_batch_merge', array()); @@ -208,16 +298,7 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { * Check we get a conflict on the integer custom field. */ public function testBatchMergeIntCustomFieldConflict() { - $customGroup = $this->customGroupCreate(); - $this->customGroupID = $customGroup['id']; - $customField = $this->customFieldCreate(array( - 'custom_group_id' => $this->customGroupID, - 'data_type' => 'Integer', - 'html_type' => 'Text', - 'default_value' => '', - )); - $this->customFieldID = $customField['id']; - $customFieldLabel = 'custom_' . $this->customFieldID; + $customFieldLabel = 'custom_' . $this->customIntFieldID; $contactID = $this->individualCreate(array($customFieldLabel => 20)); $this->individualCreate(array($customFieldLabel => 1)); $result = $this->callAPISuccess('Job', 'process_batch_merge', array()); @@ -231,16 +312,7 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { * Check we get a conflict on the integer custom field when the conflicted field is 0. */ public function testBatchMergeIntCustomFieldConflictZero() { - $customGroup = $this->customGroupCreate(); - $this->customGroupID = $customGroup['id']; - $customField = $this->customFieldCreate(array( - 'custom_group_id' => $this->customGroupID, - 'data_type' => 'Integer', - 'html_type' => 'Text', - 'default_value' => '', - )); - $this->customFieldID = $customField['id']; - $customFieldLabel = 'custom_' . $this->customFieldID; + $customFieldLabel = 'custom_' . $this->customIntFieldID; $contactID = $this->individualCreate(array($customFieldLabel => 0)); $this->individualCreate(array($customFieldLabel => 20)); $result = $this->callAPISuccess('Job', 'process_batch_merge', array()); @@ -251,21 +323,14 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { } /** - * Using the api with check perms set to off, make sure custom data is merged.git + * Using the api with check perms set to off, make sure custom data is merged. * * Test CRM-18674 date custom field handling. */ public function testBatchMergeDateCustomFieldConflictAndNoCheckPerms() { CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM', 'edit my contact'); - $customGroup = $this->customGroupCreate(); - $this->customGroupID = $customGroup['id']; - $customField = $this->customFieldCreate(array( - 'custom_group_id' => $this->customGroupID, - 'data_type' => 'Date', - 'html_type' => 'Select Date', - 'default_value' => '', - )); - $this->customFieldID = $customField['id']; + CRM_Core_DAO::executeQuery("DELETE FROM civicrm_cache"); + CRM_Utils_System::flushCache(); $customFieldLabel = 'custom_' . $this->customFieldID; $contactID = $this->individualCreate(array($customFieldLabel => '2012-11-03')); $this->individualCreate(array($customFieldLabel => '2013-11-03')); @@ -277,152 +342,85 @@ class api_v3_JobTestCustomDataTest extends CiviUnitTestCase { } /** - * Get data for batch merge. + * Using the api with check perms set to off, make sure custom data is merged. + * + * Test CRM-18674 date custom field handling. */ - public function getMergeSets() { - $data = array( - array( - array( - 'mode' => 'safe', - 'contacts' => array( - array( - 'first_name' => 'Michael', - 'last_name' => 'Jackson', - 'email' => 'michael@neverland.com', - 'contact_type' => 'Individual', - 'contact_sub_type' => 'Student', - 'api.Address.create' => array( - 'street_address' => 'big house', - 'location_type_id' => 'Home', - ), - ), - array( - 'first_name' => 'Michael', - 'last_name' => 'Jackson', - 'email' => 'michael@neverland.com', - 'contact_type' => 'Individual', - 'contact_sub_type' => 'Student', - ), - ), - 'skipped' => 0, - 'merged' => 1, - 'expected' => array( - array( - 'first_name' => 'Michael', - 'last_name' => 'Jackson', - 'email' => 'michael@neverland.com', - 'contact_type' => 'Individual', - ), - ), - ), - ), - array( - array( - 'mode' => 'safe', - 'contacts' => array( - array( - 'first_name' => 'Michael', - 'last_name' => 'Jackson', - 'email' => 'michael@neverland.com', - 'contact_type' => 'Individual', - 'contact_sub_type' => 'Student', - 'api.Address.create' => array( - 'street_address' => 'big house', - 'location_type_id' => 'Home', - ), - ), - array( - 'first_name' => 'Michael', - 'last_name' => 'Jackson', - 'email' => 'michael@neverland.com', - 'contact_type' => 'Individual', - 'contact_sub_type' => 'Student', - 'api.Address.create' => array( - 'street_address' => 'bigger house', - 'location_type_id' => 'Home', - ), - ), - ), - 'skipped' => 1, - 'merged' => 0, - 'expected' => array( - array( - 'first_name' => 'Michael', - 'last_name' => 'Jackson', - 'email' => 'michael@neverland.com', - 'contact_type' => 'Individual', - 'street_address' => 'big house', - ), - array( - 'first_name' => 'Michael', - 'last_name' => 'Jackson', - 'email' => 'michael@neverland.com', - 'contact_type' => 'Individual', - 'street_address' => 'bigger house', - ), - ), - ), - ), - array( - array( - 'mode' => 'aggressive', - 'contacts' => array( - array( - 'first_name' => 'Michael', - 'last_name' => 'Jackson', - 'email' => 'michael@neverland.com', - 'contact_type' => 'Individual', - 'contact_sub_type' => 'Student', - 'api.Address.create' => array( - 'street_address' => 'big house', - 'location_type_id' => 'Home', - ), - ), - array( - 'first_name' => 'Michael', - 'last_name' => 'Jackson', - 'email' => 'michael@neverland.com', - 'contact_type' => 'Individual', - 'contact_sub_type' => 'Student', - 'api.Address.create' => array( - 'street_address' => 'bigger house', - 'location_type_id' => 'Home', - ), - ), - ), - 'skipped' => 0, - 'merged' => 1, - 'expected' => array( - array( - 'first_name' => 'Michael', - 'last_name' => 'Jackson', - 'email' => 'michael@neverland.com', - 'contact_type' => 'Individual', - 'street_address' => 'big house', - ), - ), - ), - ), - ); - return $data; + public function testBatchMergeDateCustomFieldNoConflictAndNoCheckPerms() { + CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM', 'edit my contact'); + CRM_Core_DAO::executeQuery("DELETE FROM civicrm_cache"); + CRM_Utils_System::flushCache(); + $customFieldLabel = 'custom_' . $this->customFieldID; + $contactID = $this->individualCreate(); + $this->individualCreate(array($customFieldLabel => '2013-11-03')); + $result = $this->callAPISuccess('Job', 'process_batch_merge', array('check_permissions' => 0)); + $this->assertEquals(1, count($result['values']['merged'])); + $this->assertEquals(0, count($result['values']['skipped'])); + $contact = $this->callAPISuccess('Contact', 'getsingle', array('id' => $contactID, 'return' => $customFieldLabel)); + $this->assertEquals('2013-11-03 00:00:00', $contact[$customFieldLabel]); } /** - * @param $op - * @param string $objectName - * @param int $id - * @param array $params + * Using the api with check perms set to off, make sure custom data is merged. + * + * Test CRM-18674 date custom field handling. */ - public function hookPreRelationship($op, $objectName, $id, &$params) { - if ($op == 'delete') { - return; - } - if ($params['is_active']) { - $params['description'] = 'Hooked'; - } - else { - $params['description'] = 'Go Go you good thing'; - } + public function testBatchMergeIntCustomFieldNoConflictAndNoCheckPerms() { + CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM', 'edit my contact'); + CRM_Core_DAO::executeQuery("DELETE FROM civicrm_cache"); + CRM_Utils_System::flushCache(); + $customFieldLabel = 'custom_' . $this->customIntFieldID; + $contactID = $this->individualCreate(); + $this->individualCreate(array($customFieldLabel => 1)); + $result = $this->callAPISuccess('Job', 'process_batch_merge', array('check_permissions' => 0)); + $this->assertEquals(1, count($result['values']['merged'])); + $this->assertEquals(0, count($result['values']['skipped'])); + $contact = $this->callAPISuccess('Contact', 'getsingle', array('id' => $contactID, 'return' => $customFieldLabel)); + $this->assertEquals(1, $contact[$customFieldLabel]); + } + + /** + * Check we get a conflict on the customs field when the data conflicts for booleans. + */ + public function testBatchMergeCustomFieldConflicts() { + $this->individualCreate(array('custom_' . $this->customBoolFieldID => 0)); + $this->individualCreate(array('custom_' . $this->customBoolFieldID => 1)); + $result = $this->callAPISuccess('Job', 'process_batch_merge', array()); + $this->assertEquals(0, count($result['values']['merged'])); + $this->assertEquals(1, count($result['values']['skipped'])); + } + + /** + * Check we get a conflict on the customs field when the data conflicts for booleans (reverse). + */ + public function testBatchMergeCustomFieldConflictsReverse() { + $this->individualCreate(array('custom_' . $this->customBoolFieldID => 1)); + $this->individualCreate(array('custom_' . $this->customBoolFieldID => 0)); + $result = $this->callAPISuccess('Job', 'process_batch_merge', array()); + $this->assertEquals(0, count($result['values']['merged'])); + $this->assertEquals(1, count($result['values']['skipped'])); + } + + /** + * Check we get a conflict on the customs field when the data conflicts for booleans (reverse). + */ + public function testBatchMergeCustomFieldConflictsOneBlank() { + $this->individualCreate(array('custom_' . $this->customBoolFieldID => 1)); + $this->individualCreate(); + $result = $this->callAPISuccess('Job', 'process_batch_merge', array()); + $this->assertEquals(1, count($result['values']['merged'])); + $this->assertEquals(0, count($result['values']['skipped'])); + } + + /** + * Check we get a conflict on the customs field when the data conflicts for booleans (reverse). + */ + public function testBatchMergeCustomFieldConflictsOneBlankReverse() { + $this->individualCreate(); + $this->individualCreate(array('custom_' . $this->customBoolFieldID => 1)); + $result = $this->callAPISuccess('Job', 'process_batch_merge', array()); + $this->assertEquals(1, count($result['values']['merged'])); + $this->assertEquals(0, count($result['values']['skipped'])); } } -- 2.25.1