def test_used_types(self): # given bucharest = GeographicRegion.objects.get(slug='bucharest') romania = GeographicRegion.objects.get(slug='romania') service_type = ServiceType.objects.first() service = ServiceFactory(region=bucharest, status='current') service.types.add(service_type) service.save() # when get_used_types_bucharest = self.api_client.get( path='/v2/custom-servicetypes/used_types/?geographic_region=' + bucharest.slug, format='json') self.assertEqual(get_used_types_bucharest.status_code, 200) get_used_types_romania = self.api_client.get( path='/v2/custom-servicetypes/used_types/?geographic_region=' + romania.slug, format='json') self.assertEqual(get_used_types_romania.status_code, 200) # then used_types_bucharest = json.loads(get_used_types_bucharest.content.decode('utf-8')) self.assertEqual(len(used_types_bucharest), 1) used_types_romania = json.loads(get_used_types_romania.content.decode('utf-8')) self.assertEqual(len(used_types_romania), 1)
class IndexingTest(TestCase): def setUp(self): self.service_ar = ServiceFactory(name_ar='Arabic', name_en='', name_fr='', description_ar='language-of-Egypt', status=Service.STATUS_CURRENT) self.service_ar.save() self.service_en = ServiceFactory( name_en='English', name_ar='', name_fr='', description_en='language-of-Australia', status=Service.STATUS_CURRENT) self.service_en.save() self.service_fr = ServiceFactory(name_fr='French', name_ar='', name_en='', description_fr='language-of-France', status=Service.STATUS_CURRENT) self.service_fr.save() self.rejected_service_fr = ServiceFactory( name_fr='InactiveParis', name_ar='', name_en='', status=Service.STATUS_REJECTED) self.rejected_service_fr.save() def test_querysets(self): index = ServiceIndex() self.assertIn(self.service_ar, index.get_index_queryset('ar')) self.assertNotIn(self.service_ar, index.get_index_queryset('en')) self.assertIn(self.service_fr, index.get_index_queryset('fr')) self.assertNotIn(self.service_fr, index.get_index_queryset('ar')) self.assertNotIn(self.rejected_service_fr, index.get_index_queryset('fr')) def test_search_data(self): index = ServiceIndex() ar_data = index.get_search_data(self.service_ar, 'ar', None) self.assertIn('Egypt', ar_data) en_data = index.get_search_data(self.service_en, 'en', None) self.assertIn('Australia', en_data)
class IndexingTest(TestCase): def setUp(self): self.service_ar = ServiceFactory( name_ar='Arabic', name_en='', name_fr='', description_ar='language-of-Egypt', status=Service.STATUS_CURRENT ) self.service_ar.save() self.service_en = ServiceFactory( name_en='English', name_ar='', name_fr='', description_en='language-of-Australia', status=Service.STATUS_CURRENT ) self.service_en.save() self.service_fr = ServiceFactory( name_fr='French', name_ar='', name_en='', description_fr='language-of-France', status=Service.STATUS_CURRENT ) self.service_fr.save() self.rejected_service_fr = ServiceFactory( name_fr='InactiveParis', name_ar='', name_en='', status=Service.STATUS_REJECTED ) self.rejected_service_fr.save() def test_querysets(self): index = ServiceIndex() self.assertIn(self.service_ar, index.get_index_queryset('ar')) self.assertNotIn(self.service_ar, index.get_index_queryset('en')) self.assertIn(self.service_fr, index.get_index_queryset('fr')) self.assertNotIn(self.service_fr, index.get_index_queryset('ar')) self.assertNotIn(self.rejected_service_fr, index.get_index_queryset('fr')) def test_search_data(self): index = ServiceIndex() ar_data = index.get_search_data(self.service_ar, 'ar', None) self.assertIn('Egypt', ar_data) en_data = index.get_search_data(self.service_en, 'en', None) self.assertIn('Australia', en_data)
class ServiceAdminTest(TestCase): def setUp(self): self.service = ServiceFactory(status=Service.STATUS_DRAFT, location="POINT (33.0000 35.0000)") self.password = '******' self.user = EmailUserFactory(is_staff=True, password=self.password) assert self.user.is_staff group = Group.objects.get(name='Staff') self.user.groups.add(group) assert self.user.has_perm('services.change_service') assert self.client.login(email=self.user.email, password=self.password) def test_permissions(self): # Must have Staff group to access services in the admin self.user.groups.remove(Group.objects.get(name='Staff')) rsp = self.client.get( reverse('admin:services_service_change', args=[self.service.pk])) self.assertEqual(403, rsp.status_code) rsp = self.save_service_in_form() self.assertEqual(403, rsp.status_code) def save_service_in_form(self, **kwargs): """ Simulate loading the service in a change form in the admin, updating some data from **kwargs, and submitting. Returns the response returned by the post. """ data = model_to_dict(self.service) data['location'] = str(data['location']) # inline data data["selection_criteria-TOTAL_FORMS"] = 0 data["selection_criteria-INITIAL_FORMS"] = 0 data["selection_criteria-MIN_NUM_FORMS"] = 0 data["selection_criteria-MAX_NUM_FORMS"] = 0 # Drop any None values data = {k: v for k, v in data.items() if v is not None} # Update with caller data data.update(**kwargs) rsp = self.client.post(reverse('admin:services_service_change', args=[self.service.pk]), data=data) return rsp def test_edit_service(self): # Make a change to the data rsp = self.save_service_in_form(name_en="New service name") self.assertEqual(302, rsp.status_code, msg=rsp.content.decode('utf-8')) service = Service.objects.get(pk=self.service.pk) self.assertEqual("New service name", service.name_en) def test_approve_button(self): rsp = self.save_service_in_form( name_en="New service name", _approve=True, # the button we "clicked" ) self.assertEqual(302, rsp.status_code, msg=rsp.content.decode('utf-8')) service = Service.objects.get(pk=self.service.pk) self.assertEqual("New service name", service.name_en) self.assertEqual(Service.STATUS_CURRENT, service.status) def test_approve_button_with_bad_data(self): rsp = self.save_service_in_form( name_en="New service name", location="not a valid location", _approve=True, # the button we "clicked" ) self.assertEqual(200, rsp.status_code, msg=rsp.content.decode('utf-8')) self.assertIn( '<ul class="errorlist"><li>Invalid geometry value.</li></ul>', rsp.context['errors']) service = Service.objects.get(pk=self.service.pk) self.assertEqual(Service.STATUS_DRAFT, service.status) def test_approve_button_with_missing_data(self): rsp = self.save_service_in_form( name_en="New service name", location='', _approve=True, # the button we "clicked" ) self.assertEqual(200, rsp.status_code, msg=rsp.content.decode('utf-8')) self.assertIn( '<ul class="errorlist"><li>No geometry value provided.</li></ul>', rsp.context['errors']) service = Service.objects.get(pk=self.service.pk) self.assertEqual(Service.STATUS_DRAFT, service.status) def test_reject_button(self): rsp = self.save_service_in_form( name_en="New service name", _reject=True, # the button we "clicked" ) self.assertEqual(302, rsp.status_code, msg=rsp.content.decode('utf-8')) service = Service.objects.get(pk=self.service.pk) self.assertEqual("New service name", service.name_en) self.assertEqual(Service.STATUS_REJECTED, service.status) def test_actions_appear(self): rsp = self.client.get(reverse('admin:services_service_changelist')) self.assertContains(rsp, "Approve new or changed service") self.assertContains(rsp, "Reject new or changed service") def test_buttons_appear(self): rsp = self.client.get( reverse('admin:services_service_change', args=[self.service.pk])) self.assertContains(rsp, "Save and approve") self.assertContains(rsp, "Save and reject") def test_approve_action(self): self.service.validate_for_approval() data = { 'index': '0', # "Go" button 'action': 'approve', # selected action '_selected_action': [ str(self.service.pk), # selected checkbox ] } rsp = self.client.post(reverse('admin:services_service_changelist'), data) self.assertEqual(302, rsp.status_code, msg=rsp.content.decode('utf-8')) new_url = rsp['Location'] rsp = self.client.get(new_url) self.assertEqual(200, rsp.status_code, msg=rsp.content.decode('utf-8')) service = Service.objects.get(pk=self.service.pk) self.assertEqual(Service.STATUS_CURRENT, service.status) def test_reject_action(self): data = { 'index': '0', # "Go" button 'action': 'reject', # selected action '_selected_action': [ str(self.service.pk), # selected checkbox ] } rsp = self.client.post(reverse('admin:services_service_changelist'), data) self.assertEqual(302, rsp.status_code, msg=rsp.content.decode('utf-8')) new_url = rsp['Location'] rsp = self.client.get(new_url) self.assertEqual(200, rsp.status_code, msg=rsp.content.decode('utf-8')) service = Service.objects.get(pk=self.service.pk) self.assertEqual(Service.STATUS_REJECTED, service.status) def test_approve_action_wrong_status(self): self.service.status = Service.STATUS_CURRENT self.service.save() data = { 'index': '0', # "Go" button 'action': 'approve', # selected action '_selected_action': [ str(self.service.pk), # selected checkbox ] } rsp = self.client.post(reverse('admin:services_service_changelist'), data, follow=True) self.assertEqual(200, rsp.status_code) self.assertIn('Only services in draft status may be approved', [str(msg) for msg in rsp.context['messages']]) def test_reject_action_wrong_status(self): self.service.status = Service.STATUS_CURRENT self.service.save() data = { 'index': '0', # "Go" button 'action': 'reject', # selected action '_selected_action': [ str(self.service.pk), # selected checkbox ] } rsp = self.client.post(reverse('admin:services_service_changelist'), data, follow=True) self.assertEqual(200, rsp.status_code) self.assertIn('Only services in draft status may be rejected', [str(msg) for msg in rsp.context['messages']])
class ServiceAdminTest(TestCase): def setUp(self): self.service = ServiceFactory(status=Service.STATUS_DRAFT, location="POINT (33.0000 35.0000)") self.password = '******' self.user = EmailUserFactory(is_staff=True, password=self.password) assert self.user.is_staff group = Group.objects.get(name='Staff') self.user.groups.add(group) assert self.user.has_perm('services.change_service') assert self.client.login(email=self.user.email, password=self.password) def test_permissions(self): # Must have Staff group to access services in the admin self.user.groups.remove(Group.objects.get(name='Staff')) rsp = self.client.get(reverse('admin:services_service_change', args=[self.service.pk])) self.assertEqual(403, rsp.status_code) rsp = self.save_service_in_form() self.assertEqual(403, rsp.status_code) def save_service_in_form(self, **kwargs): """ Simulate loading the service in a change form in the admin, updating some data from **kwargs, and submitting. Returns the response returned by the post. """ data = model_to_dict(self.service) data['location'] = str(data['location']) # inline data data["selection_criteria-TOTAL_FORMS"] = 0 data["selection_criteria-INITIAL_FORMS"] = 0 data["selection_criteria-MIN_NUM_FORMS"] = 0 data["selection_criteria-MAX_NUM_FORMS"] = 0 # Drop any None values data = {k: v for k, v in data.items() if v is not None} # Update with caller data data.update(**kwargs) rsp = self.client.post(reverse('admin:services_service_change', args=[self.service.pk]), data=data) return rsp def test_edit_service(self): # Make a change to the data rsp = self.save_service_in_form(name_en="New service name") self.assertEqual(302, rsp.status_code, msg=rsp.content.decode('utf-8')) service = Service.objects.get(pk=self.service.pk) self.assertEqual("New service name", service.name_en) def test_approve_button(self): rsp = self.save_service_in_form(name_en="New service name", _approve=True, # the button we "clicked" ) self.assertEqual(302, rsp.status_code, msg=rsp.content.decode('utf-8')) service = Service.objects.get(pk=self.service.pk) self.assertEqual("New service name", service.name_en) self.assertEqual(Service.STATUS_CURRENT, service.status) def test_approve_button_with_bad_data(self): rsp = self.save_service_in_form(name_en="New service name", location="not a valid location", _approve=True, # the button we "clicked" ) self.assertEqual(200, rsp.status_code, msg=rsp.content.decode('utf-8')) self.assertIn('<ul class="errorlist"><li>Invalid geometry value.</li></ul>', rsp.context['errors']) service = Service.objects.get(pk=self.service.pk) self.assertEqual(Service.STATUS_DRAFT, service.status) def test_approve_button_with_missing_data(self): rsp = self.save_service_in_form(name_en="New service name", location='', _approve=True, # the button we "clicked" ) self.assertEqual(200, rsp.status_code, msg=rsp.content.decode('utf-8')) self.assertIn('<ul class="errorlist"><li>No geometry value provided.</li></ul>', rsp.context['errors']) service = Service.objects.get(pk=self.service.pk) self.assertEqual(Service.STATUS_DRAFT, service.status) def test_reject_button(self): rsp = self.save_service_in_form(name_en="New service name", _reject=True, # the button we "clicked" ) self.assertEqual(302, rsp.status_code, msg=rsp.content.decode('utf-8')) service = Service.objects.get(pk=self.service.pk) self.assertEqual("New service name", service.name_en) self.assertEqual(Service.STATUS_REJECTED, service.status) def test_actions_appear(self): rsp = self.client.get(reverse('admin:services_service_changelist')) self.assertContains(rsp, "Approve new or changed service") self.assertContains(rsp, "Reject new or changed service") def test_buttons_appear(self): rsp = self.client.get(reverse('admin:services_service_change', args=[self.service.pk])) self.assertContains(rsp, "Save and approve") self.assertContains(rsp, "Save and reject") def test_approve_action(self): self.service.validate_for_approval() data = { 'index': '0', # "Go" button 'action': 'approve', # selected action '_selected_action': [ str(self.service.pk), # selected checkbox ] } rsp = self.client.post(reverse('admin:services_service_changelist'), data) self.assertEqual(302, rsp.status_code, msg=rsp.content.decode('utf-8')) new_url = rsp['Location'] rsp = self.client.get(new_url) self.assertEqual(200, rsp.status_code, msg=rsp.content.decode('utf-8')) service = Service.objects.get(pk=self.service.pk) self.assertEqual(Service.STATUS_CURRENT, service.status) def test_reject_action(self): data = { 'index': '0', # "Go" button 'action': 'reject', # selected action '_selected_action': [ str(self.service.pk), # selected checkbox ] } rsp = self.client.post(reverse('admin:services_service_changelist'), data) self.assertEqual(302, rsp.status_code, msg=rsp.content.decode('utf-8')) new_url = rsp['Location'] rsp = self.client.get(new_url) self.assertEqual(200, rsp.status_code, msg=rsp.content.decode('utf-8')) service = Service.objects.get(pk=self.service.pk) self.assertEqual(Service.STATUS_REJECTED, service.status) def test_approve_action_wrong_status(self): self.service.status = Service.STATUS_CURRENT self.service.save() data = { 'index': '0', # "Go" button 'action': 'approve', # selected action '_selected_action': [ str(self.service.pk), # selected checkbox ] } rsp = self.client.post(reverse('admin:services_service_changelist'), data, follow=True) self.assertEqual(200, rsp.status_code) self.assertIn('Only services in draft status may be approved', [str(msg) for msg in rsp.context['messages']]) def test_reject_action_wrong_status(self): self.service.status = Service.STATUS_CURRENT self.service.save() data = { 'index': '0', # "Go" button 'action': 'reject', # selected action '_selected_action': [ str(self.service.pk), # selected checkbox ] } rsp = self.client.post(reverse('admin:services_service_changelist'), data, follow=True) self.assertEqual(200, rsp.status_code) self.assertIn('Only services in draft status may be rejected', [str(msg) for msg in rsp.context['messages']]) def test_show_image_in_changelist(self): rsp = self.client.get(reverse('admin:services_service_changelist')) image_tag = '<img src="%s">' % self.service.get_thumbnail_url() self.assertContains(rsp, image_tag, html=True) def test_show_no_image_if_not_set(self): self.service.image = '' self.service.save() rsp = self.client.get(reverse('admin:services_service_changelist')) self.assertContains(rsp, 'no image')
class JiraNewServiceTest(MockJiraTestMixin, TestCase): def setUp(self): self.test_service = ServiceFactory(location='POINT(5 23)') self.jira_record = self.test_service.jira_records.get( update_type=JiraUpdateRecord.NEW_SERVICE) self.staff_user = EmailUserFactory(is_staff=True) def test_create_issue_sets_keyval(self, mock_JIRA): self.assertEqual('', self.jira_record.jira_issue_key) issue_key = self.setup_issue_key(mock_JIRA) self.jira_record.do_jira_work() self.assertEqual(issue_key, self.jira_record.jira_issue_key) def test_create_issue_kwargs(self, mock_JIRA): self.test_service.sunday_open = datetime.time(11, 10) self.test_service.sunday_close = datetime.time(12, 10) self.test_service.saturday_open = datetime.time(17, 18) self.test_service.saturday_close = datetime.time(19, 18) self.test_service.save() self.test_service.provider.focal_point_phone_number = '12-345678' self.test_service.provider.number_of_monthly_beneficiaries = '31415' self.test_service.provider.save() SelectionCriterionFactory( service=self.test_service, text_en="Must be 18", text_ar="Must have passport", text_fr="Must have transportation" ) SelectionCriterionFactory( service=self.test_service, text_en="Must be 21", text_ar="Must have shoes", text_fr="Must be citizen" ) self.setup_issue_key(mock_JIRA) self.jira_record = JiraUpdateRecord.objects.get(pk=self.jira_record.pk) self.jira_record.do_jira_work() call_args, call_kwargs = mock_JIRA.return_value.create_issue.call_args # Expecting: summary, project, issuetype, description, duedate self.assertTrue('summary' in call_kwargs) self.assertTrue('new service' in call_kwargs['summary'].lower()) self.assertTrue(self.test_service.provider.name_en in call_kwargs['summary']) self.assertTrue('project' in call_kwargs) self.assertEqual({'key': settings.JIRA_SERVICES_PROJECT_KEY}, call_kwargs['project']) self.assertTrue('issuetype' in call_kwargs) self.assertEqual({'name': 'Task'}, call_kwargs['issuetype']) self.assertTrue('description' in call_kwargs) admin_url = absolute_url(self.test_service.get_admin_edit_url()) self.assertTrue( admin_url in call_kwargs['description'], msg='%s not found in %s' % (admin_url, call_kwargs['description'])) self.assertIn('11:10', call_kwargs['description']) self.assertIn('17:18', call_kwargs['description']) self.assertIn('Must be 18', call_kwargs['description']) self.assertIn('Must have shoes', call_kwargs['description']) self.assertIn('12-345678', call_kwargs['description']) self.assertIn('31415', call_kwargs['description']) self.assertTrue('duedate' in call_kwargs) expected_duedate = datetime.date.today() + datetime.timedelta(days=settings.JIRA_DUEIN_DAYS) self.assertEqual(str(expected_duedate), call_kwargs['duedate']) # We've tested 5, ensure that is all that were passed self.assertEqual(5, len(call_kwargs)) self.assertEqual((), call_args) def test_create_issue_kwargs_for_update(self, mock_JIRA): self.test_service.update_of = ServiceFactory() self.jira_record.update_type = JiraUpdateRecord.CHANGE_SERVICE self.jira_record.save() self.setup_issue_key(mock_JIRA) self.jira_record.do_jira_work() call_args, call_kwargs = mock_JIRA.return_value.create_issue.call_args # Only checking summary as that has the essentially different value # from what the "new service" case sets. self.assertTrue('summary' in call_kwargs) self.assertTrue('changed service' in call_kwargs['summary'].lower()) self.assertTrue(self.test_service.provider.name_en in call_kwargs['summary']) def test_new_service_then_approve_before_task(self, mock_JIRA): # If a service is approved before we try to do the JIRA work, # the JIRA work gracefully works self.jira_record.update_type = JiraUpdateRecord.NEW_SERVICE self.jira_record.save() self.test_service.staff_approve(self.staff_user) self.setup_issue_key(mock_JIRA) self.jira_record.do_jira_work() def test_change_service_then_approve_before_task(self, mock_JIRA): # If a service is approved before we try to do the JIRA work, # the JIRA work gracefully works self.test_service.update_of = ServiceFactory() self.jira_record.update_type = JiraUpdateRecord.CHANGE_SERVICE self.jira_record.save() self.test_service.staff_approve(self.staff_user) self.setup_issue_key(mock_JIRA) self.jira_record.do_jira_work() def test_create_jira_issue_noop_if_already_created(self, mock_JIRA): test_key_val = 'ALREADY-SET' self.jira_record.jira_issue_key = test_key_val self.jira_record.save() self.jira_record.do_jira_work() self.assertFalse(mock_JIRA.called) self.assertEqual(test_key_val, self.jira_record.jira_issue_key) def test_create_jira_issue_uses_provided_jira(self, mock_JIRA): # This 2nd mock will take precendence by default, we test to # ensure that if the original mock is passed in it is called. with mock.patch('services.jira_support.JIRA') as JIRA: issue_key = self.setup_issue_key(mock_JIRA) self.jira_record.do_jira_work(mock_JIRA()) self.assertFalse(JIRA.called) self.assertEqual(issue_key, self.jira_record.jira_issue_key) def test_cancel_current_service_creates_jira_issue(self, mock_JIRA): service = self.jira_record.service service.status = service.STATUS_CURRENT service.save() service.cancel() self.jira_record = \ service.jira_records.get(update_type=JiraUpdateRecord.CANCEL_CURRENT_SERVICE) self.jira_record.save() self.setup_issue_key(mock_JIRA) self.jira_record.do_jira_work() call_args, call_kwargs = mock_JIRA.return_value.create_issue.call_args # Only checking summary as that has the essentially different value # from what the "new service" case sets. self.assertTrue('summary' in call_kwargs) self.assertTrue('canceled service' in call_kwargs['summary'].lower()) self.assertTrue(self.test_service.provider.name_en in call_kwargs['summary']) def test_cancel_draft_new_service_comments_on_jira_issue(self, mock_JIRA): # If we cancel a pending new service, it adds a comment to the # existing JIRA issue. # First create a record from when the draft service was started issue_key = 'XXX-123' self.jira_record.jira_issue_key = issue_key self.jira_record.save() service = self.jira_record.service service.status = service.STATUS_DRAFT service.save() service.cancel() cancel_record = service.jira_records.get(update_type=JiraUpdateRecord.CANCEL_DRAFT_SERVICE) cancel_record.do_jira_work() call_args, call_kwargs = mock_JIRA.return_value.add_comment.call_args # Only checking summary as that has the essentially different value # from what the "new service" case sets. self.assertEqual(issue_key, call_args[0]) self.assertIn('change was canceled', call_args[1]) # We should NOT have created a new JIRA record self.assertFalse(mock_JIRA.return_value.create_issue.called) def test_cancel_draft_service_change_comments_on_jira_issue(self, mock_JIRA): # If we cancel a pending change to a current service, it adds a comment # to the existing jira issue. # make the service we're canceling look like a change to an existing service existing_service = ServiceFactory(status=Service.STATUS_CURRENT) draft_service = ServiceFactory( update_of=existing_service, status=Service.STATUS_DRAFT, ) # Pretend we've created a JIRA issue when the draft was started. issue_key = 'XXX-123' draft_service.jira_records.update(jira_issue_key=issue_key) # Now cancel the draft draft_service.cancel() # We should get a new jira update record created cancel_record = \ draft_service.jira_records.get(update_type=JiraUpdateRecord.CANCEL_DRAFT_SERVICE) # run it: cancel_record.do_jira_work() call_args, call_kwargs = mock_JIRA.return_value.add_comment.call_args # Only checking summary as that has the essentially different value # from what the "new service" case sets. self.assertEqual(issue_key, call_args[0]) self.assertIn('change was canceled', call_args[1]) record = JiraUpdateRecord.objects.get(pk=cancel_record.pk) self.assertEqual(issue_key, record.jira_issue_key) # We should NOT have created a new JIRA record self.assertFalse(mock_JIRA.return_value.create_issue.called) def test_replacing_a_draft_comments_on_jira_issue(self, mock_JIRA): draft_service = ServiceFactory(status=Service.STATUS_DRAFT) # Pretend we've created a JIRA issue when the draft was started. issue_key = 'XXX-123' draft_service.jira_records.update(jira_issue_key=issue_key) mock_JIRA.return_value.create_issue.reset_mock() # Forget we "created a jira record" # Now edit the draft new_draft = ServiceFactory(update_of=draft_service, status=Service.STATUS_DRAFT) # We should have a new update record jira_record = new_draft.jira_records.get(update_type=JiraUpdateRecord.SUPERSEDED_DRAFT) jira_record.do_jira_work() # We should NOT have created another JIRA record self.assertFalse(mock_JIRA.return_value.create_issue.called) # We add a comment with links to the old and new data call_args, call_kwargs = mock_JIRA.return_value.add_comment.call_args self.assertEqual(issue_key, call_args[0]) self.assertIn(new_draft.get_admin_edit_url(), call_args[1])