From eb5845d4ee34b833f0fdfeddaed9ebf5f35f4fac Mon Sep 17 00:00:00 2001 From: larssandergreen Date: Wed, 26 Apr 2023 14:33:15 -0600 Subject: [PATCH] Dave's tests --- .../CRM/Activity/Form/ActivityViewTest.php | 468 ++++++++++++++++++ 1 file changed, 468 insertions(+) diff --git a/tests/phpunit/CRM/Activity/Form/ActivityViewTest.php b/tests/phpunit/CRM/Activity/Form/ActivityViewTest.php index 5215221919..ec5eef08e8 100644 --- a/tests/phpunit/CRM/Activity/Form/ActivityViewTest.php +++ b/tests/phpunit/CRM/Activity/Form/ActivityViewTest.php @@ -5,6 +5,41 @@ */ class CRM_Activity_Form_ActivityViewTest extends CiviUnitTestCase { + /** + * @var int + */ + protected $source_contact_id; + + /** + * @var int + */ + protected $target_contact_id; + + /** + * @var int + */ + protected $mailing_id; + + /** + * @var int + */ + protected $case_id; + + public function setUp(): void { + parent::setUp(); + $this->source_contact_id = $this->createLoggedInUser(); + $this->target_contact_id = $this->individualCreate([], 0, TRUE); + $this->mailing_id = $this->callAPISuccess('Mailing', 'create', [ + 'subject' => 'A Mailing Subject', + // We need the newlines to be early since this text gets truncated + 'body_text' => "This\naddress\n\nis not ours: {domain.address}.\n\nDo not click this link {action.optOutUrl}.", + 'name' => 'amailing', + 'created_id' => $this->source_contact_id, + ]); + CRM_Core_BAO_ConfigSetting::enableComponent('CiviCase'); + $this->case_id = $this->createCase($this->target_contact_id, $this->source_contact_id)->id; + } + /** * Cleanup after class. * @@ -12,10 +47,15 @@ class CRM_Activity_Form_ActivityViewTest extends CiviUnitTestCase { */ public function tearDown(): void { $tablesToTruncate = [ + 'civicrm_case_activity', + 'civicrm_case_contact', 'civicrm_activity', 'civicrm_activity_contact', + 'civicrm_case', + 'civicrm_contact', ]; $this->quickCleanup($tablesToTruncate); + CRM_Core_BAO_ConfigSetting::disableComponent('CiviCase'); parent::tearDown(); } @@ -81,4 +121,432 @@ class CRM_Activity_Form_ActivityViewTest extends CiviUnitTestCase { $this->assertEquals($expected, $templateVar); } + /** + * Test that the text is neither squished nor double-spaced. + * @dataProvider activityTypesProvider + * @dataProvider caseActivityTypesProvider + * @param array $input + * @param string $expected + */ + public function testNewlinesLookRight(array $input, string $expected) { + if (!empty($input['skip'])) { + $this->markTestSkipped('This test is boring.'); + return; + } + + $activity = $this->activityCreate([ + 'source_contact_id' => $this->source_contact_id, + 'target_contact_id' => $this->target_contact_id, + 'details' => $input['details'], + 'activity_type_id' => $input['activity_type'], + 'source_record_id' => ($input['activity_type'] === 'Bulk Email' ? $this->mailing_id : NULL), + 'case_id' => (strpos($input['url'], 'caseid') === FALSE ? NULL : $this->case_id), + ]); + + // We have to replace these at runtime because dataproviders are + // evaluated even before setUp() runs. + $input['url'] = str_replace('%%id%%', $activity['id'], $input['url']); + $input['url'] = str_replace('%%aid%%', $activity['id'], $input['url']); + $input['url'] = str_replace('%%cid%%', $this->source_contact_id, $input['url']); + $input['url'] = str_replace('%%atype%%', CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', $input['activity_type']), $input['url']); + $input['url'] = str_replace('%%caseid%%', $this->case_id, $input['url']); + + $this->setRequestVars($input['url']); + + $item = CRM_Core_Invoke::getItem([$_GET['q']]); + ob_start(); + CRM_Core_Invoke::runItem($item); + $contents = ob_get_clean(); + + $this->unsetRequestVars($input['url']); + + // See note in activityTypesProvider why we do this + $contents = str_replace(["\r", "\n"], '', $contents); + + $this->assertStringContainsString($expected, $contents); + } + + /** + * data provider for testNewlinesLookRight() for non-case activities + * + * Unfortunately there seem to be differences in the output of `purify` on + * unix vs windows, and also on unix it seems to even work differently in + * tests than when run normally! So we strip all chr(10) and chr(13) when + * comparing the result. + * + * @return array + */ + public function activityTypesProvider(): array { + $data = [ + 'meeting-text' => [ + [ + 'activity_type' => 'Meeting', + 'url' => 'civicrm/activity?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +This is text only +and has two consecutive lines. + +And one blank line. +ENDDETAILS + ], + 'This is text only
and has two consecutive lines.

