Esempio n. 1
0
    def _test_reverted_task(self, task, iteration, num_iterations,
                            task_status, latest_data, expected_audit,
                            revert_before=False):
        response = self._revert_task(
            task, iteration, revert_before=revert_before, commit=False)
        self.assertEqual(response.status_code, 200)
        task.refresh_from_db()
        fake_audit = load_encoded_json(response.content)
        self.assertEqual(fake_audit, expected_audit)

        self.assertEqual(task.status, Task.Status.COMPLETE)
        self.assertEqual(task.assignments.count(), 2)
        for assignment in task.assignments.all():
            self.assertEqual(assignment.iterations.count(), 2)

        response = self._revert_task(
            task, iteration, revert_before=revert_before, commit=True)
        self.assertEqual(response.status_code, 200)
        task.refresh_from_db()
        audit = load_encoded_json(response.content)
        self.assertEqual(audit, fake_audit)
        task.refresh_from_db()
        self.assertEqual(task.status, task_status)
        self.assertEqual(
            get_iteration_history(task).count(), num_iterations)

        verify_iterations(task.id)

        if num_iterations:
            self.assertEqual(
                current_assignment(task).in_progress_task_data,
                latest_data)

        verify_iterations(task.id)
    def _test_reverted_task(self, task, iteration, num_iterations,
                            task_status, latest_data, expected_audit,
                            revert_before=False):
        response = self._revert_task(
            task, iteration, revert_before=revert_before, commit=False)
        self.assertEquals(response.status_code, 200)
        task.refresh_from_db()
        fake_audit = load_encoded_json(response.content)
        self.assertEqual(fake_audit, expected_audit)

        self.assertEquals(task.status, Task.Status.COMPLETE)
        self.assertEquals(task.assignments.count(), 2)
        for assignment in task.assignments.all():
            self.assertEquals(assignment.iterations.count(), 2)

        response = self._revert_task(
            task, iteration, revert_before=revert_before, commit=True)
        self.assertEqual(response.status_code, 200)
        task.refresh_from_db()
        audit = load_encoded_json(response.content)
        self.assertEqual(audit, fake_audit)
        task.refresh_from_db()
        self.assertEqual(task.status, task_status)
        self.assertEqual(
            get_iteration_history(task).count(), num_iterations)

        verify_iterations(task.id)

        if num_iterations:
            self.assertEquals(
                current_assignment(task).in_progress_task_data,
                latest_data)

        verify_iterations(task.id)
def snapshots_to_iterations(apps, schema_editor):
    Iteration = apps.get_model('orchestra', 'Iteration')
    Task = apps.get_model('orchestra', 'Task')
    TaskAssignment = apps.get_model('orchestra', 'TaskAssignment')

    for task in Task.objects.all():
        task_snapshots = get_ordered_snapshots(task)
        for task_snap_index, snapshot in enumerate(task_snapshots):
            assignment = snapshot['assignment']
            iteration = Iteration.objects.create(
                assignment=assignment,
                end_datetime=parse(snapshot['datetime']),
                submitted_data=snapshot['data'],
                status=snapshot_type_to_iteration_status[snapshot['type']])
            if snapshot['assignment_snap_index'] == 0:
                # Snapshot is the first for its assignment, so its start
                # datetime will be the same as its assignment
                # NOTE: This should cover the case where task_snap_index == 0
                iteration.start_datetime = assignment.start_datetime
            else:
                iteration.start_datetime = (task_snapshots[task_snap_index -
                                                           1]['datetime'])
            iteration.save()

        processing_assignments = task.assignments.filter(
            status=AssignmentStatus.PROCESSING)
        if processing_assignments.exists():
            if processing_assignments.count() > 1:
                logger.error(
                    'Task {} has too many processing assignments'.format(
                        task.id))
            else:
                # If task has a processing assignment, create a final
                # processing iteration
                processing_assignment = processing_assignments.first()
                if (not task_snapshots
                        or not processing_assignment.iterations.exists()):
                    final_start_datetime = processing_assignment.start_datetime
                else:
                    final_start_datetime = task_snapshots[-1]['datetime']
                iteration = Iteration.objects.create(
                    assignment=processing_assignment,
                    start_datetime=final_start_datetime,
                    status=IterationStatus.PROCESSING)

        try:
            verify_iterations(task.id)
        except AssertionError:
            logger.error('Iterations invalid for task {}.'.format(task.id))
