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
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
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
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]
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)
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
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]
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()
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
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
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)
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
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
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
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]
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
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
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)
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
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
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]
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
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
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
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]
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
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
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
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
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
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
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
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()
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
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
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()
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
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]]
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
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
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
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
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'])
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'
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
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
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
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)
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)
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)
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
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
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()
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']
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
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)
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)
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'
def test_n_tasks_site_returns_number_of_total_tasks(self): TaskFactory.create_batch(2) tasks = stats.n_tasks_site() assert tasks == 2, tasks
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