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_n_published_counts_published_projects(self): published_project = ProjectFactory.create_batch(2, published=True) ProjectFactory.create(published=False) number_of_published = cached_projects.n_published() assert number_of_published == 2, number_of_published
def test_filter_by_one_condition(self): """Test filter_by returns a list of logs that meet the filtering condition""" project = ProjectFactory.create() AuditlogFactory.create_batch( size=3, project_id=project.id, project_short_name=project.short_name, user_id=project.owner.id, user_name=project.owner.name, ) project2 = ProjectFactory.create() should_be_missing = AuditlogFactory.create_batch( size=3, project_id=project2.id, project_short_name=project2.short_name, user_id=project2.owner.id, user_name=project2.owner.name, ) retrieved_logs = self.auditlog_repo.filter_by(user_id=project.owner.id) assert len(retrieved_logs) == 3, retrieved_logs assert should_be_missing not in retrieved_logs, retrieved_logs
def test_n_featured_returns_featured(self): """Test CACHE PROJECTS _n_featured returns number of featured projects""" ProjectFactory.create(featured=True) number_of_featured = cached_projects._n_featured() assert number_of_featured == 1, number_of_featured
def test_blogpost_update_errors(self): """Test blogposts update for non existing projects raises errors""" self.register() user = user_repo.get(1) project1 = ProjectFactory.create(owner=user) project2 = ProjectFactory.create(owner=user) blogpost = BlogpostFactory.create(project=project1, body='body') # To a non-existing project url = "/project/non-existing-project/%s/update" % blogpost.id res = self.app.post(url, data={'title':'new title', 'body':'body'}, follow_redirects=True) assert res.status_code == 404, res.status_code # To a non-existing post url = "/project/%s/999999/update" % project1.short_name res = self.app.post(url, data={'title':'new title', 'body':'body'}, follow_redirects=True) assert res.status_code == 404, res.status_code # To an existing post but with a project in the URL it does not belong to url = "/project/%s/%s/update" % (project2.short_name, blogpost.id) res = self.app.post(url, data={'title':'new title', 'body':'body'}, follow_redirects=True) assert res.status_code == 404, res.status_code
def test_get_featured_returns_required_fields(self): """Test CACHE PROJECTS get_featured returns the required info about each featured project""" fields = ( "id", "name", "short_name", "info", "created", "description", "last_activity", "last_activity_raw", "overall_progress", "n_tasks", "n_volunteers", "owner", "info", "updated", ) ProjectFactory.create(featured=True) featured = cached_projects.get_featured()[0] for field in fields: assert featured.has_key(field), "%s not in project info" % field
def test_get_by_returns_none_if_no_project(self): """Test get_by returns None if no project matches the query""" ProjectFactory.create(name='My Project', short_name='myproject') project = self.project_repo.get_by(name='no_name') assert project is None, project
def test_get_featured(self): """Test CACHE PROJECTS get_featured returns featured projects""" ProjectFactory.create(featured=True) featured = cached_projects.get_featured() assert len(featured) is 1, featured
def test_get_dont_return_projects_with_password(self): """Test CACHE PROJECTS get does not return projects with a password""" project = ProjectFactory.create(published=True, info={'passwd_hash': '2'}) ProjectFactory.create(category=project.category, published=True) projects = cached_projects.get(project.category.short_name) assert len(projects) is 1, projects
def test_get_only_return_published(self): """Test CACHE PROJECTS get returns only published projects""" project = ProjectFactory.create(published=True) ProjectFactory.create(category=project.category, published=False) projects = cached_projects.get(project.category.short_name) assert len(projects) is 1, projects
def test_get_used_returns_only_categories_with_projects(self): used_category = CategoryFactory.create() ProjectFactory.create(category=used_category) unused_category = CategoryFactory.create() used_categories = cached_categories.get_used() assert used_categories[0]["id"] == used_category.id, used_categories
def test_get_draft_not_returns_hidden_projects(self): """Test CACHE PROJECTS get_draft does not return hidden projects""" ProjectFactory.create(info={}, hidden=1) drafts = cached_projects.get_draft() assert len(drafts) is 0, drafts
def test_n_count_with_password_protected_projects(self): """Test CACHE PROJECTS n_count returns the number of published projects of a given category, excluding projects with a password""" project = ProjectFactory.create(published=True, info={'passwd_hash': '2'}) ProjectFactory.create(category=project.category, published=True) n_projects = cached_projects.n_count(project.category.short_name) assert n_projects == 1, n_projects
def test_get_only_returns_projects_from_category(self): """Test CACHE PROJECTS get returns only projects from required category""" project = ProjectFactory.create(published=True) ProjectFactory.create(published=True) projects = cached_projects.get(project.category.short_name) assert len(projects) is 1, projects
def test_filter_by_no_matches(self): """Test filter_by returns an empty list if no projects match the query""" ProjectFactory.create(name='My Project', short_name='myproject') retrieved_projects = self.project_repo.filter_by(name='no_name') assert isinstance(retrieved_projects, list) assert len(retrieved_projects) == 0, retrieved_projects
def test_get_from_pro_user_projects_no_projects(self): """Test CACHE PROJECTS get_from_pro_user returns empty list if no projects with 'pro' owners""" pro_user = UserFactory.create(pro=True) ProjectFactory.create() pro_owned_projects = cached_projects.get_from_pro_user() assert pro_owned_projects == [], pro_owned_projects
def test_get_draft(self): """Test CACHE PROJECTS get_draft returns draft_projects""" # Here, we are suposing that a project is draft iff has no presenter AND has no tasks ProjectFactory.create(info={}) drafts = cached_projects.get_draft() assert len(drafts) is 1, drafts
def test_get_featured_only_returns_featured(self): """Test CACHE PROJECTS get_featured returns only featured projects""" featured_project = ProjectFactory.create(featured=True) non_featured_project = ProjectFactory.create() featured = cached_projects.get_featured() assert len(featured) is 1, featured
def test_autoimport_jobs_without_pro(self): """Test JOB autoimport jobs works without pro users.""" ProjectFactory.create() jobs_generator = get_autoimport_jobs() jobs = [] for job in jobs_generator: jobs.append(job) msg = "There should be 0 jobs." assert len(jobs) == 0, msg
def test_get_only_returns_category_projects(self): """Test CACHE PROJECTS get returns only projects from required category""" project = self.create_project_with_tasks(1, 0) #create a non published project too ProjectFactory.create() projects = cached_projects.get(project.category.short_name) assert len(projects) is 1, projects
def test_get_used_returns_requiered_fields(self): used_category = CategoryFactory.create() ProjectFactory.create(category=used_category) fields = ("id", "name", "short_name", "description") used_categories = cached_categories.get_used() for field in fields: assert field in used_categories[0].keys() assert len(fields) == len(used_categories[0].keys())
def test_get_project_jobs_for_non_pro_users(self): """Test JOB get project jobs works for non pro users.""" ProjectFactory.create() jobs_generator = get_project_jobs() jobs = [] for job in jobs_generator: jobs.append(job) err_msg = "There should be only 0 jobs" assert len(jobs) == 0, err_msg
def test_get_from_pro_users_returns_required_fields(self): """Test CACHE PROJECTS get_from_pro_user returns required fields""" pro_user = UserFactory.create(pro=True) ProjectFactory.create(owner=pro_user) fields = ('id', 'short_name') pro_owned_projects = cached_projects.get_from_pro_user() for field in fields: assert field in pro_owned_projects[0].keys(), field
def test_get_not_returns_draft_projects(self): """Test CACHE PROJECTS get does not return draft (non-published) projects""" project = self.create_project_with_contributors(1, 0) # Create a project wothout presenter ProjectFactory.create(info={}, category=project.category) projects = cached_projects.get(project.category.short_name) assert len(projects) is 1, projects
def test_published_projects_only_returns_published(self): """Test CACHE USERS published_projects does not return draft or another user's projects""" user = UserFactory.create() another_user_published_project = ProjectFactory.create(published=True) draft_project = ProjectFactory.create(owner=user, published=False) projects_published = cached_users.published_projects(user.id) assert len(projects_published) == 0, projects_published
def test_draft_projects_only_returns_drafts(self): """Test CACHE USERS draft_projects does not return any pubished projects or drafts that belong to another user""" user = UserFactory.create() published_project = ProjectFactory.create(owner=user, published=True) other_users_draft_project = ProjectFactory.create(published=False) draft_projects = cached_users.draft_projects(user.id) assert len(draft_projects) == 0, draft_projects
def test_n_count_with_published_projects(self): """Test CACHE PROJECTS n_count returns the number of published projects of a given category""" project = self.create_project_with_tasks(1, 0) #create a non published project too ProjectFactory.create() n_projects = cached_projects.n_count(project.category.short_name) assert n_projects == 1, n_projects
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_n_count_with_published_projects(self): """Test CACHE PROJECTS n_count returns the number of published projects of a given category""" project = ProjectFactory.create(published=True) ProjectFactory.create(published=True) ProjectFactory.create(category=project.category, published=False) n_projects = cached_projects.n_count(project.category.short_name) assert n_projects == 1, n_projects
def test_get_from_pro_user_projects(self): """Test CACHE PROJECTS get_from_pro_user returns list of projects with 'pro' owners only""" pro_user = UserFactory.create(pro=True) ProjectFactory.create() pro_project = ProjectFactory.create(owner=pro_user) pro_owned_projects = cached_projects.get_from_pro_user() assert len(pro_owned_projects) is 1, len(pro_owned_projects) assert pro_owned_projects[0]['short_name'] == pro_project.short_name
def test_sync_L2_without_target(self, mock_cat): project_syncer = ProjectSyncer(self.target_url, self.target_key) user = UserFactory.create(admin=True, email_addr=u'*****@*****.**') project_syncer.syncer = user project = ProjectFactory.create() project.info['data_classification'] = dict( input_data="L2 - propriertary valid", output_data="L2 - propriertary valid") project_repo.save(project) # no sync info by default assert not project.info.get("sync") payload = project_syncer._build_payload(project) # sync existing does put request headers = [('Authorization', user.api_key)] res = self.app.put("/api/project/{}".format(project.id), headers=headers, data=json.dumps(payload)) assert res.status_code == 200, 'build_payload output should result in valid api query' assert res.json["info"]["sync"] == payload["info"]["sync"]
def test_trigger_fails_webhook_with_no_url(self, mock_post, mock_send_mail): """Test WEBHOOK fails and sends email is triggered when no URL or failed connection.""" mock_post.side_effect = requests.exceptions.ConnectionError('Not URL') project = ProjectFactory.create(published=True) payload = dict( event='task_completed', project_short_name=project.short_name, project_id=project.id, task_id=1, result_id=1, fired_at=datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")) wbh = WebhookFactory.create() tmp = webhook(None, payload=payload, oid=wbh.id) headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} #mock_post.assert_called_with('url', data=json.dumps(payload), headers=headers) subject = "Broken: %s webhook failed" % project.name body = 'Sorry, but the webhook failed' mail_dict = dict(recipients=self.flask_app.config.get('ADMINS'), subject=subject, body=body, html=tmp.response) mock_send_mail.assert_called_with(mail_dict)
def test_blogpost_get_one_draft(self): """Test blogpost GET draft with id shows one blogpost""" user = self.create_users()[1] project = ProjectFactory.create(owner=user) blogpost = BlogpostFactory.create(project=project, title='title', published=False) url = "/project/%s/%s" % (project.short_name, blogpost.id) # As anonymous res = self.app.get(url, follow_redirects=True) assert res.status_code == 404, res.status_code # As authenticated self.register() res = self.app.get(url, follow_redirects=True) assert res.status_code == 404, res.status_code # As owner url = "/project/%s/%s?api_key=%s" % (project.short_name, blogpost.id, user.api_key) res = self.app.get(url, follow_redirects=True) assert res.status_code == 200, res.status_code assert 'title' in str(res.data)
def test_project_update_two_info_objects(self): """Test Auditlog API project update two info objects works.""" project = ProjectFactory.create() owner_id = project.owner.id owner_name = project.owner.name data = {'info': {'sched': 'depth_first', 'task_presenter': 'new'}} attributes = data['info'].keys() url = '/api/project/%s?api_key=%s' % (project.id, project.owner.api_key) self.app.put(url, data=json.dumps(data)) logs = auditlog_repo.filter_by(project_id=project.id) assert len(logs) == 2, logs for log in logs: assert log.user_id == owner_id, log.user_id assert log.user_name == owner_name, log.user_name assert log.project_short_name == project.short_name, log.project_short_name assert log.action == 'update', log.action assert log.caller == 'api', log.caller assert log.attribute in attributes, log.attribute msg = "%s != %s" % (data['info'][log.attribute], log.new_value) assert data['info'][log.attribute] == log.new_value, msg
def test_get_locked_task(self): owner = UserFactory.create(id=500) project = ProjectFactory.create(owner=owner) project.info['sched'] = Schedulers.locked project_repo.save(project) task1 = TaskFactory.create(project=project, info='task 1', n_answers=2) task2 = TaskFactory.create(project=project, info='task 2', n_answers=2) t1 = get_locked_task(project.id, 11) t2 = get_locked_task(project.id, 1) assert t1[0].id == task1.id assert t2[0].id == task1.id t3 = get_locked_task(project.id, 2) t4 = get_locked_task(project.id, 3) assert t3[0].id == task2.id assert t4[0].id == task2.id t5 = get_locked_task(project.id, 11) assert t5[0].id == task1.id t6 = get_locked_task(project.id, 4) assert not t6
def test_blogpost_create_by_owner(self, mock_redirect): """Test blogposts, project owners can create""" self.register() user = user_repo.get(1) project = ProjectFactory.create(owner=user) url = "/project/%s/new-blogpost" % project.short_name res = self.app.get(url, follow_redirects=True) assert res.status_code == 200, res.status_code res = self.app.post(url, data={ 'title': 'blogpost title', 'body': 'body' }, follow_redirects=True) assert res.status_code == 200, res.status_code mock_redirect.assert_called_with('/project/%E2%9C%93project1/blog') blogpost = blog_repo.get_by(title='blogpost title') assert blogpost.title == 'blogpost title', blogpost.title assert blogpost.project_id == project.id, blogpost.project.id assert blogpost.user_id == user.id, blogpost.user_id
def test_get_active_users_lock(self): """ Test number of locked tasks""" user = UserFactory.create(id=500) project = ProjectFactory.create(owner=user, info={'sched': 'default'}) TaskFactory.create_batch(2, project=project, n_answers=2) # Register the active user as a locked task. register_active_user(project.id, user.id, sentinel.master) # Verify the count of locked tasks for this project equals 1. count = get_active_user_count(project.id, sentinel.master) assert count == 1 # Unregister the active user as a locked task. unregister_active_user(project.id, user.id, sentinel.master) # Verify the count of locked tasks for this project equals 1. # There is a delay before the lock is released. count = get_active_user_count(project.id, sentinel.master) assert count == 1 # Confirm lock released after a delay. time.sleep(EXPIRE_LOCK_DELAY + 1) count = get_active_user_count(project.id, sentinel.master) assert not count
def test_update_add_field_does_not_delete_stats(self, delete): fields = { 'hello': { 'type': 'categorical', 'config': { 'labels': ['A', 'B', 'C'] } } } info = {'answer_fields': fields} project = ProjectFactory.create(published=True, info=info) url = '/project/%s/answerfieldsconfig?api_key=%s' % ( project.short_name, project.owner.api_key) res = self.app_get_json(url) data = json.loads(res.data) csrf = data['csrf'] fields['bye'] = {'config': {}, 'type': 'freetext'} res = self.app.post(url, content_type='application/json', data=json.dumps(info), headers={'X-CSRFToken': csrf}) data = json.loads(res.data) delete.assert_not_called()
def test_warn_project_owner(self, mail): """Test JOB email is sent to warn project owner.""" # Mock for the send method send_mock = MagicMock() send_mock.send.return_value = True # Mock for the connection method connection = MagicMock() connection.__enter__.return_value = send_mock # Join them mail.connect.return_value = connection date = '2010-10-22T11:02:00.000000' project = ProjectFactory.create(updated=date) project_id = project.id warn_old_project_owners() err_msg = "mail.connect() should be called" assert mail.connect.called, err_msg err_msg = "conn.send() should be called" assert send_mock.send.called, err_msg err_msg = "project.contacted field should be True" assert project.contacted, err_msg err_msg = "The update date should be different" assert project.updated != date, err_msg
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_webhook_handler_auth(self): """Test WEBHOOK view works for authenticated not owner.""" # Admin self.register() self.signout() # Owner self.register() self.signin() owner = user_repo.get(1) project = ProjectFactory.create(owner=owner) self.signout() # User self.register(name="juan") self.signin(email="*****@*****.**", password="******") url = "/project/%s/webhook" % project.short_name res = self.app.get(url) assert res.status_code == 403, res.status_code url = "/project/%s/webhook?all=true" % project.short_name res = self.app.get(url) assert res.status_code == 403, res.status_code url = "/project/%s/webhook?failed=true" % project.short_name res = self.app.get(url) assert res.status_code == 403, res.status_code
def test_ensure_task_assignment_to_project(self): project = ProjectFactory.create(info={}) task = TaskFactory.create(info={}) patched_levels = self.patched_levels( valid_project_levels_for_task_level={'A': ['A']}, valid_task_levels_for_project_level={'A': ['A']} ) with patch.dict(data_access.data_access_levels, patched_levels): with assert_raises(Exception): data_access.ensure_task_assignment_to_project(task, project) project.info['data_access'] = ['A'] with assert_raises(Exception): data_access.ensure_task_assignment_to_project(task, project) project.info['data_access'] = [] task.info['data_access'] = ['A'] with assert_raises(Exception): data_access.ensure_task_assignment_to_project(task, project) project.info['data_access'] = ['A', 'B'] task.info['data_access'] = ['A'] with assert_raises(Exception): data_access.ensure_task_assignment_to_project(task, project) project.info['ext_config'] = {'data_access': {'tracking_id': '123'}} data_access.ensure_task_assignment_to_project(task, project)
def test_org_revoke_invitation(self): user_a = UserFactory.create(email="*****@*****.**") user_b = UserFactory.create(email="*****@*****.**", full_name="User B") org = create_sample_organization(user_a, org_kwargs={ 'name': u"My first org", }) project = ProjectFactory.create(name=u"my project", org=org) org.add_user(user_b) project.add_user(user_b) self.assertTrue(project.can_read(user_b)) url = reverse("dashboard") response = self.app.get(url, user=user_b) self.assertContains(response, u"My first org") auth = AuthorizationAssociation.objects.get(org=org, user=user_b) url = reverse("org_auth_delete", args=(org.pk, auth.pk)) self.app.get(url, user=user_b, status=403) response = self.app.get(url, user=user_a) self.assertContains( response, u"Are you sure you want to revoke " u"'User B' from the organization " u"'My first org'") form = response.forms['delete_form'] response = form.submit().follow() self.assertContains( response, 'User {0} has been revoked.'.format(user_b.email), ) url = reverse("dashboard") response = self.app.get(url, user=user_b) self.assertNotContains(response, u"My first org") # ensure we revoked the rights for project too project = Project.objects.get(pk=project.pk) self.assertFalse(project.can_read(user_b))
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']['pyb_answer_url'] args = { 'host': self.host, 'bucket': self.bucket, 'project_id': project.id, 'task_id': task.id, 'user_id': project.owner.id, 'filename': 'pyb_answer.json' } expected = 'https://{host}/{bucket}/{project_id}/{task_id}/{user_id}/{filename}'.format( **args) assert url == expected, url
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' admin = UserFactory.create() url = '/api/taskrun?api_key=%s' % admin.api_key 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_task_priority_limit(self): """Test SCHED respects priority_0 field with limit""" 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=project.id).order_by('id').all() url = 'api/project/%s/newtask?limit=2' % project.id self.set_proj_passwd_cookie(project, username='******') res = self.app.get(url) tasks1 = json.loads(res.data) # Check that we received a Task err_msg = "Task.id should be the same" assert tasks1[0].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') tasks1 = json.loads(res.data) # Check that we received a Task err_msg = "Task.id should be the same" assert tasks1[0].get('id') == t.id, (err_msg, tasks1[0]) err_msg = "Task.priority_0 should be the 1" assert tasks1[0].get('priority_0') == 1, err_msg
def test_newtask(self): """Test API project new_task method and authentication""" project = ProjectFactory.create() TaskFactory.create_batch(2, project=project) user = UserFactory.create() # anonymous # test getting a new task res = self.app.get('/api/project/%s/newtask' % project.id) assert res, res task = json.loads(res.data) assert_equal(task['project_id'], project.id) # The output should have a mime-type: application/json assert res.mimetype == 'application/json', res # as a real user url = '/api/project/%s/newtask?api_key=%s' % (project.id, user.api_key) res = self.app.get(url) assert res, res task = json.loads(res.data) assert_equal(task['project_id'], project.id) # Get NotFound for an non-existing project url = '/api/project/5000/newtask' res = self.app.get(url) err = json.loads(res.data) err_msg = "The project does not exist" assert err['status'] == 'failed', err_msg assert err['status_code'] == 404, err assert err['exception_cls'] == 'NotFound', err_msg assert err['target'] == 'project', err_msg # Get an empty task url = '/api/project/%s/newtask?offset=1000' % project.id res = self.app.get(url) assert res.data == '{}', res.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_project_update_attributes(self): """Test Auditlog API project update attributes works.""" project = ProjectFactory.create( info=dict(list=[0], data_classification=dict(input_data="L4 - public", output_data="L4 - public"))) data = { 'name': 'New Name', 'short_name': project.short_name, 'description': 'new_description', 'long_description': 'new_long_description', 'allow_anonymous_contributors': False, 'info': { u'list': [1] } } attributes = data.keys() attributes.append('list') url = '/api/project/%s?api_key=%s' % (project.id, project.owner.api_key) self.app.put(url, data=json.dumps(data)) logs = auditlog_repo.filter_by(project_id=project.id) assert len(logs) == 5, (len(logs), logs) for log in logs: assert log.user_id == project.owner_id, log.user_id assert log.user_name == project.owner.name, log.user_name assert log.project_short_name == project.short_name, log.project_short_name assert log.action == 'update', log.action assert log.caller == 'api', log.caller assert log.attribute in attributes, (log.attribute, attributes) if log.attribute != 'list': msg = "%s != %s" % (data[log.attribute], log.new_value) assert unicode(data[log.attribute]) == log.new_value, msg else: msg = "%s != %s" % (data['info'][log.attribute], log.new_value) assert data['info'][log.attribute] == json.loads( log.new_value), msg
def test_enrich_task_requires_enrichment_config(self, mock_del, upload_from_string, importer_factory): mock_importer = Mock() mock_importer.tasks.return_value = [{ 'info': { u'Foo': u'a' }, 'private_fields': { u'Bar2': u'd', u'Bar': u'c' }, 'gold_answers': { u'ans2': u'e', u'ans': u'b' }, 'calibration': 1, 'exported': True, 'state': u'enrich' }] importer_factory.return_value = mock_importer project = ProjectFactory.create() form_data = dict(type='localCSV', csv_filename='fakefile.csv', validate_tp=False) with patch.dict( self.flask_app.config, { 'S3_REQUEST_BUCKET': 'mybucket', 'S3_CONN_TYPE': 'dev', 'ENABLE_ENCRYPTION': True }): import_report = self.importer.create_tasks(task_repo, project, **form_data) print import_report.message assert 'task import failed' in import_report.message
def test_newtask_default_orderby(self): """Test SCHED depth first works with orderby.""" project = ProjectFactory.create(info=dict(sched="depth_first")) task1 = TaskFactory.create(project=project, fav_user_ids=None) task2 = TaskFactory.create(project=project, fav_user_ids=[1,2,3]) api_key = project.owner.api_key url = "/api/project/%s/newtask?orderby=%s&desc=%s&api_key=%s" % (project.id, 'id', False, api_key) res = self.app.get(url) data = json.loads(res.data) assert data['id'] == task1.id, data url = "/api/project/%s/newtask?orderby=%s&desc=%s&api_key=%s" % (project.id, 'id', True, api_key) res = self.app.get(url) data = json.loads(res.data) assert data['id'] == task2.id, data url = "/api/project/%s/newtask?orderby=%s&desc=%s&api_key=%s" % (project.id, 'created', False, api_key) res = self.app.get(url) data = json.loads(res.data) assert data['id'] == task1.id, data url = "/api/project/%s/newtask?orderby=%s&desc=%s&api_key=%s" % (project.id, 'created', True, api_key) res = self.app.get(url) data = json.loads(res.data) assert data['id'] == task2.id, data url = "/api/project/%s/newtask?orderby=%s&desc=%s&api_key=%s" % (project.id, 'fav_user_ids', False, api_key) res = self.app.get(url) data = json.loads(res.data) assert data['id'] == task1.id, data url = "/api/project/%s/newtask?orderby=%s&desc=%s&api_key=%s" % (project.id, 'fav_user_ids', True, api_key) res = self.app.get(url) data = json.loads(res.data) assert data['id'] == task2.id, data assert data['fav_user_ids'] == task2.fav_user_ids, data
def test_counter_table_api(self): """Test API Counter table is updated accordingly via api.""" project = ProjectFactory.create() task = dict(project_id=project.id, info=dict(foo=1)) url = '/api/task?api_key=%s' % project.owner.api_key res = self.app.post(url, data=json.dumps(task)) data = json.loads(res.data) assert data.get('id') is not None, res.data items = db.session.query(Counter).filter_by( project_id=project.id).all() assert len(items) == 1 items = db.session.query(Counter).filter_by( task_id=data.get('id')).all() assert len(items) == 1 assert items[0].task_id == data.get('id') for i in range(9): res = self.app.post(url, data=json.dumps(task)) created_task = json.loads(res.data) items = db.session.query(Counter).filter_by( project_id=project.id).all() assert len(items) == 10, len(items) res = self.app.delete('/api/task/%s?api_key=%s' % (created_task['id'], project.owner.api_key)) items = db.session.query(Counter).filter_by( project_id=project.id).all() assert len(items) == 9 items = db.session.query(Counter).filter_by( task_id=created_task.get('id')).all() assert len(items) == 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
def test_get_query_with_api_key_and_all(self): """ Test API GET query with an API-KEY requesting all results""" users = UserFactory.create_batch(3) project = ProjectFactory.create(owner=users[0], info={'total': 150}) task = TaskFactory.create(project=project, 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 + '&all=1' res = self.app.get(url) data = json.loads(res.data) if endpoint == 'project': assert len(data) == 1, data project = data[0] 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['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 test_project_contact_no_non_admin_subadmin_owner(self, enqueue): """Test Project Contact not emailing a co-owner who is not an admin nor subadmin.""" message = u'hello' admin, owner, user = UserFactory.create_batch(3) # Create a user as a co-owner that is not an admin nor subadmin. coowner = UserFactory.create(name='My Non-Admin-Subadmin User') # Create a project with a disabled co-owner. project = ProjectFactory.create(owner=owner, short_name='test-app', name='My New Project', owners_ids=[coowner.id]) # Obtain a CSRF key. csrf = self.get_csrf('/account/signin') # Make a request to the api. url = '/project/' + project.short_name + '/contact?api_key=' + user.api_key data = dict(message=message) res = self.app.post(url, headers={'X-CSRFToken': csrf}, content_type='application/json', data=json.dumps(data)) # Get contents of email. str_message = str(enqueue.call_args_list[0]) # Verify recipient for project owner. recipients_index = str_message.find('recipients') assert recipients_index > -1 assert str_message.find(owner.email_addr) > recipients_index # Verify no recipient for co-owner that is not an admin nor subadmin. assert str_message.find(coowner.email_addr) == -1
def test_blogpost_update_by_owner(self, mock_redirect): """Test blogposts, project owners can update""" self.register() user = user_repo.get(1) project = ProjectFactory.create(owner=user) blogpost = BlogpostFactory.create(project=project) url = "/project/%s/%s/update" % (project.short_name, blogpost.id) res = self.app.get(url, follow_redirects=True) assert res.status_code == 200, res.status_code res = self.app.post(url, data={ 'id': blogpost.id, 'title': 'blogpost title', 'body': 'new body' }, follow_redirects=True) assert res.status_code == 200, res.status_code mock_redirect.assert_called_with('/project/%E2%9C%93project1/blog') blogpost = blog_repo.get_by(title='blogpost title') assert blogpost.title == 'blogpost title', blogpost.title assert blogpost.body == 'new body', blogpost.body
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_user_01_newtask(self): """ Test SCHED newtask returns a Task for John Doe User""" project = ProjectFactory.create(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 self.set_proj_passwd_cookie(project, username='******') 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_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_newtask(self): """Test API project new_task method and authentication""" project = ProjectFactory.create() project.set_password('the_password') project_repo.save(project) TaskFactory.create_batch(2, project=project, info={'question': 'answer'}) user = UserFactory.create() # anonymous # test getting a new task res = self.app.get('/api/project/%s/newtask' % project.id) assert res, res task = json.loads(res.data) assert 'error' in task['info'], 'No anonymous contributors' # as a real user, no password url = '/api/project/%s/newtask?api_key=%s' % (project.id, user.api_key) res = self.app.get(url) assert res.status_code == 403, res task = json.loads(res.data) assert task['exception_msg'] == 'No project password provided' url = '/project/%s/password?api_key=%s' % (project.short_name, user.api_key) data = dict(password='******') res = self.app.post(url, data=data) c, v, e = get_pwd_cookie(project.short_name, res) assert c self.app.set_cookie('/', c, v) url = '/api/project/%s/newtask?api_key=%s' % (project.id, user.api_key) res = self.app.get(url) assert res.status_code == 200, res task = json.loads(res.data) assert task['info'].get('question') == 'answer'