And one blank line.
', + ], + + 'bulkemail-text' => [ + [ + 'activity_type' => 'Bulk Email', + 'url' => 'civicrm/activity/view?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +This is text only +and has two consecutive lines. + +And one blank line. +ENDDETAILS + ], + // Note this is the summary of the actual bulk mailing text. The above details are a bit irrelevant for what we're testing here. + 'Text MessageThis
address

is not ours:...
', + ], + + 'email-text' => [ + [ + 'activity_type' => 'Email', + 'url' => 'civicrm/activity/view?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +This is text only +and has two consecutive lines. + +And one blank line. +ENDDETAILS + ], + ' This is text only
and has two consecutive lines.

And one blank line.', + ], + + 'inbound-text' => [ + [ + 'activity_type' => 'Inbound Email', + 'url' => 'civicrm/contact/view/activity?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +This is text only +and has two consecutive lines. + +And one blank line. +ENDDETAILS + ], + 'This is text only
and has two consecutive lines.

And one blank line.
', + ], + + // Now html only + 'meeting-html' => [ + [ + 'activity_type' => 'Meeting', + 'url' => 'civicrm/activity?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +

This is html only

+ +

And it usually looks like this.

+ +

With p's and newlines between the p's.

+ENDDETAILS + ], + '

This is html only

And it usually looks like this.

With p\'s and newlines between the p\'s.

', + ], + + 'bulkemail-html' => [ + [ + 'activity_type' => 'Bulk Email', + 'url' => 'civicrm/activity/view?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +

This is html only

+ +

And it usually looks like this.

+ +

With p's and newlines between the p's.

+ENDDETAILS + ], + // Note this is the summary of the actual bulk mailing text. The above details are a bit irrelevant for what we're testing here. + 'Text MessageThis
address

is not ours:...
', + ], + + 'email-html' => [ + [ + 'activity_type' => 'Email', + 'url' => 'civicrm/activity/view?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +

This is html only

+ +

And it usually looks like this.

+ +

With p's and newlines between the p's.

+ENDDETAILS + ], + '

This is html only

And it usually looks like this.

With p\'s and newlines between the p\'s.

', + ], + + 'inbound-html' => [ + [ + 'activity_type' => 'Inbound Email', + 'url' => 'civicrm/contact/view/activity?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + // This is probably unusual in real life. It would almost always be mixed. But there's nothing to stop custom code from creating these. + 'details' => <<<'ENDDETAILS' +

This is html only

+ +

And it usually looks like this.

+ +

With p's and newlines between the p's.

+ENDDETAILS + ], + '

This is html only

And it usually looks like this.

With p\'s and newlines between the p\'s.

', + ], + + // Now mixed with text first + 'meeting-mixed-text' => [ + [ + 'activity_type' => 'Meeting', + 'url' => 'civicrm/activity?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +-ALTERNATIVE ITEM 0- +This is mixed +and has two consecutive lines. + +And one blank line. +-ALTERNATIVE ITEM 1- +

This is mixed
+and has two consecutive lines.

