Merge pull request #15884 from kainuk/issue-lab-1365
[civicrm-core.git] / tests / phpunit / CRM / Case / XMLProcessor / ReportTest.php
1 <?php
2 require_once 'CiviTest/CiviCaseTestCase.php';
3
4 /**
5 * Class CRM_Case_XMLProcessor_ReportTest
6 * @group headless
7 */
8 class CRM_Case_XMLProcessor_ReportTest extends CiviCaseTestCase {
9
10 public function setUp() {
11 parent::setUp();
12
13 $this->simplifyCaseTypeDefinition();
14
15 $this->report = new CRM_Case_XMLProcessor_Report();
16 }
17
18 public function tearDown() {
19 parent::tearDown();
20 }
21
22 /**
23 * Test that getCaseReport has the right output.
24 *
25 * @param $activitySetName string Also acts as data provider test identifier.
26 * @param $expected array
27 *
28 * @dataProvider caseReportDataProvider
29 */
30 public function testGetCaseReport($activitySetName, $expected) {
31 $client_id = $this->individualCreate([
32 'first_name' => 'Casey',
33 'middle_name' => '',
34 'last_name' => 'Reportee',
35 'prefix_id' => NULL,
36 'suffix_id' => NULL,
37 ]);
38 $caseObj = $this->createCase($client_id, $this->_loggedInUser);
39 $case_id = $caseObj->id;
40
41 // Add an additional meeting activity not in the timeline to the case.
42 $meetingTypeId = $this->callAPISuccess('OptionValue', 'getsingle', [
43 'return' => ["value"],
44 'option_group_id' => 'activity_type',
45 'name' => 'Meeting',
46 ]);
47 $this->callAPISuccess('activity', 'create', [
48 'case_id' => $case_id,
49 'activity_type_id' => $meetingTypeId['value'],
50 'activity_date_time' => '20191114123456',
51 'subject' => 'Test Meeting',
52 'source_contact_id' => $this->_loggedInUser,
53 'target_contact_id' => $client_id,
54 ]);
55
56 $caseReportParams = [
57 'is_redact' => FALSE,
58 'include_activities' => 1,
59 ];
60
61 // run the thing we're testing and get the output vars
62 $template = CRM_Case_XMLProcessor_Report::populateCaseReportTemplate($client_id, $case_id, $activitySetName, $caseReportParams, $this->report);
63 $assigned_vars = $template->get_template_vars();
64
65 // Update $expected now since dataprovider doesn't have access to the variables from setup() because it runs before setup.
66 $this->updateExpectedBecauseDataProviderEvaluatesBeforeEverything($expected, $client_id, $case_id);
67
68 foreach ($expected as $key => $value) {
69 // does the assigned template var match the expected value?
70 $this->assertEquals($value, $assigned_vars[$key], "$activitySetName: $key does not match" . print_r($assigned_vars[$key], TRUE));
71 }
72 }
73
74 /**
75 * This is similar to testGetCaseReport but test with a timeline that
76 * does have Meeting in it.
77 */
78 public function testGetCaseReportWithMeetingInTimeline() {
79 $client_id = $this->individualCreate([
80 'first_name' => 'Casey',
81 'middle_name' => '',
82 'last_name' => 'Reportee',
83 'prefix_id' => NULL,
84 'suffix_id' => NULL,
85 ]);
86 $caseObj = $this->createCase($client_id, $this->_loggedInUser);
87 $case_id = $caseObj->id;
88
89 // Now update the timeline so it has Meeting in it.
90 $this->addMeetingToTimeline();
91
92 // Add a meeting activity to the case.
93 $meetingTypeId = $this->callAPISuccess('OptionValue', 'getsingle', [
94 'return' => ["value"],
95 'option_group_id' => 'activity_type',
96 'name' => 'Meeting',
97 ]);
98 $this->callAPISuccess('activity', 'create', [
99 'case_id' => $case_id,
100 'activity_type_id' => $meetingTypeId['value'],
101 'activity_date_time' => '20191114123456',
102 'subject' => 'Test Meeting',
103 'source_contact_id' => $this->_loggedInUser,
104 'target_contact_id' => $client_id,
105 ]);
106
107 $caseReportParams = [
108 'is_redact' => FALSE,
109 'include_activities' => 1,
110 ];
111
112 // run the thing we're testing and get the output vars
113 $template = CRM_Case_XMLProcessor_Report::populateCaseReportTemplate($client_id, $case_id, 'standard_timeline', $caseReportParams, $this->report);
114 $assigned_vars = $template->get_template_vars();
115
116 // We don't want to run all the data in the dataprovider but we know
117 // in this case it should be the same as the second one in the
118 // dataprovider so we can reuse it.
119 $expected = $this->caseReportDataProvider()[1][1];
120 $this->updateExpectedBecauseDataProviderEvaluatesBeforeEverything($expected, $client_id, $case_id);
121
122 foreach ($expected as $key => $value) {
123 // does the assigned template var match the expected value?
124 $this->assertEquals($value, $assigned_vars[$key], "$key does not match" . print_r($assigned_vars[$key], TRUE));
125 }
126 }
127
128 /**
129 * Data provider for testGetCaseReport
130 * @return array
131 */
132 public function caseReportDataProvider() {
133 return [
134 [
135 // activity set name
136 'standard_timeline',
137 // Some expected assigned vars of CRM_Core_Smarty template.
138 // In particular we shouldn't have meeting in the output since it's
139 // not in the timeline.
140 [
141 'case' => [
142 'clientName' => 'Casey Reportee',
143 'subject' => 'Case Subject',
144 'start_date' => '2019-11-14',
145 'end_date' => NULL,
146 'caseType' => 'Housing Support',
147 'caseTypeName' => 'housing_support',
148 'status' => 'Ongoing',
149 ],
150 'activities' => [
151 0 => [
152 'fields' => [
153 0 => [
154 'label' => 'Client',
155 'value' => 'Casey Reportee',
156 'type' => 'String',
157 ],
158 1 => [
159 'label' => 'Activity Type',
160 'value' => 'Open Case',
161 'type' => 'String',
162 ],
163 2 => [
164 'label' => 'Subject',
165 'value' => 'Case Subject',
166 'type' => 'Memo',
167 ],
168 3 => [
169 'label' => 'Created By',
170 // data providers run before everything, so update this later
171 'value' => 'placeholder',
172 'type' => 'String',
173 ],
174 4 => [
175 'label' => 'Reported By',
176 // see above - need to update this later
177 'value' => 'placeholder',
178 'type' => 'String',
179 ],
180 5 => [
181 'label' => 'Medium',
182 'value' => 'Phone',
183 'type' => 'String',
184 ],
185 6 => [
186 'label' => 'Location',
187 'value' => NULL,
188 'type' => 'String',
189 ],
190 7 => [
191 'label' => 'Date and Time',
192 'value' => '2019-11-14 00:00:00',
193 'type' => 'Date',
194 ],
195 8 => [
196 'label' => 'Details',
197 'value' => NULL,
198 'type' => 'Memo',
199 ],
200 9 => [
201 'label' => 'Status',
202 'value' => 'Completed',
203 'type' => 'String',
204 ],
205 10 => [
206 'label' => 'Priority',
207 'value' => 'Normal',
208 'type' => 'String',
209 ],
210 ],
211 'editURL' => 'placeholder',
212 'customGroups' => NULL,
213 ],
214 1 => [
215 'fields' => [
216 0 => [
217 'label' => 'Client',
218 'value' => 'Casey Reportee',
219 'type' => 'String',
220 ],
221 1 => [
222 'label' => 'Activity Type',
223 'value' => 'Medical evaluation',
224 'type' => 'String',
225 ],
226 2 => [
227 'label' => 'Subject',
228 'value' => '',
229 'type' => 'Memo',
230 ],
231 3 => [
232 'label' => 'Created By',
233 // see above - need to update this later
234 'value' => 'placeholder',
235 'type' => 'String',
236 ],
237 4 => [
238 'label' => 'Reported By',
239 // see above - need to update this later
240 'value' => 'placeholder',
241 'type' => 'String',
242 ],
243 5 => [
244 'label' => 'Location',
245 'value' => NULL,
246 'type' => 'String',
247 ],
248 6 => [
249 'label' => 'Date and Time',
250 'value' => '2019-11-15 00:00:00',
251 'type' => 'Date',
252 ],
253 7 => [
254 'label' => 'Details',
255 'value' => NULL,
256 'type' => 'Memo',
257 ],
258 8 => [
259 'label' => 'Status',
260 'value' => 'Scheduled',
261 'type' => 'String',
262 ],
263 9 => [
264 'label' => 'Priority',
265 'value' => 'Normal',
266 'type' => 'String',
267 ],
268 ],
269 'editURL' => 'placeholder',
270 'customGroups' => NULL,
271 ],
272 ],
273 ],
274 ],
275 [
276 // activity set name is blank here, meaning don't filter the activities
277 '',
278 // Some expected assigned vars of CRM_Core_Smarty template.
279 // In particular now we will have Meeting in the output.
280 [
281 'case' => [
282 'clientName' => 'Casey Reportee',
283 'subject' => 'Case Subject',
284 'start_date' => '2019-11-14',
285 'end_date' => NULL,
286 'caseType' => 'Housing Support',
287 'caseTypeName' => 'housing_support',
288 'status' => 'Ongoing',
289 ],
290 'activities' => [
291 0 => [
292 'fields' => [
293 0 => [
294 'label' => 'Client',
295 'value' => 'Casey Reportee',
296 'type' => 'String',
297 ],
298 1 => [
299 'label' => 'Activity Type',
300 'value' => 'Open Case',
301 'type' => 'String',
302 ],
303 2 => [
304 'label' => 'Subject',
305 'value' => 'Case Subject',
306 'type' => 'Memo',
307 ],
308 3 => [
309 'label' => 'Created By',
310 // data providers run before everything, so update this later
311 'value' => 'placeholder',
312 'type' => 'String',
313 ],
314 4 => [
315 'label' => 'Reported By',
316 // see above - need to update this later
317 'value' => 'placeholder',
318 'type' => 'String',
319 ],
320 5 => [
321 'label' => 'Medium',
322 'value' => 'Phone',
323 'type' => 'String',
324 ],
325 6 => [
326 'label' => 'Location',
327 'value' => NULL,
328 'type' => 'String',
329 ],
330 7 => [
331 'label' => 'Date and Time',
332 'value' => '2019-11-14 00:00:00',
333 'type' => 'Date',
334 ],
335 8 => [
336 'label' => 'Details',
337 'value' => NULL,
338 'type' => 'Memo',
339 ],
340 9 => [
341 'label' => 'Status',
342 'value' => 'Completed',
343 'type' => 'String',
344 ],
345 10 => [
346 'label' => 'Priority',
347 'value' => 'Normal',
348 'type' => 'String',
349 ],
350 ],
351 'editURL' => 'placeholder',
352 'customGroups' => NULL,
353 ],
354 1 => [
355 'fields' => [
356 0 => [
357 'label' => 'Client',
358 'value' => 'Casey Reportee',
359 'type' => 'String',
360 ],
361 1 => [
362 'label' => 'Activity Type',
363 'value' => 'Medical evaluation',
364 'type' => 'String',
365 ],
366 2 => [
367 'label' => 'Subject',
368 'value' => '',
369 'type' => 'Memo',
370 ],
371 3 => [
372 'label' => 'Created By',
373 // see above - need to update this later
374 'value' => 'placeholder',
375 'type' => 'String',
376 ],
377 4 => [
378 'label' => 'Reported By',
379 // see above - need to update this later
380 'value' => 'placeholder',
381 'type' => 'String',
382 ],
383 5 => [
384 'label' => 'Location',
385 'value' => NULL,
386 'type' => 'String',
387 ],
388 6 => [
389 'label' => 'Date and Time',
390 'value' => '2019-11-15 00:00:00',
391 'type' => 'Date',
392 ],
393 7 => [
394 'label' => 'Details',
395 'value' => NULL,
396 'type' => 'Memo',
397 ],
398 8 => [
399 'label' => 'Status',
400 'value' => 'Scheduled',
401 'type' => 'String',
402 ],
403 9 => [
404 'label' => 'Priority',
405 'value' => 'Normal',
406 'type' => 'String',
407 ],
408 ],
409 'editURL' => 'placeholder',
410 'customGroups' => NULL,
411 ],
412 2 => [
413 'fields' => [
414 0 => [
415 'label' => 'Client',
416 'value' => 'Casey Reportee',
417 'type' => 'String',
418 ],
419 1 => [
420 'label' => 'Activity Type',
421 'value' => 'Meeting',
422 'type' => 'String',
423 ],
424 2 => [
425 'label' => 'Subject',
426 'value' => 'Test Meeting',
427 'type' => 'Memo',
428 ],
429 3 => [
430 'label' => 'Created By',
431 // see above - need to update this later
432 'value' => 'placeholder',
433 'type' => 'String',
434 ],
435 4 => [
436 'label' => 'Reported By',
437 // see above - need to update this later
438 'value' => 'placeholder',
439 'type' => 'String',
440 ],
441 5 => [
442 'label' => 'Location',
443 'value' => NULL,
444 'type' => 'String',
445 ],
446 6 => [
447 'label' => 'Date and Time',
448 'value' => '2019-11-14 12:34:56',
449 'type' => 'Date',
450 ],
451 7 => [
452 'label' => 'Details',
453 'value' => NULL,
454 'type' => 'Memo',
455 ],
456 8 => [
457 'label' => 'Status',
458 'value' => 'Completed',
459 'type' => 'String',
460 ],
461 9 => [
462 'label' => 'Priority',
463 'value' => 'Normal',
464 'type' => 'String',
465 ],
466 ],
467 'editURL' => 'placeholder',
468 'customGroups' => NULL,
469 ],
470 ],
471 ],
472 ],
473 ];
474 }
475
476 /**
477 * Since data providers get evaluated before setup and other variable
478 * assignments, we call this during the test to update placeholders we set
479 * in the data provider.
480 * Maybe it doesn't really make sense to use a data provider here, but kinda.
481 *
482 * @param &$expected array Contains the placeholders to update.
483 * @param $client_id int
484 * @param $case_id int
485 */
486 private function updateExpectedBecauseDataProviderEvaluatesBeforeEverything(&$expected, $client_id, $case_id) {
487 $display_name = $this->callAPISuccess('Contact', 'getsingle', [
488 'return' => ["display_name"],
489 'id' => $this->_loggedInUser,
490 ]);
491
492 foreach ($expected['activities'] as $idx => $activity) {
493 $expected['activities'][$idx]['fields'][3]['value'] = $display_name['display_name'];
494 $expected['activities'][$idx]['fields'][4]['value'] = $display_name['display_name'];
495
496 $activityTypeId = $this->callAPISuccess('OptionValue', 'getsingle', [
497 'return' => ["value"],
498 'option_group_id' => 'activity_type',
499 'name' => $expected['activities'][$idx]['fields'][1]['value'],
500 ]);
501 $expected['activities'][$idx]['editURL'] = CRM_Utils_System::url('civicrm/case/activity', "reset=1&cid={$client_id}&caseid={$case_id}&action=update&atype={$activityTypeId['value']}&id=" . ($idx + 1));
502 }
503 }
504
505 /**
506 * Create and return a new case object.
507 * @param $clientId
508 * @param $loggedInUser
509 * @return CRM_Case_BAO_Case
510 */
511 private function createCase($clientId, $loggedInUser) {
512 $caseParams = [
513 'activity_subject' => 'Case Subject',
514 'client_id' => $clientId,
515 'case_type_id' => $this->caseTypeId,
516 'status_id' => 1,
517 'case_type' => $this->caseType,
518 'subject' => 'Case Subject',
519 'start_date' => '2019-11-14',
520 'start_date_time' => '20191114000000',
521 'medium_id' => 2,
522 'activity_details' => '',
523 ];
524 $form = new CRM_Case_Form_Case();
525 $caseObj = $form->testSubmit($caseParams, "OpenCase", $loggedInUser, "standalone");
526 return $caseObj;
527 }
528
529 /**
530 * We don't need so many activities as in the stock case type. Just makes
531 * dataprovider unnecessarily long. Just take the first two.
532 * @return void
533 */
534 private function simplifyCaseTypeDefinition() {
535 $caseType = $this->callAPISuccess('CaseType', 'getsingle', ['id' => $this->caseTypeId]);
536 $newActivitySet = array_slice($caseType['definition']['activitySets'][0]['activityTypes'], 0, 2);
537 $caseType['definition']['activitySets'][0]['activityTypes'] = $newActivitySet;
538 $this->callAPISuccess('CaseType', 'create', $caseType);
539 }
540
541 /**
542 * Add Meeting to the standard timeline.
543 */
544 private function addMeetingToTimeline() {
545 $caseType = $this->callAPISuccess('CaseType', 'getsingle', ['id' => $this->caseTypeId]);
546 $activityTypes = $caseType['definition']['activitySets'][0]['activityTypes'];
547 // Make a copy of the second activity type and change the type.
548 $activityType = $activityTypes[1];
549 $activityType['name'] = 'Meeting';
550 $activityType['label'] = 'Meeting';
551
552 $activityTypes[] = $activityType;
553 $caseType['definition']['activitySets'][0]['activityTypes'] = $activityTypes;
554 $this->callAPISuccess('CaseType', 'create', $caseType);
555 }
556
557 }