Ejemplo n.º 1
0
    def test_serialization(self):
        project = ProjectFactory.create()
        self.db.session.commit()
        serializer = ProjectSerializer(strict=True)
        data = serializer.dump(project).data
        assert data['id'] == project.id
        assert data['name'] == project.name
        assert data['description'] == project.description
        assert data['last_task'] is None
        assert not data['tasks']
        assert data['client']['id'] == project.client.id

        task_1 = TaskFactory.create(project=project, status='open')
        task_2 = TaskFactory.create(project=project, status='closed')
        self.db.session.commit()

        # Last task
        data = serializer.dump(project).data
        assert data['last_task'] is not None
        assert data['last_task']['id'] == task_1.id
        assert data['last_task']['title'] == task_1.title
        assert 'time_entries' not in data['last_task']

        # Tasks (with filtering)
        data = ProjectSerializer(
            strict=True, task_status='open').dump(project).data
        assert len(data['tasks']) == 1
        assert data['tasks'][0]['id'] == task_1.id
        assert data['tasks'][0]['project_id'] == project.id
        data = ProjectSerializer(
            strict=True, task_status='closed').dump(project).data
        assert len(data['tasks']) == 1
        assert data['tasks'][0]['id'] == task_2.id
        assert data['tasks'][0]['project_id'] == project.id
Ejemplo n.º 2
0
    def test_task_query_with_params(self):
        """Test API query for task with params works"""
        project = ProjectFactory.create()
        TaskFactory.create_batch(10, project=project)
        # Test for real field
        res = self.app.get("/api/task?project_id=1")
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        assert data[0]['project_id'] == 1, data

        # Valid field but wrong value
        res = self.app.get("/api/task?project_id=99999999")
        data = json.loads(res.data)
        assert len(data) == 0, data

        # Multiple fields
        res = self.app.get('/api/task?project_id=1&state=ongoing')
        data = json.loads(res.data)
        # One result
        assert len(data) == 10, data
        # Correct result
        assert data[0]['project_id'] == 1, data
        assert data[0]['state'] == u'ongoing', data

        # Limits
        res = self.app.get("/api/task?project_id=1&limit=5")
        data = json.loads(res.data)
        for item in data:
            assert item['project_id'] == 1, item
        assert len(data) == 5, data
Ejemplo n.º 3
0
    def test_warn_project_excludes_completed_projects(self, clean_mock):
        """Test JOB email excludes completed projects."""
        from pybossa.core import mail
        with mail.record_messages() as outbox:
            date = '2010-10-22T11:02:00.000000'

            owner = UserFactory.create(consent=True, subscribed=True)
            project = ProjectFactory.create(updated=date, contacted=False,
                                            owner=owner)
            TaskFactory.create(created=date, project=project, state='completed')
            project_id = project.id
            project = project_repo.get(project_id)
            project.updated = date
            project_repo.update(project)

            project = ProjectFactory.create(updated=date, contacted=False,
                                            owner=owner)
            TaskFactory.create(created=date, project=project, state='ongoing')
            project_id = project.id
            project = project_repo.get(project_id)
            project.updated = date
            project_repo.update(project)

            warn_old_project_owners()
            assert len(outbox) == 1, outbox
            subject = 'Your PYBOSSA project: %s has been inactive' % project.name
            assert outbox[0].subject == subject
            err_msg = "project.contacted field should be True"
            assert project.contacted, err_msg
            err_msg = "project.published field should be False"
            assert project.published is False, err_msg
            err_msg = "cache of project should be cleaned"
            clean_mock.assert_called_with(project_id), err_msg
            err_msg = "The update date should be different"
            assert project.updated != date, err_msg
Ejemplo n.º 4
0
 def test_handle_info_json(self):
     """Test handle info in JSON works."""
     TaskFactory.create(info={'foo': 'bar'})
     info = 'foo::bar'
     res = self.task_repo.filter_tasks_by(info=info)
     assert len(res) == 1
     assert res[0].info['foo'] == 'bar', res[0]
Ejemplo n.º 5
0
    def test_admin_cannot_publish_if_project_has_no_presenter(self):
        """Test admins cannot publish a project that has no presenter"""
        owner = UserFactory.build_batch(2)[1]
        project = ProjectFactory.create(owner=owner, published=False, info={})
        TaskFactory.create(project=project)

        assert_raises(Forbidden, ensure_authorized_to, 'publish', project)
Ejemplo n.º 6
0
    def test_task_priority(self):
        """Test SCHED respects priority_0 field"""
        project = ProjectFactory.create(info=dict(sched='depth_first_all'),
                                        owner=UserFactory.create(id=500))

        TaskFactory.create_batch(10, project=project)

        # Register
        self.register()
        self.signin()

        # By default, tasks without priority should be ordered by task.id (FIFO)
        tasks = db.session.query(Task).filter_by(project_id=1).order_by('id').all()
        url = 'api/project/%s/newtask' % project.id
        res = self.app.get(url)
        task1 = json.loads(res.data)
        # Check that we received a Task
        err_msg = "Task.id should be the same"
        assert task1.get('id') == tasks[0].id, err_msg

        # Now let's change the priority to a random task
        import random
        t = random.choice(tasks)
        # Increase priority to maximum
        t.priority_0 = 1
        db.session.add(t)
        db.session.commit()
        # Request again a new task
        res = self.app.get(url + '?orderby=priority_0&desc=true')
        task1 = json.loads(res.data)
        # Check that we received a Task
        err_msg = "Task.id should be the same"
        assert task1.get('id') == t.id, err_msg
        err_msg = "Task.priority_0 should be the 1"
        assert task1.get('priority_0') == 1, err_msg
Ejemplo n.º 7
0
    def test_it_renders_template_when_get(self, fake_render):
        TaskFactory.create(project=self.project)
        resp = self.app.get('/project/%s/publish' % self.project.short_name)

        call_args = fake_render.call_args_list
        assert call_args[0][0][0] == 'projects/publish.html', call_args[0]
        assert call_args[0][1]['project'].id == self.project.id, call_args[0]
Ejemplo n.º 8
0
    def test_user_01_newtask(self):
        """ Test SCHED newtask returns a Task for John Doe User"""
        project = ProjectFactory.create(info=dict(sched='depth_first_all'),
                                        owner=UserFactory.create(id=500))

        TaskFactory.create_batch(2, project=project, n_answers=2)

        # Register
        self.register()
        self.signin()
        url = 'api/project/%s/newtask' % project.id
        res = self.app.get(url)
        data = json.loads(res.data)
        task_id = data['id']
        assert data['id'], data

        taskrun = dict(project_id=data['project_id'], task_id=data['id'], info="hola")
        res = self.app.post('api/taskrun', data=json.dumps(taskrun))

        res = self.app.get(url)
        data = json.loads(res.data)
        assert data['id'], data
        assert data['id'] != task_id, data
        
        self.signout()
Ejemplo n.º 9
0
    def test_n_total_tasks_site_returns_aggregated_number_of_required_tasks(self):
        TaskFactory.create(n_answers=2)
        TaskFactory.create(n_answers=2)

        tasks = stats.n_total_tasks_site()

        assert tasks == 4, tasks
Ejemplo n.º 10
0
    def test_project_published(self):
        owner = UserFactory.create(email_addr='*****@*****.**', pro=True)
        owner.set_password('1234')
        user_repo.save(owner)
        project = ProjectFactory.create(owner=owner, published=False)
        self.signin(email='*****@*****.**', password='******')
        TaskFactory.create(project=project)
        short_name = project.short_name

        url = "/project/%s/publish" % short_name

        attribute = 'published'

        new_string = 'true'

        old_value = 'false'

        self.data[attribute] = new_string

        self.app.post(url, follow_redirects=True)

        logs = auditlog_repo.filter_by(project_short_name=short_name)
        assert len(logs) == 1, logs
        for log in logs:
            assert log.attribute == attribute, log.attribute
            assert log.old_value == old_value, (log.old_value, old_value)
            assert log.new_value == self.data[attribute], log.new_value
            assert log.caller == 'web', log.caller
            assert log.action == 'update', log.action
            assert log.user_name == owner.name, log.user_name
            assert log.user_id == owner.id, log.user_id