+ +

And one blank line.

+-ALTERNATIVE END- +ENDDETAILS + ], + 'This is mixed
and has two consecutive lines.

And one blank line.', + ], + + 'bulkemail-mixed-text' => [ + [ + 'activity_type' => 'Bulk Email', + 'url' => 'civicrm/activity/view?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +-ALTERNATIVE ITEM 0- +This is mixed +and has two consecutive lines. + +And one blank line. +-ALTERNATIVE ITEM 1- +

This is mixed
+and has two consecutive lines.

+ +

And one blank line.

+-ALTERNATIVE END- +ENDDETAILS + ], + // Note this is the summary of the actual bulk mailing text. The above details are a bit irrelevant for what we're testing here. + 'Text MessageThis
address

is not ours:...
', + ], + + 'email-mixed-text' => [ + [ + 'activity_type' => 'Email', + 'url' => 'civicrm/activity/view?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +-ALTERNATIVE ITEM 0- +This is mixed +and has two consecutive lines. + +And one blank line. +-ALTERNATIVE ITEM 1- +

This is mixed
+and has two consecutive lines.

+ +

And one blank line.

+-ALTERNATIVE END- +ENDDETAILS + ], + '
This is mixed
and has two consecutive lines.

And one blank line.
', + ], + + 'inbound-mixed-text' => [ + [ + 'activity_type' => 'Inbound Email', + 'url' => 'civicrm/contact/view/activity?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +-ALTERNATIVE ITEM 0- +This is mixed +and has two consecutive lines. + +And one blank line. +-ALTERNATIVE ITEM 1- +

This is mixed
+and has two consecutive lines.

+ +

And one blank line.

+-ALTERNATIVE END- +ENDDETAILS + ], + '
This is mixed
and has two consecutive lines.

And one blank line.
', + ], + + // Now mixed with html first + 'meeting-mixed-html' => [ + [ + 'activity_type' => 'Meeting', + 'url' => 'civicrm/activity?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +-ALTERNATIVE ITEM 0- +

This is mixed
+and has two consecutive lines.

+ +

And one blank line.

+-ALTERNATIVE ITEM 1- +This is mixed +and has two consecutive lines. + +And one blank line. +-ALTERNATIVE END- +ENDDETAILS + ], + '

This is mixed
and has two consecutive lines.

And one blank line.

', + ], + + 'bulkemail-mixed-html' => [ + [ + 'activity_type' => 'Bulk Email', + 'url' => 'civicrm/activity/view?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +-ALTERNATIVE ITEM 0- +

This is mixed
+and has two consecutive lines.

+ +

And one blank line.

+-ALTERNATIVE ITEM 1- +This is mixed +and has two consecutive lines. + +And one blank line. +-ALTERNATIVE END- +ENDDETAILS + ], + // Note this is the summary of the actual bulk mailing text. The above details are a bit irrelevant for what we're testing here. + 'Text MessageThis
address

is not ours:...
', + ], + + 'email-mixed-html' => [ + [ + 'activity_type' => 'Email', + 'url' => 'civicrm/activity/view?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +-ALTERNATIVE ITEM 0- +

This is mixed
+and has two consecutive lines.

+ +

And one blank line.

+-ALTERNATIVE ITEM 1- +This is mixed +and has two consecutive lines. + +And one blank line. +-ALTERNATIVE END- +ENDDETAILS + ], + '

This is mixed
and has two consecutive lines.

And one blank line.

', + ], + + 'inbound-mixed-html' => [ + [ + 'activity_type' => 'Inbound Email', + 'url' => 'civicrm/contact/view/activity?atype=%%atype%%&action=view&reset=1&id=%%id%%&cid=%%cid%%&context=activity', + 'details' => <<<'ENDDETAILS' +-ALTERNATIVE ITEM 0- +

This is mixed
+and has two consecutive lines.

+ +

And one blank line.

+-ALTERNATIVE ITEM 1- +This is mixed +and has two consecutive lines. + +And one blank line. +-ALTERNATIVE END- +ENDDETAILS + ], + '

