Example #1
0
 def test_is_entry_level(self):
     worker = WorkerFactory()
     WorkerCertificationFactory(worker=worker,
                                certification=self.cert,
                                role=WorkerCertification.Role.ENTRY_LEVEL)
     self.assertTrue(worker.is_entry_level(self.cert))
     self.assertFalse(worker.is_reviewer(self.cert))
Example #2
0
    def test_send_staffing_request_priorities(self, mock_slack):

        worker2 = WorkerFactory()
        WorkerCertificationFactory(worker=worker2, staffing_priority=-1)

        CommunicationPreferenceFactory(
            worker=worker2,
            communication_type=(CommunicationPreference.CommunicationType.
                                NEW_TASK_AVAILABLE.value))

        worker3 = WorkerFactory()
        WorkerCertificationFactory(worker=worker3, staffing_priority=1)
        CommunicationPreferenceFactory(
            worker=worker3,
            communication_type=(CommunicationPreference.CommunicationType.
                                NEW_TASK_AVAILABLE.value))

        request = StaffBotRequestFactory()
        self.assertEqual(request.status,
                         StaffBotRequest.Status.PROCESSING.value)

        # Workers should be contacted in priority order.
        excluded = []
        for worker in (worker3, self.worker, worker2):
            send_staffing_requests(worker_batch_size=1,
                                   frequency=timedelta(minutes=0))
            inquiries = (StaffingRequestInquiry.objects.filter(
                request=request).exclude(
                    communication_preference__worker__in=excluded))
            for inquiry in inquiries:
                self.assertEqual(worker.id,
                                 inquiry.communication_preference.worker.id)
            excluded.append(worker)
Example #3
0
 def test_is_entry_level(self):
     worker = WorkerFactory()
     WorkerCertificationFactory(
         worker=worker,
         certification=self.cert,
         role=WorkerCertification.Role.ENTRY_LEVEL)
     self.assertTrue(worker.is_entry_level(self.cert))
     self.assertFalse(worker.is_reviewer(self.cert))
Example #4
0
class AccountSettingsTest(OrchestraAuthenticatedTestCase):

    def setUp(self):
        super().setUp()
        self.request_client, self.user = self.authenticate_user()
        self.url = reverse('orchestra:account_settings')
        self.worker = WorkerFactory(user=self.user)

    def _get_account_settings_mock_data(self):
        return {
            'first_name': 'Mock first',
            'last_name': 'Mock last',
            'slack_username': '******',
            'phone_0': '+1',
            'phone_1': '3477761527',
        }

    def test_get_form(self):
        response = self.request_client.get(self.url)
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'accounts/settings.html')

    @patch('orchestra.accounts.forms.get_slack_user_id')
    def test_change_all_fields(self, mock_get_slack_user_id):
        mock_get_slack_user_id.return_value = 'test_id'

        data = self._get_account_settings_mock_data()
        response = self.request_client.post(self.url, data)
        self.assertTrue(response.context['success'])

        self.user.refresh_from_db()
        self.assertEqual(self.user.first_name, data['first_name'])
        self.assertEqual(self.user.last_name, data['last_name'])

        self.worker.refresh_from_db()
        self.assertEqual(self.worker.slack_username, data['slack_username'])
        self.assertEqual(self.worker.phone, data['phone_0'] + data['phone_1'])
        self.assertEqual(self.worker.slack_user_id, 'test_id')

    @patch('orchestra.accounts.forms.get_slack_user_id')
    def test_missing_fields(self, mock_get_slack_user_id):
        mock_get_slack_user_id.return_value = 'test_id'

        required_fields = self._get_account_settings_mock_data().keys()
        for field in required_fields:
            data = self._get_account_settings_mock_data()
            data.pop(field)
            response = self.request_client.post(self.url, data)
            self.assertFalse(response.context['success'])
