1 /* global $, _, CRM:true */
4 describe('crmCaseType', function() {
14 var defaultAssigneeDefaultValue
;
17 beforeEach(function() {
21 module('crmCaseType');
22 module('crmJsonComparator');
23 inject(function(crmJsonComparator
) {
24 crmJsonComparator
.register(jasmine
);
28 beforeEach(inject(function(_
$controller_
, _
$compile_
, _
$httpBackend_
, _
$q_
, _
$rootScope_
, _
$timeout_
) {
29 $controller
= _
$controller_
;
30 $compile
= _
$compile_
;
31 $httpBackend
= _
$httpBackend_
;
33 $rootScope
= _
$rootScope_
;
34 $timeout
= _
$timeout_
;
37 describe('CaseTypeCtrl', function() {
38 beforeEach(function () {
44 "option_group_id": "25",
57 "option_group_id": "25",
73 "option_group_id": "28",
87 "option_group_id": "28",
104 "option_group_id": "2",
105 "label": "ADC referral",
107 "name": "ADC referral",
118 "option_group_id": "2",
119 "label": "Add Client To Case",
121 "name": "Add Client To Case",
133 "option_group_id": "2",
134 "label": "Open Case",
144 "icon": "fa-folder-open-o"
148 "option_group_id": "2",
149 "label": "Medical evaluation",
151 "name": "Medical evaluation",
166 "name_a_b": "Benefits Specialist is",
167 "label_a_b": "Benefits Specialist is",
168 "name_b_a": "Benefits Specialist",
169 "label_b_a": "Benefits Specialist",
170 "description": "Benefits Specialist",
171 "contact_type_a": "Individual",
172 "contact_type_b": "Individual",
178 "name_a_b": "Case Coordinator is",
179 "label_a_b": "Case Coordinator is",
180 "name_b_a": "Case Coordinator",
181 "label_b_a": "Case Coordinator",
182 "description": "Case Coordinator",
183 "contact_type_a": "Individual",
184 "contact_type_b": "Individual",
190 "name_a_b": "Spouse of",
191 "label_a_b": "Spouse of",
192 "name_b_a": "Spouse of",
193 "label_b_a": "Spouse of",
194 "description": "Spousal relationship.",
195 "contact_type_a": "Individual",
196 "contact_type_b": "Individual",
206 "value": "Benefits Specialist"
210 "value": "Benefits Specialist is"
214 "value": "Case Coordinator"
218 "value": "Case Coordinator is"
228 "name": "housing_support",
229 "title": "Housing Support",
230 "description": "Help homeless individuals obtain temporary and long-term housing",
238 {"name": "Open Case", "max_instances": "1"}
242 "name": "standard_timeline",
243 "label": "Standard Timeline",
248 "status": "Completed"
251 "name": "Medical evaluation",
252 "reference_activity": "Open Case",
253 "reference_offset": "1",
254 "reference_select": "newest"
261 "name": "Homeless Services Coordinator",
268 defaultAssigneeTypes
: {
272 "option_group_id": "152",
285 "option_group_id": "152",
286 "label": "By relationship to workflow client",
288 "name": "BY_RELATIONSHIP",
298 "option_group_id": "152",
299 "label": "Specific contact",
301 "name": "SPECIFIC_CONTACT",
311 "option_group_id": "152",
312 "label": "User creating the workflow",
314 "name": "USER_CREATING_THE_CASE",
325 defaultAssigneeDefaultValue
= _
.find(apiCalls
.defaultAssigneeTypes
.values
, { is_default
: '1' });
326 scope
= $rootScope
.$new();
327 ctrl
= $controller('CaseTypeCtrl', {$scope
: scope
, apiCalls
: apiCalls
});
330 it('should load activity statuses', function() {
331 expect(scope
.activityStatuses
).toEqualData(apiCalls
.actStatuses
.values
);
334 it('should load activity types', function() {
335 expect(scope
.activityTypes
['ADC referral']).toEqualData(apiCalls
.actTypes
.values
[0]);
338 it('should store the default assignee types', function() {
339 expect(scope
.defaultAssigneeTypes
).toBe(apiCalls
.defaultAssigneeTypes
.values
);
342 it('should store the default assignee types values indexed by name', function() {
343 var defaultAssigneeTypeValues
= _
.chain(apiCalls
.defaultAssigneeTypes
.values
)
344 .indexBy('name').mapValues('value').value();
346 expect(scope
.defaultAssigneeTypeValues
).toEqual(defaultAssigneeTypeValues
);
349 it('should store the default assignee relationship type options', function() {
350 var defaultRelationshipTypeOptions
= _
.transform(apiCalls
.relTypes
.values
, function(result
, relType
) {
351 var isBidirectionalRelationship
= relType
.label_a_b
=== relType
.label_b_a
;
354 label
: relType
.label_b_a
,
355 value
: relType
.id
+ '_b_a'
358 if (!isBidirectionalRelationship
) {
360 label
: relType
.label_a_b
,
361 value
: relType
.id
+ '_a_b'
366 expect(scope
.defaultRelationshipTypeOptions
).toEqual(defaultRelationshipTypeOptions
);
369 it('addActivitySet should add an activitySet to the case type', function() {
370 scope
.addActivitySet('timeline');
371 var activitySets
= scope
.caseType
.definition
.activitySets
;
372 var newSet
= activitySets
[activitySets
.length
- 1];
373 expect(newSet
.name
).toBe('timeline_1');
374 expect(newSet
.timeline
).toBe('1');
375 expect(newSet
.label
).toBe('Timeline');
378 it('addActivitySet handles second timeline correctly', function() {
379 scope
.addActivitySet('timeline');
380 scope
.addActivitySet('timeline');
381 var activitySets
= scope
.caseType
.definition
.activitySets
;
382 var newSet
= activitySets
[activitySets
.length
- 1];
383 expect(newSet
.name
).toBe('timeline_2');
384 expect(newSet
.timeline
).toBe('1');
385 expect(newSet
.label
).toBe('Timeline #2');
388 describe('when clearing the activity\'s default assignee type values', function() {
391 beforeEach(function() {
393 default_assignee_relationship
: 1,
394 default_assignee_contact
: 2
397 scope
.clearActivityDefaultAssigneeValues(activity
);
400 it('clears the default assignee relationship for the activity', function() {
401 expect(activity
.default_assignee_relationship
).toBe(null);
404 it('clears the default assignee contact for the activity', function() {
405 expect(activity
.default_assignee_contact
).toBe(null);
409 describe('when adding a new activity to a set', function() {
412 beforeEach(function() {
413 activitySet
= { activityTypes
: [] };
414 scope
.activityTypes
= { comment
: { label
: 'Add a new comment' } };
416 scope
.addActivity(activitySet
, 'comment');
419 it('adds a new Comment activity to the set', function() {
420 expect(activitySet
.activityTypes
[0]).toEqual({
422 label
: scope
.activityTypes
.comment
.label
,
424 reference_activity
: 'Open Case',
425 reference_offset
: '1',
426 reference_select
: 'newest',
427 default_assignee_type
: defaultAssigneeDefaultValue
.value
432 describe('when creating a new workflow', function() {
433 beforeEach(inject(function ($controller
) {
434 apiCalls
.caseType
= null;
436 ctrl
= $controller('CaseTypeCtrl', {$scope
: scope
, apiCalls
: apiCalls
});
439 it('sets default values for the case type title, name, and active status', function() {
440 expect(scope
.caseType
).toEqual(jasmine
.objectContaining({
447 it('adds an Open Case activty to the default activty set', function() {
448 expect(scope
.caseType
.definition
.activitySets
[0].activityTypes
).toEqual([{
452 default_assignee_type
: defaultAssigneeDefaultValue
.value
458 describe('crmAddName', function () {
461 beforeEach(function() {
462 scope
= $rootScope
.$new();
463 scope
.activityTypeOptions
= [1, 2, 3];
464 element
= '<span crm-add-name crm-options="activityTypeOptions"></span>';
466 spyOn(CRM
.$.fn
, 'crmSelect2').and
.callThrough();
468 element
= $compile(element
)(scope
);
472 describe('when initialized', function () {
475 beforeEach (function () {
476 var dataFunction
= CRM
.$.fn
.crmSelect2
.calls
.argsFor(0)[0].data
;
477 returnValue
= dataFunction();
480 it('updates the UI with updated value of scope variable', function () {
481 expect(returnValue
).toEqual({ results
: scope
.activityTypeOptions
});
486 describe('crmEditableTabTitle', function () {
487 var element
, titleLabel
, penIcon
, saveButton
, cancelButton
;
489 beforeEach(function() {
490 scope
= $rootScope
.$new();
491 element
= '<div crm-editable-tab-title title="Click to edit">' +
492 '<span>{{ activitySet.label }}</span>' +
495 scope
.activitySet
= { label
: 'Title'};
496 element
= $compile(element
)(scope
);
498 titleLabel
= $(element
).find('span');
499 penIcon
= $(element
).find('i.fa-pencil');
500 saveButton
= $(element
).find('button[type=button]');
501 cancelButton
= $(element
).find('button[type=cancel]');
506 describe('when initialized', function () {
507 it('hides the save and cancel button', function () {
508 expect(saveButton
.parent().css('display') === 'none').toBe(true);
509 expect(cancelButton
.parent().css('display') === 'none').toBe(true);
513 describe('when clicked on title label', function () {
514 beforeEach(function () {
518 it('hides the pen icon', function () {
519 expect(penIcon
.css('display') === 'none').toBe(true);
522 it('shows the save button', function () {
523 expect(saveButton
.parent().css('display') !== 'none').toBe(true);
526 it('makes the title editable', function () {
527 expect(titleLabel
.attr('contenteditable')).toBe('true');
531 describe('when clicked outside of the editable area', function () {
532 beforeEach(function () {
534 titleLabel
.text('Updated Title');
540 it('shows the pen icon', function () {
541 expect(penIcon
.css('display') !== 'none').toBe(true);
544 it('hides the save and cancel button', function () {
545 expect(saveButton
.parent().css('display') === 'none').toBe(true);
546 expect(cancelButton
.parent().css('display') === 'none').toBe(true);
549 it('makes the title non editable', function () {
550 expect(titleLabel
.attr('contenteditable')).not
.toBe('true');
553 it('does not update the title in angular context', function () {
554 expect(scope
.activitySet
.label
).toBe('Title');
558 describe('when ESCAPE key is pressed while typing', function () {
559 beforeEach(function () {
560 var eventObj
= $.Event('keydown');
561 eventObj
.key
= 'Escape';
564 titleLabel
.text('Updated Title');
565 titleLabel
.trigger(eventObj
);
569 it('shows the pen icon', function () {
570 expect(penIcon
.css('display') !== 'none').toBe(true);
573 it('hides the save and cancel button', function () {
574 expect(saveButton
.parent().css('display') === 'none').toBe(true);
575 expect(cancelButton
.parent().css('display') === 'none').toBe(true);
578 it('makes the title non editable', function () {
579 expect(titleLabel
.attr('contenteditable')).not
.toBe('true');
582 it('does not update the title', function () {
583 expect(scope
.activitySet
.label
).toBe('Title');
587 describe('when ENTER key is pressed while typing', function () {
588 beforeEach(function () {
589 var eventObj
= $.Event('keydown');
590 eventObj
.key
= 'Enter';
593 titleLabel
.text('Updated Title');
594 titleLabel
.trigger(eventObj
);
598 it('shows the pen icon', function () {
599 expect(penIcon
.css('display') !== 'none').toBe(true);
602 it('hides the save and cancel button', function () {
603 expect(saveButton
.parent().css('display') === 'none').toBe(true);
604 expect(cancelButton
.parent().css('display') === 'none').toBe(true);
607 it('makes the title non editable', function () {
608 expect(titleLabel
.attr('contenteditable')).not
.toBe('true');
611 it('updates the title in angular context', function () {
612 expect(scope
.activitySet
.label
).toBe('Updated Title');
616 describe('when SAVE button is clicked', function () {
617 beforeEach(function () {
619 titleLabel
.text('Updated Title');
624 it('shows the pen icon', function () {
625 expect(penIcon
.css('display') !== 'none').toBe(true);
628 it('hides the save and cancel button', function () {
629 expect(saveButton
.parent().css('display') === 'none').toBe(true);
630 expect(cancelButton
.parent().css('display') === 'none').toBe(true);
633 it('makes the title non editable', function () {
634 expect(titleLabel
.attr('contenteditable')).not
.toBe('true');
637 it('updates the title in angular context', function () {
638 expect(scope
.activitySet
.label
).toBe('Updated Title');
642 describe('when CANCEL button is clicked', function () {
643 beforeEach(function () {
645 titleLabel
.text('Updated Title');
646 cancelButton
.click();
650 it('shows the pen icon', function () {
651 expect(penIcon
.css('display') !== 'none').toBe(true);
654 it('hides the save and cancel button', function () {
655 expect(saveButton
.parent().css('display') === 'none').toBe(true);
656 expect(cancelButton
.parent().css('display') === 'none').toBe(true);
659 it('makes the title non editable', function () {
660 expect(titleLabel
.attr('contenteditable')).not
.toBe('true');
663 it('does not update the title in angular context', function () {
664 expect(scope
.activitySet
.label
).toBe('Title');
669 describe('CaseTypeListCtrl', function() {
670 var caseTypes
, crmApiSpy
;
672 beforeEach(function() {
680 crmApiSpy
= jasmine
.createSpy('crmApi').and
.returnValue($q
.resolve());
681 scope
= $rootScope
.$new();
682 ctrl
= $controller('CaseTypeListCtrl', {
684 caseTypes
: caseTypes
,
689 it('should store an index of case types', function() {
690 expect(scope
.caseTypes
).toEqual(caseTypes
.values
);
693 describe('toggleCaseType', function() {
694 var caseType
= { id
: _
.uniqueId() };
696 describe('when the case is active', function() {
697 beforeEach(function() {
698 caseType
.is_active
= '1';
700 scope
.toggleCaseType(caseType
);
703 it('sets the case type as inactive', function() {
704 expect(crmApiSpy
).toHaveBeenCalledWith('CaseType', 'create', jasmine
.objectContaining({
711 describe('when the case is inactive', function() {
712 beforeEach(function() {
713 caseType
.is_active
= '0';
715 scope
.toggleCaseType(caseType
);
718 it('sets the case type as active', function() {
719 expect(crmApiSpy
).toHaveBeenCalledWith('CaseType', 'create', jasmine
.objectContaining({
727 describe('deleteCaseType', function() {
728 var caseType
= { id
: _
.uniqueId() };
730 beforeEach(function() {
731 crmApiSpy
.and
.returnValue($q
.resolve(caseType
));
732 scope
.caseTypes
[caseType
.id
] = caseType
;
734 scope
.deleteCaseType(caseType
);
738 describe('when the case type can be deleted', function() {
739 it('deletes the case from the api', function() {
740 expect(crmApiSpy
).toHaveBeenCalledWith('CaseType', 'delete', { id
: caseType
.id
}, jasmine
.any(Object
));
743 it('removes the case type from the list', function() {
744 expect(scope
.caseTypes
[caseType
.id
]).toBeUndefined();
748 describe('when the case type cannot be delted', function() {
749 var error
= { error_message
: 'Error Message' };
751 beforeEach(function() {
754 crmApiSpy
.and
.returnValue($q
.reject(error
));
755 scope
.caseTypes
[caseType
.id
] = caseType
;
758 scope
.deleteCaseType(caseType
);
761 errorHandler
= crmApiSpy
.calls
.mostRecent().args
[3].error
;
765 it('displays the error message', function() {
766 expect(CRM
.alert
).toHaveBeenCalledWith(error
.error_message
, 'Error', 'error');
770 describe('revertCaseType', function() {
777 describe('when reverting a case type', function() {
778 beforeEach(function() {
779 scope
.revertCaseType(caseType
);
782 it('resets the case type information using the api', function() {
783 expect(crmApiSpy
).toHaveBeenCalledWith('CaseType', 'create', jasmine
.objectContaining({