Ejemplo n.º 11
0
    def test_orderby(self):
        """Test orderby."""
        project = ProjectFactory.create()
        task1 = TaskFactory.create(fav_user_ids=[1], project=project)
        task2 = TaskFactory.create(fav_user_ids=None, project=project)
        task3 = TaskFactory.create(fav_user_ids=[1, 2, 3], project=project)

        task = self.task_repo.filter_tasks_by(orderby='id', desc=True,
                                              project_id=project.id, limit=1)[0]
        assert task == task3, (task, task3)

        task = self.task_repo.filter_tasks_by(orderby='id', desc=False,
                                              project_id=project.id, limit=1)[0]
        assert task == task1, (task, task1)


        task = self.task_repo.filter_tasks_by(orderby='created', desc=True,
                                              project_id=project.id)[0]
        assert task == task3, (task.id, task3.id)

        task = self.task_repo.filter_tasks_by(orderby='created', desc=False,
                                              project_id=project.id)[0]
        assert task == task1, (task.created, task1.created)

        task = self.task_repo.filter_tasks_by(orderby='fav_user_ids', desc=True,
                                              project_id=project.id)[0][0]
        assert task == task3, (task.id, task3.id)

        task = self.task_repo.filter_tasks_by(orderby='fav_user_ids', desc=False,
                                              project_id=project.id)[0][0]
        assert task == task2, (task.fav_user_ids, task2.fav_user_ids)
Ejemplo n.º 12
0
    def test_task_preloading_limit(self):
        """Test TASK Pre-loading with limit works"""
        # Register
        project = ProjectFactory.create(info=dict(sched='depth_first_all'),
                                        owner=UserFactory.create(id=500))

        TaskFactory.create_batch(10, project=project)
        self.register()
        self.signin()

        assigned_tasks = []
        url = 'api/project/%s/newtask?limit=2' % project.id
        res = self.app.get(url)
        tasks1 = json.loads(res.data)
        # Check that we received a Task
        for t in tasks1:
            assert t.get('id'),  t
        # Pre-load the next tasks for the user
        res = self.app.get(url + '&offset=2')
        tasks2 = json.loads(res.data)
        # Check that we received a Task
        for t in tasks2:
            assert t.get('id'),  t
        # Check that both tasks are different
        tasks1_ids = set([t['id'] for t in tasks1])
        tasks2_ids = set([t['id'] for t in tasks2])
        assert len(tasks1_ids.union(tasks2_ids)) == 4, "Tasks should be different"
        ## Save the assigned task
        for t in tasks1:
            assigned_tasks.append(t)
        for t in tasks2:
            assigned_tasks.append(t)

        # Submit an Answer for the assigned and pre-loaded task
        for t in assigned_tasks:
            tr = dict(project_id=t['project_id'], task_id=t['id'], info={'answer': 'No'})
            tr = json.dumps(tr)

            self.app.post('/api/taskrun', data=tr)
        # Get two tasks again
        res = self.app.get(url)
        tasks3 = json.loads(res.data)
        # Check that we received a Task
        for t in tasks3:
            assert t.get('id'),  t
        # Pre-load the next task for the user
        res = self.app.get(url + '&offset=2')
        tasks4 = json.loads(res.data)
        # Check that we received a Task
        for t in tasks4:
            assert t.get('id'),  t
        # Check that both tasks are different
        tasks3_ids = set([t['id'] for t in tasks3])
        tasks4_ids = set([t['id'] for t in tasks4])
        assert len(tasks3_ids.union(tasks4_ids)) == 4, "Tasks should be different"

        # Check that a big offset returns None
        res = self.app.get(url + '&offset=11')
        assert json.loads(res.data) == {}, res.data
Ejemplo n.º 13
0
    def test_get_task_by_returns_none_if_no_task(self):
        """Test get_task_by returns None if no task matches the query"""

        TaskFactory.create(state='done')

        task = self.task_repo.get_task_by(state='ongoing')

        assert task is None, task
Ejemplo n.º 14
0
    def test_anonymous_01_newtask(self):
        """ Test SCHED newtask returns a Task for the Anonymous User"""
        project = ProjectFactory.create()
        TaskFactory.create(project=project, info='hola')

        res = self.app.get('api/project/%s/newtask' %project.id)
        data = json.loads(res.data)
        assert data['info'] == 'hola', data
Ejemplo n.º 15
0
 def test_handle_info_json_multiple_keys(self):
     """Test handle info in JSON with multiple keys works."""
     TaskFactory.create(info={'foo': 'bar', 'bar': 'foo'})
     info = 'foo::bar|bar::foo'
     res = self.task_repo.filter_tasks_by(info=info)
     assert len(res) == 1
     assert res[0].info['foo'] == 'bar', res[0]
     assert res[0].info['bar'] == 'foo', res[0]
Ejemplo n.º 16
0
    def test_it_changes_project_to_published_after_post(self):
        TaskFactory.create(project=self.project)
        resp = self.app.post('/project/%s/publish' % self.project.short_name,
                             follow_redirects=True)

        project = project_repo.get(self.project.id)
        assert resp.status_code == 200, resp.status_code
        assert project.published == True, project
Ejemplo n.º 17
0
    def test_count_tasks_with_no_matches(self):
        """Test count_tasks_with returns 0 if no tasks match the query"""

        TaskFactory.create(state='done', n_answers=17)

        count = self.task_repo.count_tasks_with(state='ongoing')

        assert count == 0, count
Ejemplo n.º 18
0
    def test_admin_can_publish_if_project_has_tasks_and_presenter(self):
        """Test admins can publish a project that has tasks and a presenter"""
        owner = UserFactory.build_batch(2)[1]
        project = ProjectFactory.create(owner=owner, published=False)
        TaskFactory.create(project=project)

        assert project.owner.id != self.mock_admin.id, project.owner
        assert_not_raises(Exception, ensure_authorized_to, 'publish', project)
Ejemplo n.º 19
0
 def test_query_favorites_anon(self):
     """Test API Favorites works for anon."""
     user = UserFactory.create()
     TaskFactory.create(fav_user_ids=[user.id])
     res = self.app.get(self.url)
     data = json.loads(res.data)
     assert res.status_code == 401
     assert data['status_code'] == 401
Ejemplo n.º 20
0
    def test_get_query_with_api_key_context(self):
        """ Test API GET query with an API-KEY requesting only APIKEY results."""
        users = UserFactory.create_batch(4)
        project_oc = ProjectFactory.create(owner=users[0], info={'total': 150})
        projects = ProjectFactory.create_batch(3, owner=users[1])
        task_oc = TaskFactory.create(project=project_oc, info={'url': 'my url'})
        taskrun_oc = TaskRunFactory.create(task=task_oc, user=users[0],
                                        info={'answer': 'annakarenina'})
        for p in projects:
            print p.owner_id
            task_tmp = TaskFactory.create(project=p)
            TaskRunFactory.create(task=task_tmp)

        # For project owner with associated data
        for endpoint in self.endpoints:
            url = '/api/' + endpoint + '?api_key=' + users[0].api_key
            res = self.app.get(url)
            data = json.loads(res.data)

            if endpoint == 'project':
                assert len(data) == 1, data
                project = data[0]
                assert project['owner_id'] == users[0].id, project['owner_id']
                assert project['info']['total'] == 150, data
                assert res.mimetype == 'application/json', res

            if endpoint == 'task':
                assert len(data) == 1, data
                task = data[0]
                assert task['project_id'] == project_oc.id, task
                assert task['info']['url'] == 'my url', data
                assert res.mimetype == 'application/json', res

            if endpoint == 'taskrun':
                assert len(data) == 1, data
                taskrun = data[0]
                assert taskrun['project_id'] == project_oc.id, taskrun
                assert taskrun['info']['answer'] == 'annakarenina', data
                assert res.mimetype == 'application/json', res

        # For authenticated with non-associated data
        for endpoint in self.endpoints:
            url = '/api/' + endpoint + '?api_key=' + users[3].api_key

            res = self.app.get(url)
            data = json.loads(res.data)

            if endpoint == 'project':
                assert len(data) == 0, data
                assert res.mimetype == 'application/json', res

            if endpoint == 'task':
                assert len(data) == 0, data
                assert res.mimetype == 'application/json', res

            if endpoint == 'taskrun':
                assert len(data) == 0, data
                assert res.mimetype == 'application/json', res
Ejemplo n.º 21
0
 def test_handle_info_json_multiple_keys_404_fulltextsearch(self):
     """Test handle info in JSON with full text
     search with multiple keys not found works."""
     TaskFactory.create(info={'foo': 'bar', 'bar': 'foo'})
     info = 'foo::bar|'
     res = self.task_repo.filter_tasks_by(info=info, fulltextsearch='1')
     assert len(res) == 1
     assert res[0].info['foo'] == 'bar', res[0]
     assert res[0].info['bar'] == 'foo', res[0]