Example #5
0
class AccountSettingsTest(OrchestraAuthenticatedTestCase):
    def setUp(self):
        super().setUp()
        self.user = self.authenticate_user()
        self.url = reverse('orchestra:account_settings')
        self.worker = WorkerFactory(user=self.user)

    def _get_account_settings_mock_data(self):
        return {
            'first_name': 'Mock first',
            'last_name': 'Mock last',
            'slack_username': '******',
            'phone_0': '+1',
            'phone_1': '3477761527',
        }

    def test_get_form(self):
        response = self.request_client.get(self.url)
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'accounts/settings.html')

    @patch('orchestra.accounts.forms.get_slack_user_id')
    def test_change_all_fields(self, mock_get_slack_user_id):
        mock_get_slack_user_id.return_value = 'test_id'

        data = self._get_account_settings_mock_data()
        response = self.request_client.post(self.url, data)
        self.assertTrue(response.context['success'])

        self.user.refresh_from_db()
        self.assertEqual(self.user.first_name, data['first_name'])
        self.assertEqual(self.user.last_name, data['last_name'])

        self.worker.refresh_from_db()
        self.assertEqual(self.worker.slack_username, data['slack_username'])
        self.assertEqual(self.worker.phone, data['phone_0'] + data['phone_1'])
        self.assertEqual(self.worker.slack_user_id, 'test_id')

    @patch('orchestra.accounts.forms.get_slack_user_id')
    def test_missing_fields(self, mock_get_slack_user_id):
        mock_get_slack_user_id.return_value = 'test_id'

        required_fields = self._get_account_settings_mock_data().keys()
        for field in required_fields:
            data = self._get_account_settings_mock_data()
            data.pop(field)
            response = self.request_client.post(self.url, data)
            self.assertFalse(response.context['success'])
Example #6
0
 def setUp(self):
     super().setUp()
     user = UserFactory(username='******')
     self.worker = WorkerFactory(user=user)
     self.request_client.login(username=self.worker.user.username,
                               password='******')
     self.time = timezone.now()
Example #7
0
    def test_address_staffing_requests_parameters(self, mock_slack):
        for idx in range(5):
            worker = WorkerFactory()
            CommunicationPreferenceFactory(
                worker=worker,
                communication_type=(CommunicationPreference.CommunicationType.
                                    NEW_TASK_AVAILABLE.value))
            WorkerCertificationFactory(worker=worker,
                                       certification=self.certification)
        # Make a new request and turn off the global request, as the
        # global one has an inquiry on it already.
        request = StaffBotRequestFactory(task__step__is_human=True)
        request.task.step.required_certifications.add(self.certification)

        self.staffing_request_inquiry.request.status = (
            StaffBotRequest.Status.DONE_SENDING_INQUIRIES)

        address_staffing_requests(worker_batch_size=1,
                                  frequency=timedelta(minutes=20))
        # Inquiries increase by two because we send a Slack and an
        # email notification.  `last_inquiry_sent` is None on new
        # tasks, so we send this batch regardless of frequency.
        self.assertEqual(
            StaffingRequestInquiry.objects.filter(request=request).count(), 2)

        address_staffing_requests(worker_batch_size=2,
                                  frequency=timedelta(minutes=20))
        # Don't send more inquiries, since it hasn't been 20 minutes.
        self.assertEqual(
            StaffingRequestInquiry.objects.filter(request=request).count(), 2)

        request.last_inquiry_sent = timezone.now() - timedelta(minutes=21)
        request.save()
        address_staffing_requests(worker_batch_size=2,
                                  frequency=timedelta(minutes=20))
        # Send two email and two slack inquiries since it's been 21 minutes.
        self.assertEqual(
            StaffingRequestInquiry.objects.filter(request=request).count(), 6)

        address_staffing_requests(worker_batch_size=10,
                                  frequency=timedelta(minutes=20))
        # Don't send more inquiries, since it hasn't been 20 minutes.
        self.assertEqual(
            StaffingRequestInquiry.objects.filter(request=request).count(), 6)

        request.last_inquiry_sent = timezone.now() - timedelta(minutes=21)
        request.save()
        address_staffing_requests(worker_batch_size=10,
                                  frequency=timedelta(minutes=20))
        # Send remaining inquiries, since enough time has passed.
        self.assertEqual(
            StaffingRequestInquiry.objects.filter(request=request).count(), 12)

        request.last_inquiry_sent = timezone.now() - timedelta(minutes=21)
        request.save()
        address_staffing_requests(worker_batch_size=10,
                                  frequency=timedelta(minutes=20))
        # We're all out of workers to whom we'd like to send inquiries.
        self.assertEqual(
            StaffingRequestInquiry.objects.filter(request=request).count(), 12)