def snapshots_to_iterations(apps, schema_editor):
    Iteration = apps.get_model('orchestra', 'Iteration')
    Task = apps.get_model('orchestra', 'Task')
    TaskAssignment = apps.get_model('orchestra', 'TaskAssignment')

    for task in Task.objects.all():
        task_snapshots = get_ordered_snapshots(task)
        for task_snap_index, snapshot in enumerate(task_snapshots):
            assignment = snapshot['assignment']
            iteration = Iteration.objects.create(
                assignment=assignment,
                end_datetime=parse(snapshot['datetime']),
                submitted_data=snapshot['data'],
                status=snapshot_type_to_iteration_status[snapshot['type']])
            if snapshot['assignment_snap_index'] == 0:
                # Snapshot is the first for its assignment, so its start
                # datetime will be the same as its assignment
                # NOTE: This should cover the case where task_snap_index == 0
                iteration.start_datetime = assignment.start_datetime
            else:
                iteration.start_datetime = (
                    task_snapshots[task_snap_index - 1]['datetime'])
            iteration.save()

        processing_assignments = task.assignments.filter(
            status=AssignmentStatus.PROCESSING)
        if processing_assignments.exists():
            if processing_assignments.count() > 1:
                logger.error(
                    'Task {} has too many processing assignments'.format(
                        task.id))
            else:
                # If task has a processing assignment, create a final
                # processing iteration
                processing_assignment = processing_assignments.first()
                if (not task_snapshots
                        or not processing_assignment.iterations.exists()):
                    final_start_datetime = processing_assignment.start_datetime
                else:
                    final_start_datetime = task_snapshots[-1]['datetime']
                iteration = Iteration.objects.create(
                    assignment=processing_assignment,
                    start_datetime=final_start_datetime,
                    status=IterationStatus.PROCESSING)

        try:
            verify_iterations(task.id)
        except AssertionError:
            logger.error('Iterations invalid for task {}.'.format(task.id))
Esempio n. 5
0
def setup_complete_task(test_case):
    # Microseconds are truncated when manually saving models
    test_start = timezone.now().replace(microsecond=0)
    times = {
        'awaiting_pickup': test_start,
        'entry_pickup': test_start + timedelta(hours=1),
        'entry_submit': test_start + timedelta(hours=2),
        'reviewer_pickup': test_start + timedelta(hours=3),
        'reviewer_reject': test_start + timedelta(hours=4),
        'entry_resubmit': test_start + timedelta(hours=5),
        'reviewer_accept': test_start + timedelta(hours=6),
    }

    task = TaskFactory(
        project=test_case.projects['empty_project'],
        status=Task.Status.AWAITING_PROCESSING,
        step=test_case.test_step,
        start_datetime=times['awaiting_pickup'])

    workers = {
        'entry': test_case.workers[0],
        'reviewer': test_case.workers[1]
    }

    assign_task(workers['entry'].id, task.id)

    task.refresh_from_db()
    test_case.assertEqual(task.status, Task.Status.PROCESSING)

    submit_task(
        task.id, {'test': 'entry_submit'},
        Iteration.Status.REQUESTED_REVIEW,
        workers['entry'])

    task.refresh_from_db()
    test_case.assertEqual(task.status, Task.Status.PENDING_REVIEW)

    assign_task(workers['reviewer'].id, task.id)
    reviewer_assignment = task.assignments.get(
        worker=workers['reviewer'])

    # Modify assignment with correct datetime
    reviewer_assignment.start_datetime = times['reviewer_pickup']
    reviewer_assignment.save()

    task.refresh_from_db()
    test_case.assertEqual(task.status, Task.Status.REVIEWING)

    submit_task(
        task.id, {'test': 'reviewer_reject'},
        Iteration.Status.PROVIDED_REVIEW,
        workers['reviewer'])

    task.refresh_from_db()
    test_case.assertEqual(task.status, Task.Status.POST_REVIEW_PROCESSING)

    submit_task(
        task.id, {'test': 'entry_resubmit'},
        Iteration.Status.REQUESTED_REVIEW,
        workers['entry'])

    task.refresh_from_db()
    test_case.assertEqual(task.status, Task.Status.REVIEWING)

    with patch('orchestra.utils.task_lifecycle._is_review_needed',
               return_value=False):
        submit_task(
            task.id, {'test': 'reviewer_accept'},
            Iteration.Status.REQUESTED_REVIEW,
            workers['reviewer'])

    task.refresh_from_db()
    test_case.assertEqual(task.status, Task.Status.COMPLETE)
    test_case.assertEqual(task.assignments.count(), 2)
    for assignment in task.assignments.all():
        test_case.assertEqual(
            assignment.status, TaskAssignment.Status.SUBMITTED)
        test_case.assertEqual(assignment.iterations.count(), 2)

    # Modify assignments with correct datetime
    new_datetime_labels = ('entry_pickup', 'reviewer_pickup')
    for i, assignment in enumerate(assignment_history(task).all()):
        assignment.start_datetime = times[new_datetime_labels[i]]
        assignment.save()

    # Modify iterations with correct datetime
    new_datetime_labels = (
        ('entry_pickup', 'entry_submit'),
        ('reviewer_pickup', 'reviewer_reject'),
        ('reviewer_reject', 'entry_resubmit'),
        ('entry_resubmit', 'reviewer_accept')
    )
    new_datetimes = [
        (times[start_label], times[end_label])
        for start_label, end_label in new_datetime_labels]

    for i, iteration in enumerate(get_iteration_history(task)):
        iteration.start_datetime, iteration.end_datetime = new_datetimes[i]
        iteration.save()

    verify_iterations(task.id)

    return task