This is mixed
and has two consecutive lines.

And one blank line.

', + ], + ]; + + // The output of these is wrong, but they are very rare and it has always + // been wrong, so just skip these tests. But we want them to be present in + // the array because they are used in caseActivityTypesProvider correctly. + $data['meeting-text'][0]['skip'] = TRUE; + $data['meeting-mixed-text'][0]['skip'] = TRUE; + return $data; + } + + /** + * data provider for testNewlinesLookRight() for case activities + * @return array + */ + public function caseActivityTypesProvider(): array { + // We want the same set as non-case, but the url is different, and expected results might change. + $data = $this->activityTypesProvider(); + $newData = []; + foreach ($data as $key => $value) { + $newData['case-' . $key] = $data[$key]; + // The url is always the same for case, despite there being places in + // civi that give a non-case link to the activity, but those are bugs + // IMO since can lead to data loss. + $newData['case-' . $key][0]['url'] = 'civicrm/case/activity/view?reset=1&aid=%%id%%&cid=%%cid%%&caseid=%%caseid%%'; + } + $newData['case-meeting-text'][0]['skip'] = FALSE; + $newData['case-meeting-text'][1] = 'This is text only
and has two consecutive lines.

And one blank line.'; + $newData['case-bulkemail-text'][1] = 'This is text only
and has two consecutive lines.

And one blank line.'; + $newData['case-email-text'][1] = 'This is text only
and has two consecutive lines.

And one blank line.'; + $newData['case-inbound-text'][1] = 'This is text only
and has two consecutive lines.

And one blank line.'; + + $newData['case-meeting-html'][1] = "

This is html only

And it usually looks like this.

With p's and newlines between the p's.

"; + $newData['case-bulkemail-html'][1] = "

This is html only

And it usually looks like this.

With p's and newlines between the p's.

"; + $newData['case-email-html'][1] = "

This is html only

And it usually looks like this.

With p's and newlines between the p's.

"; + $newData['case-inbound-html'][1] = "

This is html only

And it usually looks like this.

With p's and newlines between the p's.

"; + + $newData['case-meeting-mixed-text'][0]['skip'] = FALSE; + $newData['case-meeting-mixed-text'][1] = 'This is mixed
and has two consecutive lines.

And one blank line.'; + $newData['case-bulkemail-mixed-text'][1] = 'This is mixed
and has two consecutive lines.

And one blank line.'; + $newData['case-email-mixed-text'][1] = 'This is mixed
and has two consecutive lines.

And one blank line.'; + $newData['case-inbound-mixed-text'][1] = 'This is mixed
and has two consecutive lines.

And one blank line.'; + + $newData['case-meeting-mixed-html'][1] = '

This is mixed
and has two consecutive lines.

And one blank line.

'; + $newData['case-bulkemail-mixed-html'][1] = '

This is mixed
and has two consecutive lines.

And one blank line.

'; + $newData['case-email-mixed-html'][1] = '

This is mixed
and has two consecutive lines.

And one blank line.

'; + $newData['case-inbound-mixed-html'][1] = '

This is mixed
and has two consecutive lines.

And one blank line.

'; + + return $newData; + } + + /** + * Invoke and preProcess often need these set. + * @param string $url + */ + private function setRequestVars(string $url): void { + $_SERVER['REQUEST_URI'] = $url; + $urlParts = explode('?', $url); + $_GET['q'] = $urlParts[0]; + + $parsed = []; + parse_str($urlParts[1], $parsed); + foreach ($parsed as $param => $value) { + $_GET[$param] = $value; + $_REQUEST[$param] = $value; + } + } + + /** + * @param string $url + */ + private function unsetRequestVars(string $url): void { + unset($_GET['q']); + $urlParts = explode('?', $url); + $parsed = []; + parse_str($urlParts[1], $parsed); + foreach ($parsed as $param => $value) { + unset($_GET[$param], $_REQUEST[$param]); + } + } + } -- 2.25.1