Example #8
0
    def test_mark_worker_as_winner(self):
        self.assertEqual(self.staffing_request_inquiry.responses.all().count(),
                         0)

        mark_worker_as_winner(self.worker,
                              self.staffing_request_inquiry.request.task, 0,
                              self.staffing_request_inquiry)
        staffbot_request = self.staffing_request_inquiry.request
        staffbot_request.refresh_from_db()

        self.assertEqual(staffbot_request.status,
                         StaffBotRequest.Status.CLOSED.value)
        self.assertEqual(self.staffing_request_inquiry.responses.all().count(),
                         0)

        # Can't mark another worker as a winner for this request
        worker2 = WorkerFactory()
        inquiry2 = StaffingRequestInquiryFactory(
            communication_preference__worker=worker2,
            communication_preference__communication_type=(
                CommunicationPreference.CommunicationType.NEW_TASK_AVAILABLE.
                value),
            request__task__step__is_human=True,
            request=self.staffing_request_inquiry.request)
        mark_worker_as_winner(worker2, inquiry2.request.task, 0, inquiry2)
        self.assertEqual(inquiry2.responses.count(), 0)
Example #9
0
    def test_restaff_command_errors(self):
        """
        Test that the staffing logic errors are raised during
        staff command.
        """
        bot = StaffBot()
        command = 'restaff 999999999999 unknown'
        data = get_mock_slack_data(
            text=command,
            user_id=self.worker.slack_user_id)

        response = bot.dispatch(data)
        self.assertEqual(response.get('text'),
                         command)

        self.assertEqual(response['attachments'][0]['text'],
                         bot.worker_does_not_exist.format('unknown'))

        worker = WorkerFactory(user__username='******')
        data['text'] = 'restaff 999999999999 username'
        response = bot.dispatch(data)
        self.assertEqual(response['attachments'][0]['text'],
                         bot.task_does_not_exist_error.format('999999999999'))

        # making sure it works with slack username as well.
        worker.slack_username = '******'
        worker.save()
        data['text'] = 'restaff 999999999999 slackusername'
        response = bot.dispatch(data)
        self.assertEqual(response['attachments'][0]['text'],
                         bot.task_does_not_exist_error.format('999999999999'))

        data['text'] = 'restaff'
        response = bot.dispatch(data)
        self.assertTrue(bot.default_error_text in response.get('text'))

        task = TaskFactory(status=Task.Status.COMPLETE)
        command = 'restaff {} {}'.format(task.id, worker.user.username)

        data['text'] = command
        response = bot.dispatch(data)
        self.assertEquals(response['attachments'][0]['text'],
                          (bot.task_assignment_does_not_exist_error
                           .format(worker.user.username, task.id)))
Example #10
0
    def test_restaff_command_errors(self):
        """
        Test that the staffing logic errors are raised during
        staff command.
        """
        bot = StaffBot()
        command = 'restaff 999999999999 unknown'
        data = get_mock_slack_data(
            text=command,
            user_id=self.worker.slack_user_id)

        response = bot.dispatch(data)
        self.assertEqual(response.get('text'),
                         command)

        self.assertEqual(response['attachments'][0]['text'],
                         bot.worker_does_not_exist.format('unknown'))

        worker = WorkerFactory(user__username='******')
        data['text'] = 'restaff 999999999999 username'
        response = bot.dispatch(data)
        self.assertEqual(response['attachments'][0]['text'],
                         bot.task_does_not_exist_error.format('999999999999'))

        # making sure it works with slack username as well.
        worker.slack_username = '******'
        worker.save()
        data['text'] = 'restaff 999999999999 slackusername'
        response = bot.dispatch(data)
        self.assertEqual(response['attachments'][0]['text'],
                         bot.task_does_not_exist_error.format('999999999999'))

        data['text'] = 'restaff'
        response = bot.dispatch(data)
        self.assertTrue(bot.default_error_text in response.get('text'))

        task = TaskFactory(status=Task.Status.COMPLETE)
        command = 'restaff {} {}'.format(task.id, worker.user.username)

        data['text'] = command
        response = bot.dispatch(data)
        self.assertEquals(response['attachments'][0]['text'],
                          (bot.task_assignment_does_not_exist_error
                           .format(worker.user.username, task.id)))