Ejemplo n.º 22
0
    def test_filter_tasks_by_no_matches(self):
        """Test filter_tasks_by returns an empty list if no tasks match the query"""

        TaskFactory.create(state='done', n_answers=17)

        retrieved_tasks = self.task_repo.filter_tasks_by(state='ongoing')

        assert isinstance(retrieved_tasks, list)
        assert len(retrieved_tasks) == 0, retrieved_tasks
Ejemplo n.º 23
0
    def test_normal_auth_used_if_no_password_protected(self, fake_authorizer):
        """Test if a project is password protected, that is the only authorization
        required for it to be seen"""
        project = ProjectFactory.create()
        TaskFactory.create(project=project)

        self.app.get('/project/%s' % project.short_name, follow_redirects=True)

        assert fake_authorizer.called == True
Ejemplo n.º 24
0
    def test_count_tasks_with_multiple_conditions(self):
        """Test count_tasks_with supports multiple-condition queries"""

        TaskFactory.create(state='done', n_answers=17)
        task = TaskFactory.create(state='done', n_answers=99)

        count = self.task_repo.count_tasks_with(state='done', n_answers=99)

        assert count == 1, count
Ejemplo n.º 25
0
    def test_handle_info_json_multiple_keys_and_fulltextsearch(self):
        """Test handle info in JSON with multiple keys and AND operator works."""
        text = "agent myself you bar"
        TaskFactory.create(info={'foo': 'bar', 'bar': text})

        info = 'foo::bar|bar::you&agent'
        res = self.task_repo.filter_tasks_by(info=info, fulltextsearch='1')
        assert len(res) == 1, len(res)
        assert res[0].info['foo'] == 'bar', res[0]
        assert res[0].info['bar'] == text, res[0]
Ejemplo n.º 26
0
    def test_count_tasks_with_one_condition(self):
        """Test count_tasks_with returns the number of tasks that meet the
        filtering condition"""

        TaskFactory.create_batch(3, state='done')
        should_be_missing = TaskFactory.create(state='ongoing')

        count = self.task_repo.count_tasks_with(state='done')

        assert count == 3, count
Ejemplo n.º 27
0
    def test_n_draft_no_drafts(self):
        """Test CACHE PROJECTS _n_draft returns 0 if there are no draft projects"""
        # Here, we are suposing that a project is draft iff has no presenter AND has no tasks

        project = ProjectFactory.create(info={})
        TaskFactory.create_batch(2, project=project)

        number_of_drafts = cached_projects._n_draft()

        assert number_of_drafts == 0, number_of_drafts
Ejemplo n.º 28
0
    def test_browse_tasks_returns_all_tasks(self):
        """Test CACHE PROJECTS browse_tasks returns a list with all the tasks
        from a given project"""

        project = ProjectFactory.create()
        TaskFactory.create_batch(2, project=project)

        browse_tasks = cached_projects.browse_tasks(project.id)

        assert len(browse_tasks) == 2, browse_tasks
Ejemplo n.º 29
0
    def test_password_not_required_for_anonymous_users_to_see_project(self):
        """Test when an anonymous user wants to visit a non-password
        protected project is able to do it"""
        project = ProjectFactory.create()
        TaskFactory.create(project=project)

        for endpoint in self.endpoints_requiring_password:
            res = self.app.get('/project/%s%s' % (project.short_name, endpoint),
                               follow_redirects=True)
            assert 'Enter the password to contribute' not in res.data, endpoint
Ejemplo n.º 30
0
    def test_get_draft_not_returns_published_projects(self):
        """Test CACHE PROJECTS get_draft does not return projects with either tasks or a presenter (REVIEW DEFINITION OF A DRAFT PROJECT REQUIRED)"""

        project_no_presenter = ProjectFactory.create(info={})
        TaskFactory.create(project=project_no_presenter)
        project_no_task = ProjectFactory.create()

        drafts = cached_projects.get_draft()

        assert len(drafts) is 0, drafts
