class api_v3_ReportTemplateTest extends CiviUnitTestCase {
protected $_apiversion = 3;
- public function setUp() {
- parent::setUp();
- $this->useTransaction(TRUE);
+ /**
+ * Our group reports use an alter so transaction cleanup won't work.
+ *
+ * @throws \Exception
+ */
+ public function tearDown() {
+ $this->quickCleanUpFinancialEntities();
+ $this->quickCleanup(array('civicrm_group', 'civicrm_saved_search', 'civicrm_group_contact'));
+ parent::tearDown();
}
public function testReportTemplate() {
return $reportTemplates;
}
+ /**
+ * Get contribution templates that work with basic filter tests.
+ *
+ * These templates require minimal data config.
+ */
+ public static function getContributionReportTemplates() {
+ return array(array('contribute/summary'), array('contribute/detail'), array('contribute/repeat'), array('contribute/topDonor'));
+ }
+
/**
* Test Lybunt report to check basic inclusion of a contact who gave in the year before the chosen year.
*/
$this->assertEquals(2, $rows['count'], "Report failed - the sql used to generate the results was " . print_r($rows['metadata']['sql'], TRUE));
}
+ /**
+ * Test the group filter works on the contribution summary (with a smart group).
+ */
+ public function testContributionSummaryWithSmartGroupFilter() {
+ $groupID = $this->setUpPopulatedSmartGroup();
+ $rows = $this->callAPISuccess('report_template', 'getrows', array(
+ 'report_id' => 'contribute/summary',
+ 'gid_value' => $groupID,
+ 'gid_op' => 'in',
+ 'options' => array('metadata' => array('sql')),
+ ));
+ $this->assertEquals(3, $rows['values'][0]['civicrm_contribution_total_amount_count']);
+
+ }
+
+ /**
+ * Test the group filter works on the contribution summary (with a smart group).
+ */
+ public function testContributionSummaryWithNotINSmartGroupFilter() {
+ $groupID = $this->setUpPopulatedSmartGroup();
+ $rows = $this->callAPISuccess('report_template', 'getrows', array(
+ 'report_id' => 'contribute/summary',
+ 'gid_value' => $groupID,
+ 'gid_op' => 'not in',
+ 'options' => array('metadata' => array('sql')),
+ ));
+ $this->assertEquals(2, $rows['values'][0]['civicrm_contribution_total_amount_count']);
+
+ }
+
+ /**
+ * Test the group filter works on the contribution summary (with a smart group).
+ *
+ * @dataProvider getContributionReportTemplates
+ *
+ * @param string $template
+ * Report template unique identifier.
+ */
+ public function testContributionSummaryWithNonSmartGroupFilter($template) {
+ $groupID = $this->setUpPopulatedGroup();
+ $rows = $this->callAPISuccess('report_template', 'getrows', array(
+ 'report_id' => $template,
+ 'gid_value' => array($groupID),
+ 'gid_op' => 'in',
+ 'options' => array('metadata' => array('sql')),
+ ));
+ $this->assertNumberOfContactsInResult(1, $rows, $template);
+ }
+
+ /**
+ * Assert the included results match the expected.
+ *
+ * There may or may not be a group by in play so the assertion varies a little.
+ *
+ * @param int $numberExpected
+ * @param array $rows
+ * Rows returned from the report.
+ * @param string $template
+ */
+ protected function assertNumberOfContactsInResult($numberExpected, $rows, $template) {
+ if (isset($rows['values'][0]['civicrm_contribution_total_amount_count'])) {
+ $this->assertEquals($numberExpected, $rows['values'][0]['civicrm_contribution_total_amount_count'], 'wrong row count in ' . $template);
+ }
+ else {
+ $this->assertEquals($numberExpected, count($rows['values']), 'wrong row count in ' . $template);
+ }
+ }
+
+ /**
+ * Test the group filter works on the contribution summary when 2 groups are involved.
+ */
+ public function testContributionSummaryWithTwoGroups() {
+ $groupID = $this->setUpPopulatedGroup();
+ $groupID2 = $this->setUpPopulatedSmartGroup();
+ $rows = $this->callAPISuccess('report_template', 'getrows', array(
+ 'report_id' => 'contribute/summary',
+ 'gid_value' => array($groupID, $groupID2),
+ 'gid_op' => 'in',
+ 'options' => array('metadata' => array('sql')),
+ ));
+ $this->assertEquals(4, $rows['values'][0]['civicrm_contribution_total_amount_count']);
+ }
+
+ /**
+ * Test the group filter works on the contribution summary when 2 groups are involved.
+ */
+ public function testContributionSummaryWithTwoGroupsWithIntersection() {
+ $groups = $this->setUpIntersectingGroups();
+
+ $rows = $this->callAPISuccess('report_template', 'getrows', array(
+ 'report_id' => 'contribute/summary',
+ 'gid_value' => $groups,
+ 'gid_op' => 'in',
+ 'options' => array('metadata' => array('sql')),
+ ));
+ $this->assertEquals(7, $rows['values'][0]['civicrm_contribution_total_amount_count']);
+ }
+
+ /**
+ * Set up a smart group for testing.
+ *
+ * The smart group includes all Households by filter. In addition an individual
+ * is created and hard-added and an individual is created that is not added.
+ *
+ * One household is hard-added as well as being in the filter.
+ *
+ * This gives us a range of scenarios for testing contacts are included only once
+ * whenever they are hard-added or in the criteria.
+ *
+ * @return int
+ */
+ public function setUpPopulatedSmartGroup() {
+ $household1ID = $this->householdCreate();
+ $individual1ID = $this->individualCreate();
+ $householdID = $this->householdCreate();
+ $individualID = $this->individualCreate();
+ $individualIDRemoved = $this->individualCreate();
+ $groupID = $this->smartGroupCreate(array(), array('name' => uniqid(), 'title' => uniqid()));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID,
+ 'contact_id' => $individualIDRemoved,
+ 'status' => 'Removed',
+ ));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID,
+ 'contact_id' => $individualID,
+ 'status' => 'Added',
+ ));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID,
+ 'contact_id' => $householdID,
+ 'status' => 'Added',
+ ));
+ foreach (array($household1ID, $individual1ID, $householdID, $individualID, $individualIDRemoved) as $contactID) {
+ $this->contributionCreate(array('contact_id' => $contactID, 'invoice_id' => '', 'trxn_id' => ''));
+ }
+
+ // Refresh the cache for test purposes. It would be better to alter to alter the GroupContact add function to add contacts to the cache.
+ CRM_Contact_BAO_GroupContactCache::remove($groupID, FALSE);
+ return $groupID;
+ }
+
+ /**
+ * Set up a smart group for testing.
+ *
+ * The smart group includes all Households by filter. In addition an individual
+ * is created and hard-added and an individual is created that is not added.
+ *
+ * One household is hard-added as well as being in the filter.
+ *
+ * This gives us a range of scenarios for testing contacts are included only once
+ * whenever they are hard-added or in the criteria.
+ *
+ * @return int
+ */
+ public function setUpPopulatedGroup() {
+ $individual1ID = $this->individualCreate();
+ $individualID = $this->individualCreate();
+ $individualIDRemoved = $this->individualCreate();
+ $groupID = $this->groupCreate(array('name' => uniqid(), 'title' => uniqid()));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID,
+ 'contact_id' => $individualIDRemoved,
+ 'status' => 'Removed',
+ ));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID,
+ 'contact_id' => $individualID,
+ 'status' => 'Added',
+ ));
+
+ foreach (array($individual1ID, $individualID, $individualIDRemoved) as $contactID) {
+ $this->contributionCreate(array('contact_id' => $contactID, 'invoice_id' => '', 'trxn_id' => ''));
+ }
+
+ // Refresh the cache for test purposes. It would be better to alter to alter the GroupContact add function to add contacts to the cache.
+ CRM_Contact_BAO_GroupContactCache::remove($groupID, FALSE);
+ return $groupID;
+ }
+
+ /**
+ * @return array
+ */
+ public function setUpIntersectingGroups() {
+ $groupID = $this->setUpPopulatedGroup();
+ $groupID2 = $this->setUpPopulatedSmartGroup();
+ $addedToBothIndividualID = $this->individualCreate();
+ $removedFromBothIndividualID = $this->individualCreate();
+ $addedToSmartGroupRemovedFromOtherIndividualID = $this->individualCreate();
+ $removedFromSmartGroupAddedToOtherIndividualID = $this->individualCreate();
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID,
+ 'contact_id' => $addedToBothIndividualID,
+ 'status' => 'Added',
+ ));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID2,
+ 'contact_id' => $addedToBothIndividualID,
+ 'status' => 'Added',
+ ));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID,
+ 'contact_id' => $removedFromBothIndividualID,
+ 'status' => 'Removed',
+ ));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID2,
+ 'contact_id' => $removedFromBothIndividualID,
+ 'status' => 'Removed',
+ ));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID2,
+ 'contact_id' => $addedToSmartGroupRemovedFromOtherIndividualID,
+ 'status' => 'Added',
+ ));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID,
+ 'contact_id' => $addedToSmartGroupRemovedFromOtherIndividualID,
+ 'status' => 'Removed',
+ ));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID,
+ 'contact_id' => $removedFromSmartGroupAddedToOtherIndividualID,
+ 'status' => 'Added',
+ ));
+ $this->callAPISuccess('GroupContact', 'create', array(
+ 'group_id' => $groupID2,
+ 'contact_id' => $removedFromSmartGroupAddedToOtherIndividualID,
+ 'status' => 'Removed',
+ ));
+
+ foreach (array(
+ $addedToBothIndividualID,
+ $removedFromBothIndividualID,
+ $addedToSmartGroupRemovedFromOtherIndividualID,
+ $removedFromSmartGroupAddedToOtherIndividualID,
+ ) as $contactID) {
+ $this->contributionCreate(array(
+ 'contact_id' => $contactID,
+ 'invoice_id' => '',
+ 'trxn_id' => '',
+ ));
+ }
+ return array($groupID, $groupID2);
+ }
+
}