Example #11
0
 def setUp(self):
     self.worker = WorkerFactory()
     self.staffing_request_inquiry = StaffingRequestInquiryFactory(
         communication_preference__worker=self.worker,
         communication_preference__communication_type=(
             CommunicationPreference.CommunicationType
             .NEW_TASK_AVAILABLE.value),
         request__task__step__is_human=True
     )
     super().setUp()
Example #12
0
 def _create_worker(self, staffing_priority):
     worker = WorkerFactory()
     WorkerCertificationFactory(worker=worker,
                                certification=self.certification,
                                staffing_priority=staffing_priority)
     communication_preference = CommunicationPreferenceFactory(
         worker=worker,
         communication_type=(CommunicationPreference.CommunicationType.
                             NEW_TASK_AVAILABLE.value))
     return worker, communication_preference
Example #13
0
    def test_unauthenticated_request(self):
        new_worker = WorkerFactory()
        comm_pref = (self.staffing_response.
                     request_inquiry.communication_preference)
        comm_pref.worker = new_worker
        comm_pref.save()

        response = self.request_client.get(self.url)
        self.assert_response(response, status_code=404,
                             template='orchestra/error.html')
    def test_send_staffing_requests(self, mock_slack):
        worker2 = WorkerFactory()
        CommunicationPreferenceFactory(
            worker=worker2,
            communication_type=(
                CommunicationPreference.CommunicationType
                .NEW_TASK_AVAILABLE.value))
        WorkerCertificationFactory(
            worker=worker2,
            certification=self.certification
        )

        request = StaffBotRequestFactory()
        request.task.step.required_certifications.add(self.certification)

        self.assertEqual(request.status,
                         StaffBotRequest.Status.SENDING_INQUIRIES.value)

        send_staffing_requests(worker_batch_size=1,
                               frequency=timedelta(minutes=0))
        mock_slack.assert_not_called()
        request.refresh_from_db()
        self.assertEqual(request.status,
                         StaffBotRequest.Status.SENDING_INQUIRIES.value)
        # Inquiries increase by two because we send a Slack and an
        # email notification.
        self.assertEqual(
            StaffingRequestInquiry.objects.filter(request=request).count(),
            2)

        send_staffing_requests(worker_batch_size=1,
                               frequency=timedelta(minutes=0))
        self.assertEqual(mock_slack.call_count, 1)
        mock_slack.reset()

        request.refresh_from_db()
        self.assertEqual(request.status,
                         StaffBotRequest.Status.SENDING_INQUIRIES.value)
        self.assertEqual(
            StaffingRequestInquiry.objects.filter(request=request).count(),
            4)

        # marked as closed and no new request inquiries sent.
        send_staffing_requests(worker_batch_size=1,
                               frequency=timedelta(minutes=0))
        self.assertTrue(mock_slack.called)
        request.refresh_from_db()
        self.assertEqual(request.status,
                         StaffBotRequest.Status.DONE_SENDING_INQUIRIES.value)
        self.assertEqual(
            StaffingRequestInquiry.objects.filter(request=request).count(),
            4)
Example #15
0
    def setUp(self):
        super().setUp()
        setup_models(self)
        self.project_admin_group = Group.objects.create(name='project_admins')
        user = (UserFactory(username='******',
                            first_name='project_management',
                            last_name='project_management',
                            password='******',
                            email='*****@*****.**'))
        self.worker = WorkerFactory(user=user)
        user.groups.add(self.project_admin_group)

        self.api_client = Client()
        self.api_client.login(username='******',
                              password='******')