Ejemplo n.º 31
0
    def test_completedtask_completedtaskrun_with_params(self):
        """Test API query for completedtask and completedtaskrun with params works"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, n_answers=2,
                                  state='ongoing', exported=False)
        admin = UserFactory.create()
        # Test no completedtask yet
        url = '/api/completedtask?project_id=1&api_key=api-key1'
        res = self.app.get(url)
        data = json.loads(res.data)
        assert len(data) == 0, data

        # mark task as completed
        task_runs = TaskRunFactory.create_batch(2, task=task)
        task.state = 'completed'
        task_repo.update(task)

        #  test task is completed
        url = '/api/completedtask?project_id=1&api_key=api-key1'
        res = self.app.get(url)
        data = json.loads(res.data)

        # correct result
        assert data[0]['project_id'] == 1, data
        assert data[0]['state'] == u'completed', data

        # call completedtask but with wrong project_id
        url = '/api/completedtask?project_id=99999999&api_key=api-key1'
        res = self.app.get(url)
        data = json.loads(res.data)
        assert len(data) == 0, data

        # get completed task runs
        url = '/api/completedtaskrun?project_id=1&api_key=api-key1'
        res = self.app.get(url)
        data = json.loads(res.data)
        assert len(data) == 2, data
Ejemplo n.º 32
0
    def test_taskrun_post_with_bad_data(self):
        """Test API TaskRun error messages."""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)
        project_id = project.id
        task_run = dict(project_id=project.id,
                        task_id=task.id,
                        info='my task result')
        url = '/api/taskrun?api_key=%s' % project.owner.api_key

        # POST with not JSON data
        res = self.app.post(url, data=task_run)
        err = json.loads(res.data)
        assert res.status_code == 415, err
        assert err['status'] == 'failed', err
        assert err['target'] == 'taskrun', err
        assert err['action'] == 'POST', err
        assert err['exception_cls'] == 'ValueError', err

        # POST with not allowed args
        res = self.app.post(url + '&foo=bar', data=task_run)
        err = json.loads(res.data)
        assert res.status_code == 415, err
        assert err['status'] == 'failed', err
        assert err['target'] == 'taskrun', err
        assert err['action'] == 'POST', err
        assert err['exception_cls'] == 'AttributeError', err

        # POST with fake data
        task_run['wrongfield'] = 13
        res = self.app.post(url, data=json.dumps(task_run))
        err = json.loads(res.data)
        assert res.status_code == 415, err
        assert err['status'] == 'failed', err
        assert err['target'] == 'taskrun', err
        assert err['action'] == 'POST', err
        assert err['exception_cls'] == 'TypeError', err
Ejemplo n.º 33
0
 def test_05_app_stats_index(self):
     '''Test PRIVACY project stats privacy is respected'''
     # As Anonymou user
     admin, user, owner = UserFactory.create_batch(3)
     task = TaskFactory.create(n_answers=3)
     TaskRunFactory.create_batch(3, task=task)
     url = '/project/%s/stats' % task.project.short_name
     update_stats(task.project.id)
     res = self.app.get(url, follow_redirects=True)
     assert 'This feature requires being logged in' in res.data, res.data
     # As Authenticated user but NOT ADMIN
     res = self.app.get(url + '?api_key=%s' % user.api_key,
                        follow_redirects=True)
     dom = BeautifulSoup(res.data)
     err_msg = 'Project Stats page should not be shown to authenticated users'
     assert dom.find(id='enforce_privacy') is not None, err_msg
     self.signout
     # As Authenticated user but ADMIN
     res = self.app.get(url + '?api_key=%s' % admin.api_key,
                        follow_redirects=True)
     dom = BeautifulSoup(res.data)
     err_msg = 'Project Stats page should be shown to admin users'
     assert dom.find(id='enforce_privacy') is None, err_msg
     self.signout()
Ejemplo n.º 34
0
    def test_export_tasks_bucket(self, create_conn, mail):
        """Test JOB export_tasks to bucket works."""
        user = UserFactory.create(admin=True)
        project = ProjectFactory.create(name='test_project',
                                        info={'export-bucket': 'buck'})
        task = TaskFactory.create(project=project)
        task_run = TaskRunFactory.create(project=project, task=task)
        conn = create_conn.return_value
        buck = conn.get_bucket.return_value
        key = buck.new_key.return_value
        key.generate_url.return_value = 'https://s3.com/buck/key'

        with patch.dict(self.flask_app.config, {
                'EXPORT_MAX_SIZE': 0,
                'EXPORT_BUCKET': 'export-bucket'
        }):
            export_tasks(user.email_addr, project.short_name, 'consensus',
                         False, 'csv')
        args, kwargs = mail.send.call_args
        message = args[0]
        assert message.recipients[0] == user.email_addr, message.recipients
        assert message.subject == 'Data exported for your project: test_project', message.subject
        assert not message.attachments
        assert 'https://s3.com/buck/key' in message.html
Ejemplo n.º 35
0
    def test_taskrun_multipart(self, set_content):
        with patch.dict(self.flask_app.config, self.patch_config):
            project = ProjectFactory.create()
            task = TaskFactory.create(project=project)
            self.app.get('/api/project/%s/newtask?api_key=%s' %
                         (project.id, project.owner.api_key))
            data = dict(project_id=project.id,
                        task_id=task.id,
                        info={'field': 'value'})
            datajson = json.dumps(data)

            form = {
                'request_json': datajson,
                'test__upload_url': (StringIO('Hi there'), 'hello.txt')
            }

            url = '/api/taskrun?api_key=%s' % project.owner.api_key
            success = self.app.post(url,
                                    content_type='multipart/form-data',
                                    data=form)

            assert success.status_code == 200, success.data
            set_content.assert_called()
            res = json.loads(success.data)
            url = res['info']['test__upload_url']
            args = {
                'host': self.host,
                'bucket': self.bucket,
                'project_id': project.id,
                'task_id': task.id,
                'user_id': project.owner.id,
                'filename': 'hello.txt'
            }
            expected = 'https://{host}/{bucket}/{project_id}/{task_id}/{user_id}/{filename}'.format(
                **args)
            assert url == expected, url
Ejemplo n.º 36
0
    def test_taskrun_multipart_error(self, set_content):
        with patch.dict(self.flask_app.config, self.patch_config):
            project = ProjectFactory.create()
            task = TaskFactory.create(project=project)
            self.app.get('/api/project/%s/newtask?api_key=%s' %
                         (project.id, project.owner.api_key))

            data = dict(project_id=project.id,
                        task_id=task.id,
                        info={'field': 'value'})
            datajson = json.dumps(data)

            form = {
                'request_json': datajson,
                'test': (StringIO('Hi there'), 'hello.txt')
            }

            url = '/api/taskrun?api_key=%s' % project.owner.api_key
            success = self.app.post(url,
                                    content_type='multipart/form-data',
                                    data=form)

            assert success.status_code == 400, success.data
            set_content.assert_not_called()
Ejemplo n.º 37
0
    def test_it_deletes_project_taskruns_before_publishing(
            self, mock_task_repo, mock_result_repo, mock_webhook_repo):
        project = project_repo.get(self.project_id)
        task = TaskFactory.create(project=project, n_answers=1)
        TaskRunFactory.create(task=task)
        result = result_repo.get_by(project_id=task.project_id)
        assert not result, "There should not be a result"
        resp = self.app.post('/project/%s/1/publish' % project.short_name,
                             follow_redirects=True,
                             data={'force_reset': 'on'})

        taskruns = task_repo.filter_task_runs_by(project_id=project.id)

        repo_call = mock_task_repo.delete_taskruns_from_project.call_args_list[
            0][0][0]
        assert repo_call.id == project.id, repo_call

        mock_webhook_repo.assert_called_with(project)
        mock_result_repo.assert_called_with(project)

        # Try again
        resp = self.app.post('/project/%s/1/publish' % project.short_name,
                             follow_redirects=True)
        assert 'Project published' in resp.data, resp.data
Ejemplo n.º 38
0
    def test_update_row(self):
        answer_fields = {
            'hello': {
                'type': 'categorical',
                'config': {
                    'labels': ['A', 'B']
                }
            }
        }
        project = ProjectFactory.create(info={'answer_fields': answer_fields})
        task = TaskFactory.create(project=project,
                                  calibration=1,
                                  gold_answers={'hello': 'A'})
        task_run = TaskRunFactory.create(task=task, info={'hello': 'B'})
        stat = PerformanceStatsFactory.create(
            user_id=task_run.user_id,
            project_id=project.id,
            field='hello',
            info={'matrix': [[1, 4], [2, 3]]})

        update_gold_stats(task_run.user_id, task.id, task_run.dictize())
        stats = performance_repo.filter_by(project_id=project.id)
        assert len(stats) == 1
        assert stats[0].info['matrix'] == [[1, 5], [2, 3]]
Ejemplo n.º 39
0
    def test_no_more_tasks(self):
        """Test that a users gets always tasks"""
        owner = UserFactory.create()
        project = ProjectFactory.create(owner=owner, short_name='egil', name='egil',
                  description='egil')

        project_id = project.id

        tasks = TaskFactory.create_batch(20, project=project, n_answers=10)

        for t in tasks[0:10]:
            TaskRunFactory.create_batch(10, task=t, project=project)

        tasks = db.session.query(Task).filter_by(project_id=project.id, state='ongoing').all()
        assert tasks[0].n_answers == 10

        url = 'api/project/%s/newtask?api_key=%s' % (project.id, owner.api_key)
        res = self.app.get(url)
        data = json.loads(res.data)

        err_msg = "User should get a task"
        assert 'project_id' in data.keys(), err_msg
        assert data['project_id'] == project_id, err_msg
        assert data['id'] == tasks[0].id, err_msg
Ejemplo n.º 40
0
    def test_query_delete_favorites_auth(self):
        """Test API DEL Favorites works for user."""
        user = UserFactory.create()
        user2 = UserFactory.create()
        task = TaskFactory.create(fav_user_ids=[user.id, user2.id])

        url = self.url + '/%s?api_key=%s' % (task.id, user.api_key)
        res = self.app.delete(url)
        data = json.loads(res.data)
        assert res.status_code == 200, res.status_code
        assert user.id not in data['fav_user_ids'], data
        assert user2.id in data['fav_user_ids'], data

        url = self.url + '/%s?api_key=%s' % (task.id, user2.api_key)
        res = self.app.delete(url)
        data = json.loads(res.data)
        assert res.status_code == 200, res.status_code
        assert user.id not in data['fav_user_ids'], data
        assert user2.id not in data['fav_user_ids'], data

        url = self.url + '/%s?api_key=%s' % (task.id, user2.api_key)
        res = self.app.delete(url)
        data = json.loads(res.data)
        assert res.status_code == 404, res.status_code
Ejemplo n.º 41
0
    def test_taskrun_updates_task_state(self, guard, mock_request):
        """Test API TaskRun POST updates task state"""
        guard.return_value = mock_contributions_guard(True)
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, n_answers=2)
        url = '/api/taskrun?api_key=%s' % project.owner.api_key

        # Post first taskrun
        data = dict(project_id=task.project_id,
                    task_id=task.id,
                    user_id=project.owner.id,
                    info='my task result')
        datajson = json.dumps(data)
        mock_request.data = datajson

        tmp = self.app.post(url, data=datajson)
        r_taskrun = json.loads(tmp.data)

        assert tmp.status_code == 200, r_taskrun

        err_msg = "Task state should be different from completed"
        assert task.state == 'ongoing', err_msg

        # Post second taskrun
        mock_request.remote_addr = '127.0.0.0'
        url = '/api/taskrun'
        data = dict(project_id=task.project_id,
                    task_id=task.id,
                    info='my task result anon')
        datajson = json.dumps(data)
        tmp = self.app.post(url, data=datajson)
        r_taskrun = json.loads(tmp.data)

        assert tmp.status_code == 200, r_taskrun
        err_msg = "Task state should be equal to completed"
        assert task.state == 'completed', err_msg
Ejemplo n.º 42
0
    def test_get_query_with_api_key(self):
        """ Test API GET query with an API-KEY"""
        users = UserFactory.create_batch(3)
        app = AppFactory.create(owner=users[0], info={'total': 150})
        task = TaskFactory.create(app=app, info={'url': 'my url'})
        taskrun = TaskRunFactory.create(task=task,
                                        user=users[0],
                                        info={'answer': 'annakarenina'})
        for endpoint in self.endpoints:
            url = '/api/' + endpoint + '?api_key=' + users[1].api_key
            res = self.app.get(url)
            data = json.loads(res.data)

            if endpoint == 'app':
                assert len(data) == 1, data
                app = data[0]
                assert app['info']['total'] == 150, data
                assert res.mimetype == 'application/json', res

            if endpoint == 'task':
                assert len(data) == 1, data
                task = data[0]
                assert task['info']['url'] == 'my url', data
                assert res.mimetype == 'application/json', res

            if endpoint == 'taskrun':
                assert len(data) == 1, data
                taskrun = data[0]
                assert taskrun['info']['answer'] == 'annakarenina', data
                assert res.mimetype == 'application/json', res

            if endpoint == 'user':
                assert len(data) == 3, data
                user = data[0]
                assert user['name'] == 'user1', data
                assert res.mimetype == 'application/json', res
Ejemplo n.º 43
0
    def setUp(self):
        # Competition and creator
        self.creator = UserFactory(username='******', password='******')
        self.comp = CompetitionFactory(created_by=self.creator)
        self.phase = PhaseFactory(competition=self.comp)
        for _ in range(2):
            self.phase.tasks.add(TaskFactory.create())

        # Extra phase for testing tasks can't be run on the wrong phase
        self.other_phase = PhaseFactory(competition=self.comp)

        # URL and data for making submissions
        self.submission_url = reverse('submission-list')
        self.submission_data = {
            'phase':
            self.phase.id,
            'data':
            Data.objects.create(created_by=self.creator,
                                type=Data.SUBMISSION).key,
            'tasks':
            random.sample(
                list(self.phase.tasks.all().values_list('id', flat=True)), 2)
        }
        self.sorted_tasks = sorted(self.submission_data['tasks'])
Ejemplo n.º 44
0
    def test_completion_mode_all_questions(self):
        '''Test quiz does not end until all questions have been presented'''
        project, user = self.create_project_and_user(short_circuit=False)
        task_answers = {}
        quiz = project.get_quiz()

        for i in range(quiz['questions']):
            gold_answers = {'answer': i}
            golden_task = TaskFactory.create(project=project,
                                             n_answers=1,
                                             calibration=1,
                                             gold_answers=gold_answers)
            task_answers[golden_task.id] = gold_answers

        def submit_wrong_answer():
            new_task_url = '/api/project/{}/newtask'.format(project.id)
            new_task_response = self.app.get(new_task_url)
            task = json.loads(new_task_response.data)
            task_run_url = '/api/taskrun'
            task_run_data = {
                'project_id': project.id,
                'task_id': task['id'],
                'info': {
                    'answer': 'wrong'
                }
            }
            return self.app.post(task_run_url, data=json.dumps(task_run_data))

        for _ in range(quiz['questions'] - 1):
            submit_wrong_answer()
            updated_quiz = user.get_quiz_for_project(project)
            assert updated_quiz['status'] == 'in_progress'

        submit_wrong_answer()
        updated_quiz = user.get_quiz_for_project(project)
        assert updated_quiz['status'] == 'failed'
Ejemplo n.º 45
0
    def test_taskrun_post_requires_newtask_first_external_uid(self):
        """Test API TaskRun post fails if task was not previously requested for
        external user"""
        project = ProjectFactory.create()
        url = '/api/auth/project/%s/token' % project.short_name
        headers = {'Authorization': project.secret_key}
        token = self.app.get(url, headers=headers)
        headers['Authorization'] = 'Bearer %s' % token.data
        task = TaskFactory.create(project=project)
        data = dict(
            project_id=project.id,
            task_id=task.id,
            info='my task result',
            external_uid='1xa')
        datajson = json.dumps(data)
        fail = self.app.post('/api/taskrun', data=datajson, headers=headers)
        err = json.loads(fail.data)

        assert fail.status_code == 403, fail.status_code
        assert err['status'] == 'failed', err
        assert err['status_code'] == 403, err
        assert err['exception_msg'] == 'You must request a task first!', err
        assert err['exception_cls'] == 'Forbidden', err
        assert err['target'] == 'taskrun', err

        # Succeeds after requesting a task
        res = self.app.get('/api/project/%s/newtask?external_uid=1xa' % project.id)
        assert res.status_code == 401
        assert json.loads(res.data) == INVALID_HEADER_MISSING


        # Succeeds after requesting a task
        self.app.get('/api/project/%s/newtask?external_uid=1xa' % project.id,
                     headers=headers)
        success = self.app.post('/api/taskrun', data=datajson, headers=headers)
        assert success.status_code == 200, success.data
Ejemplo n.º 46
0
    def test_taskrun_post_requires_newtask_first_anonymous(self):
        """Test API TaskRun post fails if task was not previously requested for
        anonymous user"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)
        data = dict(
            project_id=project.id,
            task_id=task.id,
            info='my task result')
        datajson = json.dumps(data)
        fail = self.app.post('/api/taskrun', data=datajson)
        err = json.loads(fail.data)

        assert fail.status_code == 403, fail.status_code
        assert err['status'] == 'failed', err
        assert err['status_code'] == 403, err
        assert err['exception_msg'] == 'You must request a task first!', err
        assert err['exception_cls'] == 'Forbidden', err
        assert err['target'] == 'taskrun', err

        # Succeeds after requesting a task
        self.app.get('/api/project/%s/newtask' % project.id)
        success = self.app.post('/api/taskrun', data=datajson)
        assert success.status_code == 200, success.data