Esempio n. 6
0
def _setup_tasks(test_case, tasks):
    # Create and assign tasks
    test_case.tasks = {}
    test_case.test_step = test_case.workflow_steps[
        test_case.test_version_slug][test_case.test_step_slug]
    for task_slug, details in tasks.items():
        task_pickup_time = BASE_DATETIME + timedelta(hours=1)
        task = TaskFactory(
            project=test_case.projects[details['project_name']],
            step=test_case.test_step,
            status=details['status'],
            start_datetime=task_pickup_time,
        )
        test_case.tasks[task_slug] = task
        for i, (user_id,
                task_data,
                assignment_status) in enumerate(details['assignments']):
            assignment = TaskAssignmentFactory(
                worker=test_case.workers[user_id],
                task=task,
                status=assignment_status,
                assignment_counter=i,
                in_progress_task_data=task_data,
                start_datetime=_new_assignment_start_datetime(task))

            # Each assignment must have at least one corresponding iteration
            Iteration.objects.create(
                assignment=assignment,
                start_datetime=assignment.start_datetime,
                end_datetime=assignment.start_datetime + ITERATION_DURATION,
                submitted_data=assignment.in_progress_task_data,
                status=Iteration.Status.REQUESTED_REVIEW)

            # Create time entry for each task.
            TimeEntryFactory(date='2016-04-04',
                             time_worked=timedelta(minutes=30),
                             assignment=assignment,
                             worker=test_case.workers[user_id],
                             description=(
                                 'test description {}'.format(assignment.id)))

        cur_assignment = current_assignment(task)
        assignments = assignment_history(task).all()
        if cur_assignment and (
                cur_assignment.status == TaskAssignment.Status.PROCESSING):
            # If there's a currently processing assignment, we'll need to
            # adjust the task's iteration sequence
            processing_counter = cur_assignment.assignment_counter
            if processing_counter != len(assignments) - 1:
                # If processing assignment is not the last in the hierarchy, we
                # need to reconstruct an iteration sequence: REQUESTED_REVIEW
                # up to the highest assignment counter, then PROVIDED_REVIEW
                # back down to the current assignment
                last_iteration = assignments.last().iterations.first()
                last_iteration.status = Iteration.Status.PROVIDED_REVIEW
                last_iteration.save()

                adjust_assignments = list(assignments)[processing_counter:-1]
                for assignment in reversed(adjust_assignments):
                    last_iteration = get_iteration_history(task).last()
                    Iteration.objects.create(
                        assignment=assignment,
                        start_datetime=last_iteration.end_datetime,
                        end_datetime=(
                            last_iteration.end_datetime + ITERATION_DURATION),
                        submitted_data=assignment.in_progress_task_data,
                        status=Iteration.Status.PROVIDED_REVIEW)

            # If there is a currently processing assignment, the task's last
            # iteration should still be processing
            last_iteration = get_iteration_history(task).last()
            last_iteration.end_datetime = None
            last_iteration.submitted_data = {}
            last_iteration.status = Iteration.Status.PROCESSING
            last_iteration.save()

        verify_iterations(task.id)