Example #16
0
    def setUp(self):
        self.workflow_old = WorkflowFactory(
            slug='workflow_old',
            name='Old workflow',
            description='Old workflow to migrate certifications from.',
            code_directory='workflow_old')
        self.workflow_new = WorkflowFactory(
            slug='workflow_new',
            name='New workflow',
            description='New workflow to migrate certifications from.',
            code_directory='workflow_new')

        for workflow in (self.workflow_old, self.workflow_new):
            # Certifications must exist in both workflows for certification
            # to be migrated
            CertificationFactory(
                slug='certification1',
                name='Certification 1',
                description='First certification to migrate.',
                workflow=workflow)
            CertificationFactory(
                slug='certification2',
                name='Certification 2',
                description='Second certification to migrate.',
                workflow=workflow)

        user = (UserFactory(username='******',
                            first_name='test',
                            last_name='test',
                            password='******',
                            email='*****@*****.**'))
        self.worker = WorkerFactory(user=user)

        for certification in self.workflow_old.certifications.all():
            # Worker certifications exist only for old workflow
            WorkerCertificationFactory(
                worker=self.worker,
                certification=certification,
                role=WorkerCertification.Role.ENTRY_LEVEL)
            WorkerCertificationFactory(
                worker=self.worker,
                certification=certification,
                role=WorkerCertification.Role.REVIEWER)

        super().setUp()
Example #17
0
    def test_handle_staffing_response_all_rejected(self, mock_slack):
        worker2 = WorkerFactory()

        CommunicationPreferenceFactory(
            worker=worker2,
            communication_type=(CommunicationPreference.CommunicationType.
                                NEW_TASK_AVAILABLE.value))

        response = handle_staffing_response(self.worker,
                                            self.staffing_request_inquiry.id,
                                            is_available=False)
        self.assertFalse(response.is_winner)
        self.assertEqual(response.request_inquiry.request.status,
                         StaffBotRequest.Status.CLOSED.value)
        self.assertEqual(mock_slack.call_count, 1)
        mock_slack.reset()

        handle_staffing_response(worker2,
                                 self.staffing_request_inquiry.id,
                                 is_available=False)

        self.assertEqual(mock_slack.call_count, 1)
Example #18
0
    def test_handle_staffing_response_is_available(self):
        # Test StaffingResponse object creation
        old_count = StaffingResponse.objects.all().count()

        # assign task is called
        response = handle_staffing_response(self.worker,
                                            self.staffing_request_inquiry.id,
                                            is_available=True)
        self.assertTrue(response.is_winner)
        self.staffing_request_inquiry.refresh_from_db()
        self.assertEqual(response.request_inquiry.request.status,
                         StaffBotRequest.Status.CLOSED.value)
        self.assertEqual(StaffingResponse.objects.all().count(), old_count + 1)

        task_assignment = (TaskAssignment.objects.get(
            worker=self.worker,
            task=self.staffing_request_inquiry.request.task))
        self.assertEqual(task_assignment.status,
                         TaskAssignment.Status.PROCESSING)
        self.staffing_request_inquiry.request.task.refresh_from_db()

        # Replay of same request
        response = handle_staffing_response(self.worker,
                                            self.staffing_request_inquiry.id,
                                            is_available=True)
        self.assertTrue(response.is_winner)
        self.assertEqual(response.request_inquiry.request.status,
                         StaffBotRequest.Status.CLOSED.value)
        self.assertEqual(StaffingResponse.objects.all().count(), old_count + 1)

        # Change mind to `is_available=False` does not do anything
        with self.assertRaises(StaffingResponseException):
            response = handle_staffing_response(
                self.worker,
                self.staffing_request_inquiry.id,
                is_available=False)

        new_request_inquiry = StaffingRequestInquiryFactory(
            request__task__step__is_human=True)
        new_worker = new_request_inquiry.communication_preference.worker
        old_count = StaffingResponse.objects.all().count()
        response = handle_staffing_response(new_worker,
                                            new_request_inquiry.id,
                                            is_available=True)
        self.assertTrue(response.is_winner)
        self.assertEqual(response.request_inquiry.request.status,
                         StaffBotRequest.Status.CLOSED.value)
        self.assertEqual(StaffingResponse.objects.all().count(), old_count + 1)

        task_assignment = (TaskAssignment.objects.get(
            worker=new_worker, task=new_request_inquiry.request.task))
        self.assertEqual(task_assignment.status,
                         TaskAssignment.Status.PROCESSING)

        # restaff
        response.is_winner = False
        response.save()

        worker2 = WorkerFactory()
        staffing_request_inquiry2 = StaffingRequestInquiryFactory(
            communication_preference__worker=worker2,
            request__task=new_request_inquiry.request.task)
        response = handle_staffing_response(worker2,
                                            staffing_request_inquiry2.id,
                                            is_available=True)
        self.assertTrue(response.is_winner)
        self.assertEqual(response.request_inquiry.request.status,
                         StaffBotRequest.Status.CLOSED.value)
        task_assignment.refresh_from_db()
        self.assertEqual(task_assignment.worker, worker2)