Ejemplo n.º 47
0
    def test_manual_migration_makes_submissions_out_of_only_parents_not_children(self):
        self.client.login(username='******', password='******')

        # make 1 submission with 4 children
        parent = SubmissionFactory(owner=self.creator, phase=self.phase_1, has_children=True, status=Submission.FINISHED)
        for _ in range(4):
            # Make a submission _and_ new Task for phase 2
            self.phase_2.tasks.add(TaskFactory())
            SubmissionFactory(owner=self.creator, phase=self.phase_1, parent=parent, status=Submission.FINISHED)

        assert self.phase_1.submissions.count() == 5
        assert self.phase_2.submissions.count() == 0

        # call "migrate" from phase 1 -> 2
        with mock.patch("competitions.tasks.run_submission") as run_submission_mock:
            url = reverse('phases-manually_migrate', kwargs={"pk": self.phase_1.pk})
            resp = self.client.post(url)
            assert resp.status_code == 200
            # Only 1 run here because parent has to create children
            assert run_submission_mock.call_count == 1

        # check phase 2 has the 1 parent submission
        assert self.phase_1.submissions.count() == 5
        assert self.phase_2.submissions.count() == 1
Ejemplo n.º 48
0
    def test_charts(self):
        """Test project chart"""
        return #to fix
        date_old = (datetime.datetime.utcnow() -  datetime.timedelta(30*36)).isoformat()
        date_4_mo = (datetime.datetime.utcnow() -  datetime.timedelta(120)).isoformat()
        date_3_mo = (datetime.datetime.utcnow() -  datetime.timedelta(90)).isoformat()
        date_2_mo = (datetime.datetime.utcnow() -  datetime.timedelta(60)).isoformat()
        date_1_mo = (datetime.datetime.utcnow() -  datetime.timedelta(30)).isoformat()
        expected_tasks = 6
        expected_categories = 2
        expected_projects = 4
        expected_taskruns = 5

        CategoryFactory.create(created=date_1_mo)
        CategoryFactory.create(created=date_2_mo)
        CategoryFactory.create(created=date_3_mo)

        ProjectFactory.create(created=date_1_mo)
        ProjectFactory.create(created=date_2_mo)
        ProjectFactory.create(created=date_3_mo)
        ProjectFactory.create(created=date_4_mo)
        ProjectFactory.create(created=date_old)

        TaskFactory.create(created=date_1_mo)
        TaskFactory.create(created=date_2_mo)
        TaskFactory.create(created=date_3_mo)

        TaskRunFactory.create(created=date_1_mo)
        TaskRunFactory.create(created=date_2_mo)
        TaskRunFactory.create(created=date_3_mo)
        TaskRunFactory.create(created=date_4_mo)
        TaskRunFactory.create(created=date_old)

        projects = stats.project_chart()
        assert projects['series'][0][24] == expected_projects, "{} projects created in last 24 months".format(expected_projects)
        categories = stats.category_chart()
        assert categories['series'][0][24] == expected_categories, "{} categories created in last 24 months".format(expected_categories)
        tasks = stats.task_chart()
        assert tasks['series'][0][24] == expected_tasks, "{} tasks created in last 24 months".format(expected_tasks)
        taskruns = stats.submission_chart()
        assert taskruns['series'][0][24] == expected_taskruns, "{} taskruns created in last 24 months".format(expected_taskruns)
Ejemplo n.º 49
0
    def test_avg_tasks_per_category(self):
        """Test average tasks per category created since current time"""
        date_recent = (datetime.datetime.utcnow() -  datetime.timedelta(31)).isoformat()
        date_now = (datetime.datetime.utcnow() -  datetime.timedelta(1)).isoformat()
        expected_avg_tasks = 3

        categories = CategoryFactory.create_batch(3)
        project1 = ProjectFactory.create(category=categories[0], created=date_now)
        project2 = ProjectFactory.create(category=categories[1], created=date_recent)
        project3 = ProjectFactory.create(category=categories[2], created=date_recent)

        for i in range(5):
            TaskFactory.create(project=project1, created=date_now)

        for i in range(2):
            TaskFactory.create(project=project2, created=date_recent)

        for i in range(3):
            TaskFactory.create(project=project3, created=date_recent)

        avg_tasks = round(stats.tasks_per_category())
        assert avg_tasks == expected_avg_tasks, "Average tasks created per category should be {}".format(expected_avg_tasks)
