def test_max_limit(self): """Test ACTIVITY FEED limit works.""" ProjectFactory.create_batch(101) update_feed = get_update_feed() err_msg = "There should be at max 100 updates." assert len(update_feed) == 100, 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_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_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_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_n_draft_with_drafts(self): """Test CACHE PROJECTS _n_draft returns 2 if there are 2 draft projects""" ProjectFactory.create_batch(2, published=False) number_of_drafts = cached_projects._n_draft() assert number_of_drafts == 2, number_of_drafts
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_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_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_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_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_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_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_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_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_n_draft_with_drafts(self): """Test CACHE PROJECTS _n_draft returns 2 if there are 2 draft projects""" # Here, we are suposing that a project is draft iff has no presenter AND has no tasks ProjectFactory.create_batch(2, info={}) number_of_drafts = cached_projects._n_draft() assert number_of_drafts == 2, number_of_drafts
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_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_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_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_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_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_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_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_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_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_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_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) external_uid = 'as2d-4cab-3daf-234a-2344x' data = dict( project_id=project.id, task_id=task.id, info='my task result', external_uid=external_uid) 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=%s' % (project.id, external_uid)) 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=%s' % (project.id, external_uid), headers=headers) success = self.app.post('/api/taskrun', data=datajson, headers=headers) assert success.status_code == 200, success.data
def test_create_dict_job(self): """Test JOB create dict job works.""" user = UserFactory.create(pro=True) project = ProjectFactory.create(owner=user) from sqlalchemy.sql import text from pybossa.core import db sql = text( '''SELECT project.id, project.short_name FROM project, "user" WHERE project.owner_id="user".id AND "user".pro=True;''') results = db.slave_session.execute(sql) jobs_generator = create_dict_jobs(results, get_project_stats, (10 * 60)) jobs = [] for job in jobs_generator: jobs.append(job) err_msg = "There should be only one job" assert len(jobs) == 1, err_msg job = jobs[0] assert 'get_project_stats' in job['name'].__name__ assert job['args'] == [project.id, project.short_name]
def test_email_notif(self, get_contrib_emails): """ if the project is configured, email notifications will be sent """ owner = UserFactory.create(id=500, user_pref={'languages': ['en']}) project = ProjectFactory.create(owner=owner, email_notif=True) project.info['sched'] = Schedulers.user_pref project_repo.save(project) tasks = TaskFactory.create_batch(1, project=project, n_answers=1, user_pref={'languages': ['en']}) TaskRunFactory.create(task=tasks[0], user=owner) TaskFactory.create_batch(1, project=project, n_answers=1, user_pref={'languages': ['en']}) send_email_notifications() get_contrib_emails.assert_called()
def test_webhook_handler_post_oid(self): """Test WEBHOOK post oid works.""" self.register() self.signin() user = user_repo.get(1) project = ProjectFactory.create(owner=user) task = TaskFactory.create(project=project, n_answers=1) AnonymousTaskRunFactory.create(project=project, task=task) payload = self.payload(project, task) webhook = Webhook(project_id=project.id, payload=payload, response='OK', response_status_code=200) webhook_repo.save(webhook) webhook = webhook_repo.get(1) url = "/project/%s/webhook/%s" % (project.short_name, webhook.id) res = self.app.post(url) tmp = json.loads(res.data) assert res.status_code == 200, res.status_code assert tmp['payload']['project_short_name'] == project.short_name assert tmp['payload']['project_id'] == project.id assert tmp['payload']['task_id'] == task.id
def test_project_update_scheduler(self): """Test Auditlog API project update info scheduler works.""" project = ProjectFactory.create() owner_id = project.owner.id owner_name = project.owner.name data = {'info': {'sched': 'depth_first'}} 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) == 1, 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 == 'sched', log.attribute msg = "%s != %s" % (data['info']['sched'], log.new_value) assert data['info']['sched'] == log.new_value, msg
def test_sync_L3_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="L3 - community", output_data="L3 - community") 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_blogpost_update_by_anonymous(self): """Test blogpost update, anonymous users are redirected to signin""" project = ProjectFactory.create() blogpost = BlogpostFactory.create(project=project, title='title') 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 assert "Please sign in to access this page" in res.data, res.data res = self.app.post(url, data={ 'id': blogpost.id, 'title': 'new title', 'body': 'new body' }, follow_redirects=True) assert res.status_code == 200, res.status_code assert "Please sign in to access this page" in res.data blogpost = blog_repo.get_by() assert blogpost.title == 'title', blogpost.title
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'
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 create_project_with_contributors(self, anonymous, registered, two_tasks=False, name='my_app', info={}): project = ProjectFactory.create(name=name, info=info) task = TaskFactory(project=project) if two_tasks: task2 = TaskFactory(project=project) for i in range(anonymous): task_run = AnonymousTaskRunFactory(task=task, user_ip='127.0.0.%s' % i) if two_tasks: task_run2 = AnonymousTaskRunFactory(task=task2, user_ip='127.0.0.%s' % i) for i in range(registered): user = UserFactory.create() task_run = TaskRunFactory(task=task, user=user) if two_tasks: task_run2 = TaskRunFactory(task=task2, user=user) return project
def test_task_update_state(self): """Test API task n_answers updates state properly.""" user = UserFactory.create() project = ProjectFactory.create(owner=user) task = TaskFactory.create(project=project, n_answers=1, state='ongoing') data = {'n_answers': 2} datajson = json.dumps(data) 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 task.state = 'completed' task_repo.update(task) data = {'n_answers': 1} datajson = json.dumps(data) 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, 'completed') assert task.id == out['id'], out data = {'n_answers': 5} datajson = json.dumps(data) 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
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_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 create_auditlogs(self): project = ProjectFactory.create( info={ 'task_presenter': 'version1', 'task_guidelines': 'version1', 'data_classification': dict(input_data="L4 - public", output_data="L4 - public") }) AuditlogFactory.create(project_id=project.id, project_short_name=project.short_name, user_id=project.owner.id, user_name=project.owner.name, attribute='task_presenter', old_value="old_task_presenter1", new_value="new_task_presenter2", created='2019-01-11T15:24:42.263980') 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, attribute='task_guidelines', old_value="old_task_guidelines1", new_value="new_task_guidelines2", created='2019-01-11T15:24:42.263980') 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, attribute='task_guidelines', old_value="old_task_guidelines1", new_value="new_task_guidelines2", created='2020-01-11T15:24:42.263980')
def test_update_delete_multiple_fields(self, delete): fields = { 'hello': { 'type': 'freetext', 'config': {} }, 'ä½ å¥½': { 'type': 'freetext', 'config': {} }, 'ciao': { 'type': 'freetext', 'config': {} }, 'hola': { 'type': 'freetext', 'config': {} } } 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.pop('hello') fields['Привет'] = {'type': 'freetext', 'config': {}} fields['hola']['type'] = 'categorical' res = self.app.post(url, content_type='application/json', data=json.dumps({'answer_fields': fields}), headers={'X-CSRFToken': csrf}) data = json.loads(res.data) assert delete.call_count == 2 assert all(args[0] == project.id for args, _ in delete.call_args_list) deleted_fields = set(args[1] for args, _ in delete.call_args_list) assert deleted_fields == set(['hello', 'hola'])
def test_newtask_expired_cookie(self): """Test API project new_task expired cookie""" project = ProjectFactory.create(info={'timeout': 60}) project.set_password('the_password') project_repo.save(project) TaskFactory.create_batch(2, project=project, info={'question': 'answer'}) user = UserFactory.create() # simulate sending expired cookies with patch.dict(self.flask_app.config, {'PASSWD_COOKIE_TIMEOUT': -1}): 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) res = self.app.post(url, data=data) c, v, e = get_pwd_cookie(project.short_name, res) assert c url = '/project/%s/newtask?api_key=%s' % (project.short_name, user.api_key) res = self.app.get(url) assert res.status_code == 302 headers = {'Content-Type': 'application/json'} res = self.app.get(url, headers=headers) next_url = json.loads(res.data)['next'] print next_url headers = {'Authorization': user.api_key} res = self.app.get(next_url, headers=headers) assert 'Enter the password to contribute to this project' in res.data, res.data
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 assert r_taskrun['user_ip'] != '127.0.0.0', r_taskrun err_msg = "Task state should be equal to completed" assert task.state == 'completed', err_msg
def test_anonymous_03_respects_limit_tasks(self): """ Test SCHED newtask respects the limit of 10 TaskRuns per Task""" assigned_tasks = [] project = ProjectFactory.create(owner=UserFactory.create(id=500), info=dict(sched='depth_first_all')) user = UserFactory.create() task = TaskFactory.create(project=project, n_answers=10) tasks = get_depth_first_all_task(project.id, user.id) assert len(tasks) == 1, len(tasks) assert tasks[0].id == task.id, tasks assert tasks[0].state == 'ongoing', tasks for i in range(10): tr = TaskRun(project_id=project.id, task_id=task.id, user_ip='127.0.0.%s' % i) db.session.add(tr) db.session.commit() tasks = get_depth_first_all_task(project.id, user.id) assert len(tasks) == 1, len(tasks) assert tasks[0].id == task.id, tasks assert tasks[0].state == 'completed', tasks for i in range(10): tasks = get_depth_first_all_task(project.id, user_id=None, user_ip='127.0.0.%s' % i) assert len(tasks) == 0, tasks tr = TaskRun(project_id=project.id, task_id=task.id, user_id=user.id) db.session.add(tr) db.session.commit() tasks = get_depth_first_all_task(project.id, user.id) assert len(tasks) == 0, tasks
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_project_contact_no_disabled_owner(self, enqueue): """Test Project Contact not emailing a disabled co-owner.""" message = u'hello' admin, owner, user = UserFactory.create_batch(3) # Create a disabled user as a co-owner. coowner = UserFactory.create(name='My Disabled Co-Owner User', enabled=False, subadmin=True) # 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 disabled co-owner. assert str_message.find(coowner.email_addr) == -1
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_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 res.data
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_query_projectstats_filter_project(self): owner = UserFactory.create() project1, project2 = ProjectFactory.create_batch(2, owner=owner) stats = PerformanceStatsFactory.create(user_id=owner.id, project_id=project1.id, info={'project': project1.id}) stats = PerformanceStatsFactory.create(user_id=owner.id, project_id=project2.id, info={'project': project2.id}) url = '/api/performancestats' res = self.app.get('{}?api_key={}&project_id={}'.format( url, owner.api_key, project1.id)) data = json.loads(res.data) assert len(data) == 1 assert data[0]['info']['project'] == project1.id res = self.app.get('{}?api_key={}&project_id={}'.format( url, owner.api_key, project2.id)) data = json.loads(res.data) assert len(data) == 1 assert data[0]['info']['project'] == project2.id
def test_blogpost_update_by_non_owner(self): """Test blogpost update by non owner of the project is forbidden""" self.register() self.signin() user = user_repo.get(1) project = ProjectFactory.create(owner=user) blogpost = BlogpostFactory.create(project=project, title='title', body='body') url = "/project/%s/new-blogpost" % project.short_name self.signout() self.register(name='notowner', email='*****@*****.**') self.signin(email='*****@*****.**', password='******') url = "/project/%s/%s/update" % (project.short_name, blogpost.id) res = self.app.get(url, follow_redirects=True) assert res.status_code == 403, res.status_code res = self.app.post(url, data={'title':'new title', 'body':'body'}, follow_redirects=True) assert res.status_code == 403, res.status_code blogpost = blog_repo.get_by() assert blogpost.title == 'title', blogpost.title
def test_query_projectstats_filter_user(self): owner, user = UserFactory.create_batch(2) project = ProjectFactory.create(owner=owner) stats = PerformanceStatsFactory.create(user_id=user.id, project_id=project.id, info={'user': user.id}) stats = PerformanceStatsFactory.create(user_id=owner.id, project_id=project.id, info={'user': owner.id}) url = '/api/performancestats' res = self.app.get('{}?api_key={}&user_id={}'.format( url, owner.api_key, user.id)) data = json.loads(res.data) assert len(data) == 1 assert data[0]['info']['user'] == user.id res = self.app.get('{}?api_key={}&user_id={}'.format( url, owner.api_key, owner.id)) data = json.loads(res.data) assert len(data) == 1 assert data[0]['info']['user'] == owner.id
def test_create_tasks_creates_them_correctly(self, importer_factory): mock_importer = Mock() mock_importer.tasks.return_value = [{ 'info': { 'question': 'question', 'url': 'url' }, 'n_answers': 20 }] importer_factory.return_value = mock_importer project = ProjectFactory.create() form_data = dict(type='csv', csv_url='http://fakecsv.com', validate_tp=False) self.importer.create_tasks(task_repo, project, **form_data) task = task_repo.get_task(1) assert task is not None assert task.project_id == project.id, task.project_id assert task.n_answers == 20, task.n_answers assert task.info == {'question': 'question', 'url': 'url'}, task.info importer_factory.assert_called_with(**form_data) mock_importer.tasks.assert_called_with()
def test_task_routing_2(self): ''' task[0]: needs finance skill at least 0.8, should not be able to assign to the user task[1]: needs geography skill at least 0.5, should not be able to assign to the user task[3]: doesnt have filters, should be able to assign to the user ''' user_info = dict( metadata={ "profile": json.dumps({ "finance": 0.6, "marketing": 0.4 }) }) owner = UserFactory.create(id=500, info=user_info) user_repo.save(owner) project = ProjectFactory.create(owner=owner) project.info['sched'] = Schedulers.user_pref tasks = TaskFactory.create_batch(3, project=project, n_answers=10) tasks[0].worker_filter = {'finance': [0.8, '>=']} task_repo.save(tasks[0]) tasks[1].worker_filter = {'geography': [0.5, '>=']} task_repo.save(tasks[1]) assert n_available_tasks_for_user(project, 500) == 1
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_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