Esempio n. 7
0
    def test_submit_reviewer_task_assignment(self):
        data = {'submit_key1': 'submit_val1'}

        # user 1 is picking up a task as a reviewer
        response = (self.clients[1].get(
            '/orchestra/api/interface/new_task_assignment/reviewer/'))
        self.assertEqual(response.status_code, 200)
        returned = load_encoded_json(response.content)
        task_id = returned['id']
        task = Task.objects.get(id=returned['id'])
        self.assertEqual(task.assignments.count(), 2)
        self.assertEqual(task_id, self.tasks['review_task'].id)

        verify_iterations(task.id)

        rejected_data = {'rejected_key': 'rejected_val'}

        # user 0 can retrieve data, but should see a read-only interface
        self._verify_good_task_assignment_information(
            self.clients[0], {'task_id': task.id},
            task.project.short_description, 'Submitted', 'Reviewing', False,
            True, {'test_key': 'test_value'}, self.workers[0])

        # user 1 should be able to review the post
        self._verify_good_task_assignment_information(
            self.clients[1], {'task_id': task.id},
            task.project.short_description, 'Processing', 'Reviewing', True,
            False, {'test_key': 'test_value'}, self.workers[1])

        # user 1 rejects a task
        response = self._submit_assignment(self.clients[1],
                                           task_id,
                                           data=rejected_data,
                                           command='reject')
        self.assertEqual(response.status_code, 200)

        verify_iterations(task.id)

        # user 0 should have the task back
        self._verify_good_task_assignment_information(
            self.clients[0], {'task_id': task.id},
            task.project.short_description, 'Processing',
            'Post-review Processing', False, False, rejected_data,
            self.workers[0])

        # user 1 should no longer be able to modify the post
        self._verify_good_task_assignment_information(
            self.clients[1], {'task_id': task.id},
            task.project.short_description, 'Submitted',
            'Post-review Processing', True, True, rejected_data,
            self.workers[1])

        # user 0 submits an updated data
        response = self._submit_assignment(self.clients[0], task_id, data=data)
        self.assertEqual(response.status_code, 200)

        verify_iterations(task.id)

        # check if the data is saved
        self._verify_good_task_assignment_information(
            self.clients[1], {'task_id': task.id},
            task.project.short_description, 'Processing', 'Reviewing', True,
            False, data, self.workers[1])

        accepted_data = {'accepted_key': 'accepted_val'}
        # user 1 accepts a task
        response = self._submit_assignment(self.clients[1],
                                           task_id,
                                           data=accepted_data,
                                           command='accept')
        self.assertEqual(response.status_code, 200)

        verify_iterations(task.id)

        # check if the accepted_data is saved
        # and task is pending for a second review.
        self._verify_good_task_assignment_information(
            self.clients[1], {'task_id': task.id},
            task.project.short_description, 'Submitted', 'Pending Review',
            True, True, accepted_data, self.workers[1])

        # make sure a task can't be submitted twice
        response = self._submit_assignment(self.clients[1],
                                           task_id,
                                           command='accept')
        self.assertEqual(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEqual(returned['message'],
                         'Worker is not allowed to submit')

        # user 3 is picking up a task as a reviewer
        response = (self.clients[3].get(
            '/orchestra/api/interface/new_task_assignment/reviewer/'))
        self.assertEqual(response.status_code, 200)
        returned = load_encoded_json(response.content)
        self.assertEqual(returned['id'], task.id)

        verify_iterations(task.id)

        rejected_data = {'rejected_key': 'rejected_val'}

        # user 3 rejects a task
        response = self._submit_assignment(self.clients[3],
                                           task_id,
                                           data=rejected_data,
                                           command='reject')
        self.assertEqual(response.status_code, 200)
        returned = load_encoded_json(response.content)

        verify_iterations(task.id)

        # check if the rejected_data is saved
        self._verify_good_task_assignment_information(
            self.clients[3], {'task_id': task.id},
            task.project.short_description, 'Submitted',
            'Post-review Processing', True, True, rejected_data,
            self.workers[3])

        # check client dashboards
        self._check_client_dashboard_state(self.clients[0], 'pending_review')

        self._check_client_dashboard_state(self.clients[1], 'returned')

        self._check_client_dashboard_state(self.clients[3],
                                           'pending_processing')

        response = self._submit_assignment(self.clients[1], task.id)
        self.assertEqual(response.status_code, 200)

        verify_iterations(task.id)

        # check if client dashboards were updated
        self._check_client_dashboard_state(self.clients[0], 'pending_review')

        self._check_client_dashboard_state(self.clients[1], 'pending_review')

        self._check_client_dashboard_state(self.clients[3], 'in_progress')

        # check if the accepted_data is saved
        response = self._submit_assignment(self.clients[3],
                                           task_id,
                                           data=accepted_data,
                                           command='accept')
        self.assertEqual(response.status_code, 200)
        returned = load_encoded_json(response.content)

        verify_iterations(task.id)

        # check if task is complete
        self._verify_good_task_assignment_information(
            self.clients[3], {'task_id': task.id},
            task.project.short_description, 'Submitted', 'Complete', True,
            True, accepted_data, self.workers[3])

        # check that reviewer cannot reaccept task
        response = self._submit_assignment(self.clients[3],
                                           task_id,
                                           data=accepted_data,
                                           command='accept')
        self.assertEqual(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEqual(returned['message'], 'Task already completed')
Esempio n. 8
0
    def test_submit_entry_level_task_assignment(self):
        # user 0 only has certification for entry level tasks
        response = (self.clients[0].get(
            '/orchestra/api/interface/new_task_assignment/entry_level/'))
        self.assertEqual(response.status_code, 200)
        returned = load_encoded_json(response.content)
        task = Task.objects.get(id=returned['id'])

        verify_iterations(task.id)

        # user is not assigned to a task
        response = self._submit_assignment(self.clients[1], task.id)
        self.assertEqual(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEqual(returned['message'],
                         'Task assignment with worker is in broken state.')

        # task does not exist
        response = self._submit_assignment(self.clients[1], -1)
        self.assertEqual(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEqual(returned['message'], 'No task for given id')

        # user 0 can only submit a task not reject
        response = self._submit_assignment(self.clients[0],
                                           task.id,
                                           command='reject')
        self.assertEqual(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEqual(returned['message'], 'Task not in rejectable state.')

        # user 0 can't call illegal commands
        response = self._submit_assignment(self.clients[0],
                                           task.id,
                                           command='approve')
        self.assertEqual(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEqual(returned['message'], 'Illegal command')
        data = {'submit_key1': 'submit_val1'}

        # user 0 can't submit a task if its submission prerequisites aren't
        # complete
        step = task.step
        step.submission_depends_on = [
            Step.objects.create(
                workflow_version=step.workflow_version,
                slug='imaginary_test_step',
                is_human=True,
            )
        ]
        step.save()
        response = self._submit_assignment(self.clients[0], task.id)
        self.assertEqual(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEqual(returned['message'],
                         'Submission prerequisites are not complete.')
        step.submission_depends_on.set([])
        step.save()

        data = {'submit_key1': 'submit_val1'}
        # user 0 submits a task
        response = self._submit_assignment(self.clients[0], task.id, data=data)
        self.assertEqual(response.status_code, 200)

        self._verify_good_task_assignment_information(
            self.clients[0], {'task_id': task.id},
            task.project.short_description, 'Submitted', 'Pending Review',
            False, True, data, self.workers[0])

        # Check that iteration has correct submitted state
        verify_iterations(task.id)

        # user cannot resubmit a task
        response = self._submit_assignment(self.clients[0], task.id)
        self.assertEqual(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEqual(returned['message'],
                         'Worker is not allowed to submit')
Esempio n. 9
0
def setup_complete_task(test_case):
    # Microseconds are truncated when manually saving models
    test_start = timezone.now().replace(microsecond=0)
    times = {
        'awaiting_pickup': test_start,
        'entry_pickup': test_start + timedelta(hours=1),
        'entry_submit': test_start + timedelta(hours=2),
        'reviewer_pickup': test_start + timedelta(hours=3),
        'reviewer_reject': test_start + timedelta(hours=4),
        'entry_resubmit': test_start + timedelta(hours=5),
        'reviewer_accept': test_start + timedelta(hours=6),
    }

    task = TaskFactory(
        project=test_case.projects['empty_project'],
        status=Task.Status.AWAITING_PROCESSING,
        step=test_case.test_step,
        start_datetime=times['awaiting_pickup'])

    workers = {
        'entry': test_case.workers[0],
        'reviewer': test_case.workers[1]
    }

    assign_task(workers['entry'].id, task.id)

    task.refresh_from_db()
    test_case.assertEquals(task.status, Task.Status.PROCESSING)

    submit_task(
        task.id, {'test': 'entry_submit'},
        Iteration.Status.REQUESTED_REVIEW,
        workers['entry'])

    task.refresh_from_db()
    test_case.assertEquals(task.status, Task.Status.PENDING_REVIEW)

    assign_task(workers['reviewer'].id, task.id)
    reviewer_assignment = task.assignments.get(
        worker=workers['reviewer'])

    # Modify assignment with correct datetime
    reviewer_assignment.start_datetime = times['reviewer_pickup']
    reviewer_assignment.save()

    task.refresh_from_db()
    test_case.assertEquals(task.status, Task.Status.REVIEWING)

    submit_task(
        task.id, {'test': 'reviewer_reject'},
        Iteration.Status.PROVIDED_REVIEW,
        workers['reviewer'])

    task.refresh_from_db()
    test_case.assertEquals(task.status, Task.Status.POST_REVIEW_PROCESSING)

    submit_task(
        task.id, {'test': 'entry_resubmit'},
        Iteration.Status.REQUESTED_REVIEW,
        workers['entry'])

    task.refresh_from_db()
    test_case.assertEquals(task.status, Task.Status.REVIEWING)

    with patch('orchestra.utils.task_lifecycle._is_review_needed',
               return_value=False):
        submit_task(
            task.id, {'test': 'reviewer_accept'},
            Iteration.Status.REQUESTED_REVIEW,
            workers['reviewer'])

    task.refresh_from_db()
    test_case.assertEquals(task.status, Task.Status.COMPLETE)
    test_case.assertEquals(task.assignments.count(), 2)
    for assignment in task.assignments.all():
        test_case.assertEquals(
            assignment.status, TaskAssignment.Status.SUBMITTED)
        test_case.assertEquals(assignment.iterations.count(), 2)

    # Modify assignments with correct datetime
    new_datetime_labels = ('entry_pickup', 'reviewer_pickup')
    for i, assignment in enumerate(assignment_history(task).all()):
        assignment.start_datetime = times[new_datetime_labels[i]]
        assignment.save()

    # Modify iterations with correct datetime
    new_datetime_labels = (
        ('entry_pickup', 'entry_submit'),
        ('reviewer_pickup', 'reviewer_reject'),
        ('reviewer_reject', 'entry_resubmit'),
        ('entry_resubmit', 'reviewer_accept')
    )
    new_datetimes = [
        (times[start_label], times[end_label])
        for start_label, end_label in new_datetime_labels]

    for i, iteration in enumerate(get_iteration_history(task)):
        iteration.start_datetime, iteration.end_datetime = new_datetimes[i]
        iteration.save()

    verify_iterations(task.id)

    return task
Esempio n. 10
0
def _setup_tasks(test_case, tasks):
    # Create and assign tasks
    test_case.tasks = {}
    test_case.test_step = test_case.workflow_steps[
        test_case.test_version_slug][test_case.test_step_slug]
    for task_slug, details in tasks.items():
        task_pickup_time = BASE_DATETIME + timedelta(hours=1)
        task = TaskFactory(
            project=test_case.projects[details['project_name']],
            step=test_case.test_step,
            status=details['status'],
            start_datetime=task_pickup_time,
        )
        test_case.tasks[task_slug] = task
        for i, (user_id,
                task_data,
                assignment_status) in enumerate(details['assignments']):
            assignment = TaskAssignmentFactory(
                worker=test_case.workers[user_id],
                task=task,
                status=assignment_status,
                assignment_counter=i,
                in_progress_task_data=task_data,
                start_datetime=_new_assignment_start_datetime(task))

            # Each assignment must have at least one corresponding iteration
            Iteration.objects.create(
                assignment=assignment,
                start_datetime=assignment.start_datetime,
                end_datetime=assignment.start_datetime + ITERATION_DURATION,
                submitted_data=assignment.in_progress_task_data,
                status=Iteration.Status.REQUESTED_REVIEW)

            # Create time entry for each task.
            TimeEntryFactory(date='2016-04-04',
                             time_worked=timedelta(minutes=30),
                             assignment=assignment,
                             worker=test_case.workers[user_id],
                             description=(
                                 'test description {}'.format(assignment.id)))

        cur_assignment = current_assignment(task)
        assignments = assignment_history(task).all()
        if cur_assignment and (
                cur_assignment.status == TaskAssignment.Status.PROCESSING):
            # If there's a currently processing assignment, we'll need to
            # adjust the task's iteration sequence
            processing_counter = cur_assignment.assignment_counter
            if processing_counter != len(assignments) - 1:
                # If processing assignment is not the last in the hierarchy, we
                # need to reconstruct an iteration sequence: REQUESTED_REVIEW
                # up to the highest assignment counter, then PROVIDED_REVIEW
                # back down to the current assignment
                last_iteration = assignments.last().iterations.first()
                last_iteration.status = Iteration.Status.PROVIDED_REVIEW
                last_iteration.save()

                adjust_assignments = list(assignments)[processing_counter:-1]
                for assignment in reversed(adjust_assignments):
                    last_iteration = get_iteration_history(task).last()
                    Iteration.objects.create(
                        assignment=assignment,
                        start_datetime=last_iteration.end_datetime,
                        end_datetime=(
                            last_iteration.end_datetime + ITERATION_DURATION),
                        submitted_data=assignment.in_progress_task_data,
                        status=Iteration.Status.PROVIDED_REVIEW)

            # If there is a currently processing assignment, the task's last
            # iteration should still be processing
            last_iteration = get_iteration_history(task).last()
            last_iteration.end_datetime = None
            last_iteration.submitted_data = {}
            last_iteration.status = Iteration.Status.PROCESSING
            last_iteration.save()

        verify_iterations(task.id)
Esempio n. 11
0
    def test_submit_reviewer_task_assignment(self):
        data = {'submit_key1': 'submit_val1'}

        # user 1 is picking up a task as a reviewer
        response = (self.clients[1].get(
            '/orchestra/api/interface/new_task_assignment/reviewer/'))
        self.assertEquals(response.status_code, 200)
        returned = load_encoded_json(response.content)
        task_id = returned['id']
        task = Task.objects.get(id=returned['id'])
        self.assertEquals(task.assignments.count(), 2)
        self.assertEquals(task_id, self.tasks['review_task'].id)

        verify_iterations(task.id)

        rejected_data = {'rejected_key': 'rejected_val'}

        # user 0 can retrieve data, but should see a read-only interface
        self._verify_good_task_assignment_information(
            self.clients[0], {'task_id': task.id},
            task.project.short_description,
            'Submitted', 'Reviewing', False,
            True, {'test_key': 'test_value'}, self.workers[0])

        # user 1 should be able to review the post
        self._verify_good_task_assignment_information(
            self.clients[1], {'task_id': task.id},
            task.project.short_description,
            'Processing', 'Reviewing', True,
            False, {'test_key': 'test_value'}, self.workers[1])

        # user 1 rejects a task
        response = self._submit_assignment(
            self.clients[1], task_id, data=rejected_data, command='reject')
        self.assertEquals(response.status_code, 200)

        verify_iterations(task.id)

        # user 0 should have the task back
        self._verify_good_task_assignment_information(
            self.clients[0], {'task_id': task.id},
            task.project.short_description,
            'Processing', 'Post-review Processing', False,
            False, rejected_data, self.workers[0])

        # user 1 should no longer be able to modify the post
        self._verify_good_task_assignment_information(
            self.clients[1], {'task_id': task.id},
            task.project.short_description,
            'Submitted', 'Post-review Processing', True,
            True, rejected_data, self.workers[1])

        # user 0 submits an updated data
        response = self._submit_assignment(
            self.clients[0], task_id, data=data)
        self.assertEquals(response.status_code, 200)

        verify_iterations(task.id)

        # check if the data is saved
        self._verify_good_task_assignment_information(
            self.clients[1], {'task_id': task.id},
            task.project.short_description,
            'Processing', 'Reviewing', True,
            False, data, self.workers[1])

        accepted_data = {'accepted_key': 'accepted_val'}
        # user 1 accepts a task
        response = self._submit_assignment(
            self.clients[1], task_id, data=accepted_data, command='accept')
        self.assertEquals(response.status_code, 200)

        verify_iterations(task.id)

        # check if the accepted_data is saved
        # and task is pending for a second review.
        self._verify_good_task_assignment_information(
            self.clients[1], {'task_id': task.id},
            task.project.short_description,
            'Submitted', 'Pending Review', True,
            True, accepted_data, self.workers[1])

        # make sure a task can't be submitted twice
        response = self._submit_assignment(
            self.clients[1], task_id, command='accept')
        self.assertEquals(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEquals(returned['message'],
                          'Worker is not allowed to submit')

        # user 3 is picking up a task as a reviewer
        response = (self.clients[3].get(
            '/orchestra/api/interface/new_task_assignment/reviewer/'))
        self.assertEquals(response.status_code, 200)
        returned = load_encoded_json(response.content)
        self.assertEquals(returned['id'],
                          task.id)

        verify_iterations(task.id)

        rejected_data = {'rejected_key': 'rejected_val'}

        # user 3 rejects a task
        response = self._submit_assignment(
            self.clients[3], task_id, data=rejected_data, command='reject')
        self.assertEquals(response.status_code, 200)
        returned = load_encoded_json(response.content)

        verify_iterations(task.id)

        # check if the rejected_data is saved
        self._verify_good_task_assignment_information(
            self.clients[3], {'task_id': task.id},
            task.project.short_description,
            'Submitted', 'Post-review Processing', True,
            True, rejected_data, self.workers[3])

        # check client dashboards
        self._check_client_dashboard_state(self.clients[0], 'pending_review')

        self._check_client_dashboard_state(self.clients[1], 'returned')

        self._check_client_dashboard_state(self.clients[3],
                                           'pending_processing')

        response = self._submit_assignment(
            self.clients[1], task.id)
        self.assertEquals(response.status_code, 200)

        verify_iterations(task.id)

        # check if client dashboards were updated
        self._check_client_dashboard_state(self.clients[0], 'pending_review')

        self._check_client_dashboard_state(self.clients[1], 'pending_review')

        self._check_client_dashboard_state(self.clients[3], 'in_progress')

        # check if the accepted_data is saved
        response = self._submit_assignment(
            self.clients[3], task_id, data=accepted_data, command='accept')
        self.assertEquals(response.status_code, 200)
        returned = load_encoded_json(response.content)

        verify_iterations(task.id)

        # check if task is complete
        self._verify_good_task_assignment_information(
            self.clients[3], {'task_id': task.id},
            task.project.short_description,
            'Submitted', 'Complete', True,
            True, accepted_data, self.workers[3])

        # check that reviewer cannot reaccept task
        response = self._submit_assignment(
            self.clients[3], task_id, data=accepted_data, command='accept')
        self.assertEquals(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEquals(returned['message'],
                          'Task already completed')
Esempio n. 12
0
    def test_submit_entry_level_task_assignment(self):
        # user 0 only has certification for entry level tasks
        response = (self.clients[0].get(
            '/orchestra/api/interface/new_task_assignment/entry_level/'))
        self.assertEquals(response.status_code, 200)
        returned = load_encoded_json(response.content)
        task = Task.objects.get(id=returned['id'])

        verify_iterations(task.id)

        # user is not assigned to a task
        response = self._submit_assignment(self.clients[1], task.id)
        self.assertEquals(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEquals(returned['message'],
                          'Task assignment with worker is in broken state.')

        # task does not exist
        response = self._submit_assignment(self.clients[1], -1)
        self.assertEquals(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEquals(returned['message'],
                          'No task for given id')

        # user 0 can only submit a task not reject
        response = self._submit_assignment(
            self.clients[0], task.id, command='reject')
        self.assertEquals(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEquals(returned['message'],
                          'Task not in rejectable state.')

        # user 0 can't call illegal commands
        response = self._submit_assignment(
            self.clients[0], task.id, command='approve')
        self.assertEquals(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEquals(returned['message'],
                          'Illegal command')
        data = {'submit_key1': 'submit_val1'}

        # user 0 can't submit a task if its submission prerequisites aren't
        # complete
        step = task.step
        step.submission_depends_on = [
            Step.objects.create(
                workflow_version=step.workflow_version,
                slug='imaginary_test_step',
                is_human=True,
            )
        ]
        step.save()
        response = self._submit_assignment(
            self.clients[0], task.id)
        self.assertEquals(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEquals(returned['message'],
                          'Submission prerequisites are not complete.')
        step.submission_depends_on = []
        step.save()

        data = {'submit_key1': 'submit_val1'}
        # user 0 submits a task
        response = self._submit_assignment(
            self.clients[0], task.id, data=data)
        self.assertEquals(response.status_code, 200)

        self._verify_good_task_assignment_information(
            self.clients[0], {'task_id': task.id},
            task.project.short_description,
            'Submitted', 'Pending Review', False,
            True, data, self.workers[0])

        # Check that iteration has correct submitted state
        verify_iterations(task.id)

        # user cannot resubmit a task
        response = self._submit_assignment(
            self.clients[0], task.id)
        self.assertEquals(response.status_code, 400)
        returned = load_encoded_json(response.content)
        self.assertEquals(returned['message'],
                          'Worker is not allowed to submit')