Ejemplo n.º 50
0
 def setUp(self):
     super(TestHateoas, self).setUp()
     project = ProjectFactory.create(published=True, id=1)
     task = TaskFactory.create(id=1, project=project)
     TaskRunFactory.create(project=project, task=task)
Ejemplo n.º 51
0
    def test_task_update(self):
        """Test API task update"""
        admin = UserFactory.create()
        user = UserFactory.create()
        non_owner = UserFactory.create()
        project = ProjectFactory.create(owner=user)
        task = TaskFactory.create(project=project)
        root_task = TaskFactory.create(project=project)
        data = {'n_answers': 1}
        datajson = json.dumps(data)
        root_data = {'n_answers': 4}
        root_datajson = json.dumps(root_data)

        # anonymous
        res = self.app.put('/api/task/%s' % task.id, data=data)
        assert_equal(res.status, '401 UNAUTHORIZED', res.status)
        # real user but not allowed as not owner!
        url = '/api/task/%s?api_key=%s' % (task.id, non_owner.api_key)
        res = self.app.put(url, data=datajson)
        assert_equal(res.status, '403 FORBIDDEN', res.status)

        # real user
        url = '/api/task/%s?api_key=%s' % (task.id, user.api_key)
        res = self.app.put(url, data=datajson)
        out = json.loads(res.data)
        assert_equal(res.status, '200 OK', res.data)
        assert_equal(task.n_answers, data['n_answers'])
        assert_equal(task.state, 'ongoing')
        assert task.id == out['id'], out

        # root
        res = self.app.put('/api/task/%s?api_key=%s' %
                           (root_task.id, admin.api_key),
                           data=root_datajson)
        assert_equal(res.status, '200 OK', res.data)
        assert_equal(root_task.n_answers, root_data['n_answers'])
        assert_equal(task.state, 'ongoing')

        # PUT with not JSON data
        res = self.app.put(url, data=data)
        err = json.loads(res.data)
        assert res.status_code == 415, err
        assert err['status'] == 'failed', err
        assert err['target'] == 'task', err
        assert err['action'] == 'PUT', err
        assert err['exception_cls'] == 'ValueError', err

        # PUT with not allowed args
        res = self.app.put(url + "&foo=bar", data=json.dumps(data))
        err = json.loads(res.data)
        assert res.status_code == 415, err
        assert err['status'] == 'failed', err
        assert err['target'] == 'task', err
        assert err['action'] == 'PUT', err
        assert err['exception_cls'] == 'AttributeError', err

        # PUT with fake data
        data['wrongfield'] = 13
        res = self.app.put(url, data=json.dumps(data))
        err = json.loads(res.data)
        assert res.status_code == 415, err
        assert err['status'] == 'failed', err
        assert err['target'] == 'task', err
        assert err['action'] == 'PUT', err
        assert err['exception_cls'] == 'TypeError', err
Ejemplo n.º 52
0
    def test_task_query_with_params_with_context(self):
        """Test API query for task with params works with context"""
        user = UserFactory.create()
        user_two = UserFactory.create()
        project_oc = ProjectFactory.create(owner=user)
        project_two = ProjectFactory.create()
        tasks = TaskFactory.create_batch(10, project=project_oc)
        TaskFactory.create_batch(10, project=project_two)
        # Test for real field
        res = self.app.get("/api/task?project_id=" + str(project_oc.id) +
                           "&api_key=" + user.api_key)
        data = json.loads(res.data)
        # Should return then results
        assert len(data) == 10, data
        # Correct result
        for t in data:
            assert t['project_id'] == project_oc.id, t

        res = self.app.get("/api/task?api_key=" + user.api_key + "&all=1")
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 20, data

        # Valid field but wrong value
        res = self.app.get("/api/task?project_id=99999999&api_key=" +
                           user.api_key)
        data = json.loads(res.data)
        assert len(data) == 0, data

        # Multiple fields
        res = self.app.get('/api/task?project_id=1&state=ongoing&api_key=' +
                           user.api_key)
        data = json.loads(res.data)
        # One result
        assert len(data) == 10, data
        # Correct result
        for t in data:
            assert t['project_id'] == project_oc.id, data
            assert t['state'] == u'ongoing', data

        # Limits
        res = self.app.get("/api/task?project_id=1&limit=5&api_key=" +
                           user.api_key)
        data = json.loads(res.data)
        assert len(data) == 5, data
        for item in data:
            assert item['project_id'] == project_oc.id, item

        # Keyset pagination
        url = "/api/task?project_id=1&limit=5&last_id=%s&api_key=%s" % (
            tasks[4].id, user.api_key)
        res = self.app.get(url)
        data = json.loads(res.data)
        assert len(data) == 5, data
        assert data[0]['id'] == tasks[5].id, data
        for item in data:
            assert item['project_id'] == project_oc.id, item

        # Test for real field with user_two
        res = self.app.get("/api/task?project_id=" + str(project_oc.id) +
                           "&api_key=" + user_two.api_key)
        data = json.loads(res.data)
        # Should return then results
        assert len(data) == 0, data
        # Test for real field with user_two
        res = self.app.get("/api/task?all=1&project_id=" + str(project_oc.id) +
                           "&api_key=" + user_two.api_key)
        data = json.loads(res.data)
        # Should return then results
        assert len(data) == 10, data
        # Correct result
        for t in data:
            assert t['project_id'] == project_oc.id, t

        res = self.app.get("/api/task?api_key=" + user_two.api_key + "&all=1")
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 20, data

        # Valid field but wrong value
        res = self.app.get("/api/task?project_id=99999999&api_key=" +
                           user_two.api_key)
        data = json.loads(res.data)
        assert len(data) == 0, data

        # Multiple fields
        res = self.app.get('/api/task?project_id=1&state=ongoing&api_key=' +
                           user_two.api_key)
        data = json.loads(res.data)
        # One result
        assert len(data) == 0, data
        res = self.app.get(
            '/api/task?all=1&project_id=1&state=ongoing&api_key=' +
            user_two.api_key)
        data = json.loads(res.data)
        # One result
        assert len(data) == 10, data
        # Correct result
        for t in data:
            assert t['project_id'] == project_oc.id, data
            assert t['state'] == u'ongoing', data

        # Limits
        res = self.app.get("/api/task?project_id=1&limit=5&api_key=" +
                           user_two.api_key)
        data = json.loads(res.data)
        assert len(data) == 0, data
        res = self.app.get("/api/task?all=1&project_id=1&limit=5&api_key=" +
                           user_two.api_key)
        data = json.loads(res.data)
        assert len(data) == 5, data
        for item in data:
            assert item['project_id'] == project_oc.id, item

        # Keyset pagination
        url = "/api/task?project_id=1&limit=5&last_id=%s&api_key=%s" % (
            tasks[4].id, user_two.api_key)
        res = self.app.get(url)
        data = json.loads(res.data)
        assert len(data) == 0, data
        url = "/api/task?all=1&project_id=1&limit=5&last_id=%s&api_key=%s" % (
            tasks[4].id, user_two.api_key)
        res = self.app.get(url)
        data = json.loads(res.data)
        assert len(data) == 5, data
        assert data[0]['id'] == tasks[5].id, data
        for item in data:
            assert item['project_id'] == project_oc.id, item