Example #19
0
    def test_get_available_request(self, mock_slack):
        # Close all open requests so new worker doesn't receive them.
        address_staffing_requests(worker_batch_size=2,
                                  frequency=timedelta(minutes=0))

        self.assertEqual(len(get_available_requests(self.worker)), 1)

        worker2 = WorkerFactory()
        CommunicationPreferenceFactory(
            worker=worker2,
            communication_type=(CommunicationPreference.CommunicationType.
                                NEW_TASK_AVAILABLE.value))
        WorkerCertificationFactory(worker=worker2,
                                   certification=self.certification)

        request1 = StaffBotRequestFactory(task__step__is_human=True)
        request1.task.step.required_certifications.add(self.certification)
        request2 = StaffBotRequestFactory(task__step__is_human=True)
        request2.task.step.required_certifications.add(self.certification)

        address_staffing_requests(worker_batch_size=2,
                                  frequency=timedelta(minutes=0))
        inquiry1 = (StaffingRequestInquiry.objects.filter(
            communication_preference__worker=self.worker).filter(
                request=request1).first())
        inquiry2 = (StaffingRequestInquiry.objects.filter(
            communication_preference__worker=worker2).filter(
                request=request2).first())

        # `self.worker` now has three available tasks, whereas `worker2`
        # just has access to the two new tasks.
        available_requests = get_available_requests(self.worker)
        self.assertEqual(len(available_requests), 3)
        self.assertEqual(len(get_available_requests(worker2)), 2)

        # Tasks should be sorted by start_datetime in ascending order.

        first_available, second_available, third_available = (
            available_requests[0]['available_datetime'],
            available_requests[1]['available_datetime'],
            available_requests[2]['available_datetime'])
        self.assertLess(first_available, second_available)
        self.assertLess(second_available, third_available)

        # `self.worker` will lose an available task (they accept it),
        # whereas `worker2` is unchanged.
        handle_staffing_response(self.worker,
                                 self.staffing_request_inquiry.id,
                                 is_available=True)
        self.assertEqual(len(get_available_requests(self.worker)), 2)
        self.assertEqual(len(get_available_requests(worker2)), 2)

        # `self.worker` will lose an available task (they ignore it),
        # whereas `worker2` is unchanged.
        handle_staffing_response(self.worker, inquiry1.id, is_available=False)
        self.assertEqual(len(get_available_requests(self.worker)), 1)
        self.assertEqual(len(get_available_requests(worker2)), 2)

        # `worker2` takes a task.
        handle_staffing_response(worker2, inquiry2.id, is_available=True)
        self.assertEqual(len(get_available_requests(self.worker)), 0)
        self.assertEqual(len(get_available_requests(worker2)), 1)
Example #20
0
 def setUp(self):
     self.user = UserFactory()
     self.worker = WorkerFactory(user=self.user)
     super().setUp()
Example #21
0
 def setUp(self):
     super().setUp()
     self.user = self.authenticate_user()
     self.url = reverse('orchestra:account_settings')
     self.worker = WorkerFactory(user=self.user)
Example #22
0
 def setUp(self):
     super().setUp()
     self.request_client, self.user = self.authenticate_user()
     self.url = reverse('orchestra:account_settings')
     self.worker = WorkerFactory(user=self.user)