Ejemplo n.º 53
0
    def test_task_query_without_params(self):
        """ Test API Task query"""
        project = ProjectFactory.create()
        t1 = TaskFactory.create(created='2015-01-01T14:37:30.642119',
                                info={'question': 'answer'})
        tasks = TaskFactory.create_batch(8,
                                         project=project,
                                         info={'question': 'answer'})
        t2 = TaskFactory.create(created='2019-01-01T14:37:30.642119',
                                info={'question': 'answer'},
                                fav_user_ids=[1, 2, 3, 4])

        t3 = TaskFactory.create(created='2018-01-01T14:37:30.642119',
                                info={'question': 'answer'},
                                fav_user_ids=[1, 2])
        t4 = TaskFactory.create(fav_user_ids=[1])

        tasks.insert(0, t1)
        tasks.append(t2)
        tasks.append(t3)
        tasks.append(t4)

        res = self.app.get('/api/task')
        tasks = json.loads(res.data)
        assert len(tasks) == 12, tasks
        task = tasks[0]
        assert task['info']['question'] == 'answer', task

        # The output should have a mime-type: application/json
        assert res.mimetype == 'application/json', res

        # Desc filter
        url = "/api/task?desc=true"
        res = self.app.get(url)
        data = json.loads(res.data)
        err_msg = "It should get the last item first."
        assert data[0]['created'] == tasks[len(tasks) - 1]['created'], err_msg

        # Desc filter
        url = "/api/task?orderby=wrongattribute"
        res = self.app.get(url)
        data = json.loads(res.data)
        err_msg = "It should be 415."
        assert data['status'] == 'failed', data
        assert data['status_code'] == 415, data
        assert 'has no attribute' in data['exception_msg'], data

        # Desc filter
        url = "/api/task?orderby=id"
        res = self.app.get(url)
        data = json.loads(res.data)
        err_msg = "It should get the last item first."
        tasks_by_id = sorted(tasks, key=lambda x: x['id'], reverse=False)
        i = 0
        for t in tasks_by_id:
            assert tasks_by_id[i]['id'] == data[i]['id']
            i += 1

        # Desc filter
        url = "/api/task?orderby=id&desc=true"
        res = self.app.get(url)
        data = json.loads(res.data)
        err_msg = "It should get the last item first."
        tasks_by_id = sorted(tasks, key=lambda x: x['id'], reverse=True)
        i = 0
        for t in tasks_by_id:
            assert tasks_by_id[i]['id'] == data[i]['id']
            i += 1

        # fav_user_ids
        url = "/api/task?orderby=fav_user_ids&desc=true"
        res = self.app.get(url)
        data = json.loads(res.data)
        err_msg = "It should get the last item first."
        # print data
        assert data[0]['id'] == t2.id, err_msg

        # fav_user_ids
        url = "/api/task?orderby=fav_user_ids&desc=true&limit=1&offset=1"
        res = self.app.get(url)
        data = json.loads(res.data)
        err_msg = "It should get the last item first."
        assert data[0]['id'] == t3.id, err_msg
        url = "/api/task?orderby=fav_user_ids&desc=true&limit=1&offset=2"
        res = self.app.get(url)
        data = json.loads(res.data)
        err_msg = "It should get the last item first."
        assert data[0]['id'] == t4.id, err_msg

        # Related
        taskruns = TaskRunFactory.create_batch(8, project=project, task=t2)
        res = self.app.get('/api/task?id=' + str(t2.id) + '&related=True')
        data = json.loads(res.data)
        task = data[0]
        assert task['info']['question'] == 'answer', task
        assert len(task['task_runs']) == 8, task
        assert len(task['task_runs']) == len(taskruns), task
        assert task['result'] == None, task

        # Stats
        res = self.app.get("/api/task?limit=1&stats=True")
        data = json.loads(res.data)
        assert len(data) == 1, data
        assert 'stats' not in data[0].keys()
Ejemplo n.º 54
0
    def test_task_query_participated(self):
        """Test API Task query with participated arg."""
        admin, owner, user = UserFactory.create_batch(3)
        project = ProjectFactory.create(owner=owner)
        tasks1 = TaskFactory.create_batch(10,
                                          project=project,
                                          info=dict(foo='fox'))
        tasks2 = TaskFactory.create_batch(10,
                                          project=project,
                                          info=dict(foo='dog'))
        tasks = tasks1 + tasks2
        TaskRunFactory.create(task=tasks[0], user=user)
        TaskRunFactory.create(task=tasks[1], user=user)
        TaskRunFactory.create(task=tasks[2], user=user)

        url = '/api/task?api_key=%s&participated=1&all=1' % user.api_key

        res = self.app.get(url)
        data = json.loads(res.data)

        assert len(data) == 17, len(data)
        participated_tasks = [tasks[0].id, tasks[1].id, tasks[2].id]

        for task in data:
            assert task['id'] not in participated_tasks, task['id']

        # limit & offset
        url = '/api/task?api_key=%s&participated=1&all=1&limit=10&offset=10' % user.api_key

        res = self.app.get(url)
        data = json.loads(res.data)

        assert len(data) == 7, len(data)
        participated_tasks = [tasks[0].id, tasks[1].id, tasks[2].id]

        for task in data:
            assert task['id'] not in participated_tasks, task['id']

        # last_id
        url = '/api/task?api_key=%s&participated=1&all=1&last_id=%s' % (
            user.api_key, tasks[0].id)

        res = self.app.get(url)
        data = json.loads(res.data)

        assert len(data) == 17, len(data)
        participated_tasks = [tasks[0].id, tasks[1].id, tasks[2].id]

        for task in data:
            assert task['id'] not in participated_tasks, task['id']

        # orderby & desc
        url = '/api/task?api_key=%s&participated=1&all=1&orderby=created&desc=1' % user.api_key

        res = self.app.get(url)
        data = json.loads(res.data)

        assert len(data) == 17, len(data)
        participated_tasks = [tasks[0].id, tasks[1].id, tasks[2].id]

        assert data[0]['id'] == tasks[-1].id

        for task in data:
            assert task['id'] not in participated_tasks, task['id']

        # info & fulltextsearch
        url = '/api/task?api_key=%s&participated=1&all=1&orderby=created&desc=1&info=foo::fox&fulltextsearch=1' % user.api_key

        res = self.app.get(url)
        data = json.loads(res.data)

        assert len(data) == 7, len(data)
        participated_tasks = [tasks[0].id, tasks[1].id, tasks[2].id]

        assert data[0]['id'] == tasks1[-1].id

        for task in data:
            assert task['id'] not in participated_tasks, task['id']
Ejemplo n.º 55
0
    def test_taskrun_authenticated_external_uid_post(self, guard):
        """Test API TaskRun creation and auth for authenticated external uid"""
        guard.return_value = mock_contributions_guard(True)
        project = ProjectFactory.create()
        url = '/api/auth/project/%s/token' % project.short_name
        headers = {'Authorization': project.secret_key}
        token = self.app.get(url, headers=headers)
        headers['Authorization'] = 'Bearer %s' % token.data

        task = TaskFactory.create(project=project)
        data = dict(project_id=project.id,
                    task_id=task.id,
                    info='my task result',
                    external_uid='1xa')

        # With wrong project_id
        data['project_id'] = 100000000000000000
        datajson = json.dumps(data)
        url = '/api/taskrun?api_key=%s' % project.owner.api_key
        tmp = self.app.post(url, data=datajson, headers=headers)
        err_msg = "This post should fail as the project_id is wrong"
        err = json.loads(tmp.data)
        assert tmp.status_code == 403, err_msg
        assert err['status'] == 'failed', err_msg
        assert err['status_code'] == 403, err_msg
        assert err['exception_msg'] == 'Invalid project_id', err_msg
        assert err['exception_cls'] == 'Forbidden', err_msg
        assert err['target'] == 'taskrun', err_msg

        # With wrong task_id
        data['project_id'] = task.project_id
        data['task_id'] = 100000000000000000000
        datajson = json.dumps(data)
        tmp = self.app.post(url, data=datajson, headers=headers)
        err_msg = "This post should fail as the task_id is wrong"
        err = json.loads(tmp.data)
        assert tmp.status_code == 403, err_msg
        assert err['status'] == 'failed', err_msg
        assert err['status_code'] == 403, err_msg
        assert err['exception_msg'] == 'Invalid task_id', err_msg
        assert err['exception_cls'] == 'Forbidden', err_msg
        assert err['target'] == 'taskrun', err_msg

        # Now with everything fine
        data = dict(project_id=task.project_id,
                    task_id=task.id,
                    user_id=project.owner.id,
                    info='my task result',
                    external_uid='1xa')
        datajson = json.dumps(data)
        # But without authentication
        tmp = self.app.post(url, data=datajson)
        r_taskrun = json.loads(tmp.data)
        assert tmp.status_code == 403, r_taskrun

        tmp = self.app.post(url, data=datajson, headers=headers)
        r_taskrun = json.loads(tmp.data)
        assert tmp.status_code == 200, r_taskrun

        # If the user tries again it should be forbidden
        tmp = self.app.post(url, data=datajson, headers=headers)
        assert tmp.status_code == 403, tmp.data
Ejemplo n.º 56
0
    def test_taskrun_update(self):
        """Test TaskRun API update works"""
        admin = UserFactory.create()
        owner = UserFactory.create()
        non_owner = UserFactory.create()
        project = ProjectFactory.create(owner=owner)
        task = TaskFactory.create(project=project)
        anonymous_taskrun = AnonymousTaskRunFactory.create(
            task=task, info='my task result')
        user_taskrun = TaskRunFactory.create(task=task,
                                             user=owner,
                                             info='my task result')

        task_run = dict(project_id=project.id,
                        task_id=task.id,
                        info='another result')
        datajson = json.dumps(task_run)

        # anonymous user
        # No one can update anonymous TaskRuns
        url = '/api/taskrun/%s' % anonymous_taskrun.id
        res = self.app.put(url, data=datajson)
        assert anonymous_taskrun, anonymous_taskrun
        assert_equal(anonymous_taskrun.user, None)
        error_msg = 'Should not be allowed to update'
        assert_equal(res.status, '401 UNAUTHORIZED', error_msg)

        # real user but not allowed as not owner!
        url = '/api/taskrun/%s?api_key=%s' % (user_taskrun.id,
                                              non_owner.api_key)
        res = self.app.put(url, data=datajson)
        error_msg = 'Should not be able to update TaskRuns of others'
        assert_equal(res.status, '403 FORBIDDEN', error_msg)

        # real user
        url = '/api/taskrun/%s?api_key=%s' % (user_taskrun.id, owner.api_key)
        out = self.app.get(url, follow_redirects=True)
        task = json.loads(out.data)
        datajson = json.loads(datajson)
        datajson['link'] = task['link']
        datajson['links'] = task['links']
        datajson = json.dumps(datajson)
        url = '/api/taskrun/%s?api_key=%s' % (user_taskrun.id, owner.api_key)
        res = self.app.put(url, data=datajson)
        out = json.loads(res.data)
        assert_equal(res.status, '403 FORBIDDEN', res.data)

        # PUT with not JSON data
        res = self.app.put(url, data=task_run)
        err = json.loads(res.data)
        assert res.status_code == 403, err
        assert err['status'] == 'failed', err
        assert err['target'] == 'taskrun', err
        assert err['action'] == 'PUT', err
        assert err['exception_cls'] == 'Forbidden', err

        # PUT with not allowed args
        res = self.app.put(url + "&foo=bar", data=json.dumps(task_run))
        err = json.loads(res.data)
        assert res.status_code == 415, err
        assert err['status'] == 'failed', err
        assert err['target'] == 'taskrun', err
        assert err['action'] == 'PUT', err
        assert err['exception_cls'] == 'AttributeError', err

        # PUT with fake data
        task_run['wrongfield'] = 13
        res = self.app.put(url, data=json.dumps(task_run))
        err = json.loads(res.data)
        assert res.status_code == 403, err
        assert err['status'] == 'failed', err
        assert err['target'] == 'taskrun', err
        assert err['action'] == 'PUT', err
        assert err['exception_cls'] == 'Forbidden', err
        task_run.pop('wrongfield')

        # root user
        url = '/api/taskrun/%s?api_key=%s' % (user_taskrun.id, admin.api_key)
        res = self.app.put(url, data=datajson)
        assert_equal(res.status, '403 FORBIDDEN', res.data)
Ejemplo n.º 57
0
 def setUp(self):
     super(TestStats, self).setUp()
     self.project = AppFactory.create()
     for task in TaskFactory.create_batch(4, app=self.project, n_answers=3):
         TaskRunFactory.create(task=task)
         AnonymousTaskRunFactory.create(task=task)
Ejemplo n.º 58
0
    def test_locked_sched_gold_task(self, mock_random):
        """ Test gold tasks presented with locked scheduler """

        [admin, owner, user] = UserFactory.create_batch(3)
        make_admin(admin)
        make_subadmin(owner)

        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        tasks = TaskFactory.create_batch(4, project=project, n_answers=1)
        gold_task = tasks[3]
        gold_task.calibration = 1
        gold_task.gold_answers = dict(field_3='someans')

        # gold task to be presented to the user when available with randomness
        # set to a value (to zero) that means gold task to be presented
        mock_random.return_value = 0
        # user #1
        self.set_proj_passwd_cookie(project, user)
        res = self.app.get('api/project/{}/newtask?api_key={}'.format(
            project.id, user.api_key))
        assert res.status_code == 200, res.status_code
        resp = json.loads(res.data)
        assert resp['id'] == gold_task.id, \
            'task presented to regular user under locked sched should be gold task'
        # submit answer for gold task
        task_run = dict(project_id=project.id,
                        task_id=gold_task.id,
                        info='hi there!')
        res = self.app.post('api/taskrun?api_key={}'.format(user.api_key),
                            data=json.dumps(task_run))
        assert res.status_code == 200, res.status_code

        # user #2 also gets gold_task even when redundancy was set to 1
        res = self.app.get('api/project/{}/newtask?api_key={}'.format(
            project.id, owner.api_key))
        assert res.status_code == 200, res.status_code
        resp = json.loads(res.data)
        assert resp['id'] == gold_task.id, \
            'task presented to owner under locked sched should be gold task'

        # after two task run submissions for gold task, state is unchanged to ongoing
        task_run = dict(project_id=project.id,
                        task_id=gold_task.id,
                        info='hi there!')
        res = self.app.post('api/taskrun?api_key={}'.format(owner.api_key),
                            data=json.dumps(task_run))
        assert res.status_code == 200, res.status_code
        res = self.app.get('api/task/{}?api_key={}'.format(
            gold_task.id, admin.api_key))
        assert res.status_code == 200, res.status_code
        resp = json.loads(res.data)
        assert resp['id'] == gold_task.id and resp['state'] == 'ongoing', \
            'gold task state should be unchanged to ongoing'

        # user #3 don't receive gold_task when randomness is not zero
        mock_random.return_value = 1
        res = self.app.get('api/project/{}/newtask?api_key={}'.format(
            project.id, admin.api_key))
        assert res.status_code == 200, res.status_code
        resp = json.loads(res.data)
        assert resp['id'] == tasks[0].id, \
            'task presented should not be gold task'
Ejemplo n.º 59
0
    def test_n_tasks_site_returns_number_of_total_tasks(self):
        TaskFactory.create_batch(2)

        tasks = stats.n_tasks_site()

        assert tasks == 2, tasks
Ejemplo n.º 60
0
    def test_export_tasks_csv_json(self, mail):
        """Test JOB export_tasks task csv works."""
        user = UserFactory.create(admin=True)
        project = ProjectFactory.create(name='test_project')
        task = TaskFactory.create(project=project)
        task_run = TaskRunFactory.create(project=project, task=task)

        export_tasks(user.email_addr, project.short_name, 'task', False, 'csv')
        args, kwargs = mail.send.call_args
        message = args[0]
        assert message.recipients[0] == user.email_addr, message.recipients
        assert message.subject == 'Data exported for your project: test_project', message.subject

        attachment = message.attachments[0]
        proj_name = unidecode(project.short_name)
        filename = '{}_{}'.format(project.id, proj_name)
        assert attachment.filename == '{}_task_csv.zip'.format(filename)

        export_tasks(user.email_addr, project.short_name, 'task', False,
                     'json')
        args, kwargs = mail.send.call_args
        message = args[0]
        assert message.recipients[0] == user.email_addr, message.recipients
        assert message.subject == 'Data exported for your project: test_project', message.subject

        attachment = message.attachments[0]
        assert attachment.filename == '{}_task_json.zip'.format(filename)

        export_tasks(user.email_addr, project.short_name, 'task_run', False,
                     'csv')
        args, kwargs = mail.send.call_args
        message = args[0]
        assert message.recipients[0] == user.email_addr, message.recipients
        assert message.subject == 'Data exported for your project: test_project', message.subject

        attachment = message.attachments[0]
        assert attachment.filename == '{}_task_run_csv.zip'.format(filename)

        export_tasks(user.email_addr, project.short_name, 'task_run', False,
                     'json')
        args, kwargs = mail.send.call_args
        message = args[0]
        assert message.recipients[0] == user.email_addr, message.recipients
        assert message.subject == 'Data exported for your project: test_project', message.subject

        attachment = message.attachments[0]
        assert attachment.filename == '{}_task_run_json.zip'.format(filename)

        filters = dict(task_id=1,
                       hide_completed=True,
                       pcomplete_from='2018-01-01T00:00:00.0001',
                       pcomplete_to='2018-12-12T00:00:00.0001',
                       priority_from=0.0,
                       priority_to=0.5,
                       created_from='2018-01-01T00:00:00.0001',
                       created_to='2018-12-12T00:00:00.0001')

        filters = {
            'display_info_columns': [],
            'pcomplete_from': 0.0,
            'pcomplete_to': 0.45
        }
        export_tasks(user.email_addr, project.short_name, 'task', False, 'csv',
                     filters)
        args, kwargs = mail.send.call_args
        message = args[0]
        assert message.recipients[0] == user.email_addr, message.recipients
        assert message.subject == 'Data exported for your project: test_project', message.subject

        export_tasks(user.email_addr, project.short_name, 'task', False,
                     'json', filters)
        args, kwargs = mail.send.call_args
        message = args[0]
        assert message.recipients[0] == user.email_addr, message.recipients
        assert message.subject == 'Data exported for your project: test_project', message.subject