def test_app_create(self): """Test Auditlog API project create works.""" # app = AppFactory.create() CategoryFactory.create() user = UserFactory.create() data = { 'name': 'New Name', 'short_name': 'new_short_name', 'description': 'new_description', 'long_description': 'new_long_description', 'allow_anonymous_contributors': 'False', } url = '/api/app?api_key=%s' % (user.api_key) self.app.post(url, data=json.dumps(data)) logs = auditlog_repo.filter_by(app_short_name='new_short_name') assert len(logs) == 1, logs for log in logs: assert log.user_id == user.id, log.user_id assert log.user_name == user.name, log.user_name assert log.app_short_name == 'new_short_name', log.app_short_name assert log.caller == 'api', log.caller assert log.action == 'create', log.action assert log.attribute == 'project', log.attribute assert log.old_value == 'Nothing', log.old_value assert log.new_value == 'New project', log.new_value
def test_project_create(self): """Test Auditlog API project create works.""" CategoryFactory.create() user = UserFactory.create() data = {'name': 'New Name', 'short_name': 'new_short_name', 'description': 'new_description', 'long_description': 'new_long_description', 'allow_anonymous_contributors': 'False', } url = '/api/project?api_key=%s' % (user.api_key) self.app.post(url, data=json.dumps(data)) logs = auditlog_repo.filter_by(project_short_name='new_short_name') assert len(logs) == 1, logs for log in logs: assert log.user_id == user.id, log.user_id assert log.user_name == user.name, log.user_name assert log.project_short_name == 'new_short_name', log.project_short_name assert log.caller == 'api', log.caller assert log.action == 'create', log.action assert log.attribute == 'project', log.attribute assert log.old_value == 'Nothing', log.old_value assert log.new_value == 'New project', log.new_value
def test_project_create(self): """Test Auditlog API project create works.""" CategoryFactory.create() user = UserFactory.create() data = { 'name': 'New Name', 'short_name': 'new_short_name', 'description': 'new_description', 'long_description': 'new_long_description', 'allow_anonymous_contributors': False, 'info': dict(passwd_hash="hello"), 'zip_download': True } url = '/api/project?api_key=%s' % (user.api_key) self.app.post(url, data=json.dumps(data)) logs = auditlog_repo.filter_by(project_short_name='new_short_name') assert len(logs) == 1, logs for log in logs: assert log.user_id == user.id, log.user_id assert log.user_name == user.name, log.user_name assert log.project_short_name == 'new_short_name', log.project_short_name assert log.caller == 'api', log.caller assert log.action == 'create', log.action assert log.attribute == 'project', log.attribute assert log.old_value == 'Nothing', log.old_value assert log.new_value == 'New project', log.new_value
def test_get_category_by_returns_none_if_no_category(self): """Test get_category returns None if no category matches the query""" CategoryFactory.create(name='My Project', short_name='mycategory') category = self.project_repo.get_by(name='no_name') assert category is None, category
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_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_filter_categories_by_ownerid(self): """Test filter_categories_by removes ownerid from query.""" CategoryFactory.create(name='My Project', short_name='mycategory') retrieved_categories = self.project_repo.filter_categories_by( short_name='mycategory', owner_id=1) assert isinstance(retrieved_categories, list) assert len(retrieved_categories) == 1, retrieved_categories
def test_filter_categories_by_no_matches(self): """Test filter_categories_by returns an empty list if no categories match the query""" CategoryFactory.create(name='My Project', short_name='mycategory') retrieved_categories = self.project_repo.filter_categories_by(name='no_name') assert isinstance(retrieved_categories, list) assert len(retrieved_categories) == 0, retrieved_categories
def test_filter_categories_by_ownerid(self): """Test filter_categories_by removes ownerid from query.""" CategoryFactory.create(name='My Project', short_name='mycategory') retrieved_categories = self.project_repo.filter_categories_by(short_name='mycategory', owner_id=1) assert isinstance(retrieved_categories, list) assert len(retrieved_categories) == 1, retrieved_categories
def test_query_category(self): """Test API query for category endpoint works""" CategoryFactory.create(name='thinking', short_name='thinking') # Test for real field url = "/api/category" res = self.app.get(url + "?short_name=thinking") data = json.loads(res.data) # Should return one result assert len(data) == 1, data # Correct result assert data[0]['short_name'] == 'thinking', data # Valid field but wrong value res = self.app.get(url + "?short_name=wrongvalue") data = json.loads(res.data) assert len(data) == 0, data # Multiple fields res = self.app.get(url + '?short_name=thinking&name=thinking') data = json.loads(res.data) # One result assert len(data) == 1, data # Correct result assert data[0]['short_name'] == 'thinking', data assert data[0]['name'] == 'thinking', data # Limits res = self.app.get(url + "?limit=1") data = json.loads(res.data) for item in data: assert item['short_name'] == 'thinking', item assert len(data) == 1, data # Keyset pagination CategoryFactory.create(name='computing', short_name='computing') res = self.app.get(url) data = json.loads(res.data) tmp = '?limit=1&last_id=%s' % data[0]['id'] res = self.app.get(url + tmp) data_new = json.loads(res.data) assert len(data_new) == 1, data_new assert data_new[0]['id'] == data[1]['id'] # Errors res = self.app.get(url + "?something") err = json.loads(res.data) err_msg = "AttributeError exception should be raised" res.status_code == 415, err_msg assert res.status_code == 415, err_msg assert err['action'] == 'GET', err_msg assert err['status'] == 'failed', err_msg assert err['exception_cls'] == 'AttributeError', err_msg
def test_query_category(self): """Test API query for category endpoint works""" CategoryFactory.create(name="thinking", short_name="thinking") # Test for real field url = "/api/category" res = self.app.get(url + "?short_name=thinking") data = json.loads(res.data) # Should return one result assert len(data) == 1, data # Correct result assert data[0]["short_name"] == "thinking", data # Valid field but wrong value res = self.app.get(url + "?short_name=wrongvalue") data = json.loads(res.data) assert len(data) == 0, data # Multiple fields res = self.app.get(url + "?short_name=thinking&name=thinking") data = json.loads(res.data) # One result assert len(data) == 1, data # Correct result assert data[0]["short_name"] == "thinking", data assert data[0]["name"] == "thinking", data # Limits res = self.app.get(url + "?limit=1") data = json.loads(res.data) for item in data: assert item["short_name"] == "thinking", item assert len(data) == 1, data # Keyset pagination CategoryFactory.create(name="computing", short_name="computing") res = self.app.get(url) data = json.loads(res.data) tmp = "?limit=1&last_id=%s" % data[0]["id"] res = self.app.get(url + tmp) data_new = json.loads(res.data) assert len(data_new) == 1, data_new assert data_new[0]["id"] == data[1]["id"] # Errors res = self.app.get(url + "?something") err = json.loads(res.data) err_msg = "AttributeError exception should be raised" res.status_code == 415, err_msg assert res.status_code == 415, err_msg assert err["action"] == "GET", err_msg assert err["status"] == "failed", err_msg assert err["exception_cls"] == "AttributeError", err_msg
def test_sync(self, fake_requests, mocl_build, mock_create, mock_get): category_syncer = CategorySyncer(self.target_url, self.target_key) category = CategoryFactory.create() category_syncer.sync(category) category_syncer.get_target.assert_called_once() category_syncer._create.assert_called_once()
def test_index_based_sorting(self): """Tests index based category sorting""" parent_1 = CategoryFactory.create(name="parent 1", index=10) sub_1 = CategoryFactory.create(name="sub 1", index=13, parent=parent_1) sub_2 = CategoryFactory.create(name="sub 2", index=12, parent=parent_1) sub_3 = CategoryFactory.create(name="sub 3", index=11, parent=parent_1) categories = Category.objects.all() indexes = [] for category in categories: indexes.append(category.index) self.assertEquals(indexes, sorted(indexes)) self.assertEquals(categories[0], parent_1) self.assertEquals(categories[3], sub_1)
def test_update_category_fails_if_integrity_error(self): """Test update raises a DBIntegrityError if the instance to be updated lacks a required value""" category = CategoryFactory.create() category.name = None assert_raises(DBIntegrityError, self.project_repo.update_category, category)
def test_get_category_by(self): """Test get_category returns a category with the specified attribute""" category = CategoryFactory.create(name='My Cat', short_name='mycat') retrieved_category = self.project_repo.get_category_by(name=category.name) assert category == retrieved_category, retrieved_category
def test_get_category_returns_category(self): """Test get_category method returns a category if exists""" category = CategoryFactory.create() retrieved_category = self.project_repo.get_category(category.id) assert category == retrieved_category, retrieved_category
def test_delete_category(self): """Test delete_category removes the category instance""" category = CategoryFactory.create() self.project_repo.delete_category(category) deleted = self.project_repo.get_category(category.id) assert deleted is None, deleted
def test_project_put_invalid_short_name(self): """Test API project PUT returns error if short_name is invalid (i.e. is a name used by the Flask app as a URL endpoint""" user = UserFactory.create() CategoryFactory.create() project = ProjectFactory.create(owner=user) name = u'XXXX Project' data = {'short_name': 'new'} datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (project.id, user.api_key), data=datajson) error = json.loads(res.data) assert res.status_code == 415, res.status_code assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['target'] == 'project', error assert error['exception_cls'] == 'ValueError', error message = "Project short_name is not valid, as it's used by the system." assert error['exception_msg'] == message, error
def test_update_category(self): """Test update_category persists the changes made to the category""" category = CategoryFactory.create(description='this is a category') category.description = 'the description has changed' self.project_repo.update_category(category) updated_category = self.project_repo.get_category(category.id) assert updated_category.description == 'the description has changed', updated_category
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 list(used_categories[0].keys()) assert len(fields) == len(list(used_categories[0].keys()))
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_blogpost_public_json(self): """Test CATEGORY to_public_json method works with extra fields.""" cat = CategoryFactory.create() cat.info = {'secret': 'mysecret', 'public': 'hello'} err_msg = "There should be info keys" with patch.dict(self.flask_app.config, {'CATEGORY_INFO_PUBLIC_FIELDS': ['public']}): json = cat.to_public_json() assert json['info'].keys().sort() == Category().public_info_keys().sort(), err_msg assert 'public' in json['info'].keys() assert 'secret' not in json['info'].keys()
def test_project_post_with_reserved_fields_returns_error(self): user = UserFactory.create() CategoryFactory.create() data = dict(name='name', short_name='name', description='description', owner_id=user.id, long_description=u'Long Description\n================', info={}, id=222, created='today', updated='now', contacted=False, completed=False) data = json.dumps(data) res = self.app.post('/api/project?api_key=' + user.api_key, data=data) assert res.status_code == 400, res.status_code error = json.loads(res.data) assert error['exception_msg'] == "Reserved keys in payload", error
def test_project_put_invalid_short_name(self): """Test API project PUT returns error if try to update short_name(i.e. is a name used by the Flask app as a URL endpoint""" user = UserFactory.create() CategoryFactory.create() project = ProjectFactory.create(owner=user) name = u'XXXX Project' data = {'short_name': 'new'} datajson = json.dumps(data) res = self.app.put('/api/projectbyname/%s?api_key=%s' % (project.short_name, user.api_key), data=datajson) error = json.loads(res.data) assert res.status_code == 403, res.status_code assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['target'] == 'project', error assert error['exception_cls'] == 'Forbidden', error message = "Cannot change short_name via API" assert error['exception_msg'] == message, error
def test_info_json_search_category(self): """Test search in JSON info works.""" category = CategoryFactory.create() text = 'bar' data = {'foo': text} category.info = data self.project_repo.update_category(category) info = 'foo::bar' res = self.project_repo.filter_categories_by(info=info) assert len(res) == 1, len(res) assert res[0].info['foo'] == text, res[0]
def test_project_post_with_reserved_fields_returns_error(self): user = UserFactory.create() CategoryFactory.create() data = dict( name='name', short_name='name', description='description', owner_id=user.id, long_description=u'Long Description\n================', info={}, id=222, created='today', updated='now', contacted=False, completed=False) data = json.dumps(data) res = self.app.post('/api/project?api_key=' + user.api_key, data=data) assert res.status_code == 400, res.status_code error = json.loads(res.data) assert error['exception_msg'] == "Reserved keys in payload", error
def test_filter_categories_by_one_condition(self): """Test filter_categories_by returns a list of categories that meet the filtering condition""" CategoryFactory.create_batch(3, description='generic category') should_be_missing = CategoryFactory.create(description='other category') retrieved_categories = (self.project_repo .filter_categories_by(description='generic category')) assert len(retrieved_categories) == 3, retrieved_categories assert should_be_missing not in retrieved_categories, retrieved_categories
def test_project_cache_post_is_refreshed(self, caching_mock): """Test API project cache is updated after POST.""" clean_project_mock = MagicMock() caching_mock.get.return_value = dict(refresh=clean_project_mock) owner = UserFactory.create() category = CategoryFactory.create() url = '/api/project?api_key=%s' % owner.api_key payload = dict(name='foo', short_name='foo', description='foo') res = self.app.post(url, data=json.dumps(payload)) print res.data project_id = json.loads(res.data)['id'] clean_project_mock.assert_called_with(project_id), res.data
def test_blogpost_public_json(self): """Test CATEGORY to_public_json method works with extra fields.""" cat = CategoryFactory.create() cat.info = {'secret': 'mysecret', 'public': 'hello'} err_msg = "There should be info keys" with patch.dict(self.flask_app.config, {'CATEGORY_INFO_PUBLIC_FIELDS': ['public']}): json = cat.to_public_json() assert list(json['info'].keys()).sort() == Category( ).public_info_keys().sort(), err_msg assert 'public' in list(json['info'].keys()) assert 'secret' not in list(json['info'].keys())
def test_update_category(self): """Test update_category persists the changes made to the category""" info = {'key': 'val'} category = CategoryFactory.create(info=info) info_new = {'f': 'v'} category.info = info_new self.project_repo.update_category(category) updated_category = self.project_repo.get_category(category.id) assert updated_category.info == info_new, updated_category
def test_app_post_invalid_short_name(self): """Test API project POST returns error if short_name is invalid (i.e. is a name used by the Flask app as a URL endpoint""" users = UserFactory.create_batch(2) CategoryFactory.create() name = u'XXXX Project' data = dict(name=name, short_name='new', description='description', owner_id=1, long_description=u'Long Description\n================') data = json.dumps(data) res = self.app.post('/api/app?api_key=' + users[1].api_key, data=data) error = json.loads(res.data) assert res.status_code == 415, res.status_code assert error['status'] == 'failed', error assert error['action'] == 'POST', error assert error['target'] == 'app', error assert error['exception_cls'] == 'ValueError', error message = "Project short_name is not valid, as it's used by the system." assert error['exception_msg'] == message, error
def test_fulltext_search_category_01(self): """Test fulltext search in JSON info works.""" category = CategoryFactory.create() text = 'something word you me bar' data = {'foo': text, 'bar': 'foo'} category.info = data self.project_repo.update_category(category) info = 'foo::word&bar|bar::foo' res = self.project_repo.filter_categories_by(info=info, fulltextsearch='1') assert len(res) == 1, len(res) assert res[0][0].info['foo'] == text, res[0]
def test_project_filter_by_category_works(self): """Test API project filter by category works.""" category = CategoryFactory.create() projects_published = ProjectFactory.create_batch(2, published=True, category=category) projects_not_published = ProjectFactory.create_batch(2, published=False, category=category) res = self.app.get('/api/project?category_id=%s' % category.id) data = json.loads(res.data) assert len(data) == 2, data assert data[0]['id'] == projects_published[0].id assert data[1]['id'] == projects_published[1].id
def test_project_post_invalid_short_name(self): """Test API project POST returns error if short_name is invalid (i.e. is a name used by the Flask app as a URL endpoint""" users = UserFactory.create_batch(2) CategoryFactory.create() name = u'XXXX Project' data = dict( name=name, short_name='new', description='description', owner_id=1, long_description=u'Long Description\n================') data = json.dumps(data) res = self.app.post('/api/project?api_key=' + users[1].api_key, data=data) error = json.loads(res.data) assert res.status_code == 415, res.status_code assert error['status'] == 'failed', error assert error['action'] == 'POST', error assert error['target'] == 'project', error assert error['exception_cls'] == 'ValueError', error message = "Project short_name is not valid, as it's used by the system." assert error['exception_msg'] == message, error
def test_get_categories_with_recent_projects(self): """Test categories with projects created in last 30 days""" date_now = datetime.datetime.utcnow() date_60_days_old = (datetime.datetime.utcnow() - datetime.timedelta(60)).isoformat() categories = CategoryFactory.create_batch(3) unused_category = CategoryFactory.create() ProjectFactory.create(category=categories[0], created=date_now) ProjectFactory.create(category=categories[1], created=date_now) ProjectFactory.create(category=categories[0], created=date_now) ProjectFactory.create(category=categories[2], created=date_60_days_old) total_categories = stats.categories_with_new_projects() assert total_categories == 2, "Total categories with recent projects should be 2"
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_index_based_sorting_with_two_parents(self): """Tests index based category sorting with two parents""" parent_2 = CategoryFactory.create(name="parent 2", index=1) sub_1a = CategoryFactory.create(name="sub 1a", index=2, parent=parent_2) sub_2a = CategoryFactory.create(name="sub 2a", index=4, parent=parent_2) sub_3a = CategoryFactory.create(name="sub 3a", index=3, parent=parent_2) parent_1 = CategoryFactory.create(name="parent 1", index=10) sub_1 = CategoryFactory.create(name="sub 1", index=13, parent=parent_1) sub_2 = CategoryFactory.create(name="sub 2", index=12, parent=parent_1) sub_3 = CategoryFactory.create(name="sub 3", index=11, parent=parent_1) categories = Category.objects.all() indexes = [] for category in categories: indexes.append(category.index) # first two categories should be the parents in the right order self.assertEquals(categories[0], parent_2) self.assertEquals(categories[1], parent_1)
def test_get_all_returns_all_categories(self): categories = [CategoryFactory.create()] assert cached_categories.get_all() == categories
def setUp(self): super(TestJsonProject, self).setUp() CategoryFactory.create()
def test_category_public_attributes(self): """Test CATEGORY public attributes works.""" cat = CategoryFactory.create() assert cat.public_attributes().sort() == cat.dictize().keys().sort()
def test_project_post(self): """Test API project creation and auth""" users = UserFactory.create_batch(2) CategoryFactory.create() name = u'XXXX Project' data = dict(name=name, short_name='xxxx-project', description='description', owner_id=1, long_description=u'Long Description\n================') data = json.dumps(data) # no api-key res = self.app.post('/api/project', data=data) assert_equal(res.status, '401 UNAUTHORIZED', 'Should not be allowed to create') # now a real user res = self.app.post('/api/project?api_key=' + users[1].api_key, data=data) out = project_repo.get_by(name=name) assert out, out assert_equal(out.short_name, 'xxxx-project'), out assert_equal(out.owner.name, 'user2') id_ = out.id # now a real user with headers auth headers = [('Authorization', users[1].api_key)] new_project = dict( name=name + '2', short_name='xxxx-project2', description='description2', owner_id=1, long_description=u'Long Description\n================') new_project = json.dumps(new_project) res = self.app.post('/api/project', headers=headers, data=new_project) out = project_repo.get_by(name=name + '2') assert out, out assert_equal(out.short_name, 'xxxx-project2'), out assert_equal(out.owner.name, 'user2') ## Test that a default category is assigned to the project assert out.category_id, "No category assigned to project" id_ = out.id # test re-create should fail res = self.app.post('/api/project?api_key=' + users[1].api_key, data=data) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'POST', err assert err['exception_cls'] == "DBIntegrityError", err # test create with non-allowed fields should fail data = dict(name='fail', short_name='fail', link='hateoas', wrong=15) res = self.app.post('/api/project?api_key=' + users[1].api_key, data=data) err = json.loads(res.data) err_msg = "ValueError exception should be raised" assert res.status_code == 415, err assert err['action'] == 'POST', err assert err['status'] == 'failed', err assert err['exception_cls'] == "ValueError", err_msg # Now with a JSON object but not valid data = json.dumps(data) res = self.app.post('/api/project?api_key=' + users[1].api_key, data=data) err = json.loads(res.data) err_msg = "TypeError exception should be raised" assert err['action'] == 'POST', err_msg assert err['status'] == 'failed', err_msg assert err['exception_cls'] == "TypeError", err_msg assert res.status_code == 415, err_msg # test update data = {'name': 'My New Title', 'links': 'hateoas'} data = dict(name='My New Title', links='hateoas', info={}) datajson = json.dumps(data) ## anonymous res = self.app.put('/api/project/%s' % id_, data=datajson) error_msg = 'Anonymous should not be allowed to update' assert_equal(res.status, '401 UNAUTHORIZED', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['exception_cls'] == 'Unauthorized', error ### real user but not allowed as not owner! non_owner = UserFactory.create() url = '/api/project/%s?api_key=%s' % (id_, non_owner.api_key) res = self.app.put(url, data=datajson) error_msg = 'Should not be able to update projects of others' assert_equal(res.status, '403 FORBIDDEN', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['exception_cls'] == 'Forbidden', error res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) # with hateoas links assert_equal(res.status, '200 OK', res.data) out2 = project_repo.get(id_) assert_equal(out2.name, data['name']) out = json.loads(res.data) assert out.get('status') is None, error assert out.get('id') == id_, error # without hateoas links del data['links'] newdata = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=newdata) assert_equal(res.status, '200 OK', res.data) out2 = project_repo.get(id_) assert_equal(out2.name, data['name']) out = json.loads(res.data) assert out.get('status') is None, error assert out.get('id') == id_, error assert 'task_presenter' not in out.get('info').keys(), error data['info']['task_presenter'] = 'htmlpresenter' newdata = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=newdata) assert_equal(res.status, '200 OK', res.data) out2 = project_repo.get(id_) assert_equal(out2.name, data['name']) out = json.loads(res.data) assert out.get('status') is None, error assert out.get('id') == id_, error # With wrong id res = self.app.put('/api/project/5000?api_key=%s' % users[1].api_key, data=datajson) assert_equal(res.status, '404 NOT FOUND', res.data) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['exception_cls'] == 'NotFound', error # With fake data data['algo'] = 13 datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'TypeError', err # With empty fields data.pop('algo') data['name'] = None datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'DBIntegrityError', err data['name'] = '' datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'DBIntegrityError', err data['name'] = 'something' data['short_name'] = '' datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'DBIntegrityError', err # With not JSON data datajson = {'foo': 'bar'} res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'ValueError', err # With wrong args in the URL data = dict(name=name, short_name='xxxx-project', long_description=u'Long Description\n================') datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s&search=select1' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'AttributeError', err # test delete ## anonymous res = self.app.delete('/api/project/%s' % id_, data=data) error_msg = 'Anonymous should not be allowed to delete' assert_equal(res.status, '401 UNAUTHORIZED', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'DELETE', error assert error['target'] == 'project', error ### real user but not allowed as not owner! url = '/api/project/%s?api_key=%s' % (id_, non_owner.api_key) res = self.app.delete(url, data=datajson) error_msg = 'Should not be able to delete projects of others' assert_equal(res.status, '403 FORBIDDEN', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'DELETE', error assert error['target'] == 'project', error url = '/api/project/%s?api_key=%s' % (id_, users[1].api_key) res = self.app.delete(url, data=datajson) assert_equal(res.status, '204 NO CONTENT', res.data) # delete a project that does not exist url = '/api/project/5000?api_key=%s' % users[1].api_key res = self.app.delete(url, data=datajson) error = json.loads(res.data) assert res.status_code == 404, error assert error['status'] == 'failed', error assert error['action'] == 'DELETE', error assert error['target'] == 'project', error assert error['exception_cls'] == 'NotFound', error # delete a project that does not exist url = '/api/project/?api_key=%s' % users[1].api_key res = self.app.delete(url, data=datajson) assert res.status_code == 404, error
def setUp(self): super(TestOnesignal, self).setUp() CategoryFactory.create()
def test_project_post(self): """Test API project creation and auth""" users = UserFactory.create_batch(2) cat1 = CategoryFactory.create() cat2 = CategoryFactory.create() name = u'XXXX Project' data = dict( name=name, short_name='xxxx-project', description='description', owner_id=1, long_description=u'Long Description\n================') data = json.dumps(data) # no api-key res = self.app.post('/api/project', data=data) assert_equal(res.status, '401 UNAUTHORIZED', 'Should not be allowed to create') assert res.mimetype == 'application/json' # now a real user res = self.app.post('/api/project?api_key=' + users[1].api_key, data=data) out = project_repo.get_by(name=name) assert out, out assert_equal(out.short_name, 'xxxx-project'), out assert_equal(out.owner.name, 'user2') assert_equal(out.owners_ids, [2]) id_ = out.id # now a real user with headers auth headers = [('Authorization', users[1].api_key)] new_project = dict( name=name + '2', short_name='xxxx-project2', description='description2', owner_id=1, long_description=u'Long Description\n================') new_project = json.dumps(new_project) res = self.app.post('/api/project', headers=headers, data=new_project) out = project_repo.get_by(name=name + '2') assert out, out assert_equal(out.short_name, 'xxxx-project2'), out assert_equal(out.owner.name, 'user2') # Test that a default category is assigned to the project assert cat1.id == out.category_id, "No category assigned to project" id_ = out.id # now a real user with headers auth and specific category_id headers = [('Authorization', users[1].api_key)] new_project2 = dict( name=name + '3', short_name='xxxx-project3', description='description3', owner_id=1, category_id=cat2.id, long_description=u'Long Description\n================') new_project2 = json.dumps(new_project2) res = self.app.post('/api/project', headers=headers, data=new_project2) out = project_repo.get_by(name=name + '3') assert out, out assert_equal(out.short_name, 'xxxx-project3'), out assert_equal(out.owner.name, 'user2') # Test that a default category is assigned to the project assert cat2.id == out.category_id, "No category assigned to project" # now a real user with headers auth and non-existing category_id headers = [('Authorization', users[1].api_key)] new_project3 = dict( name=name + '4', short_name='xxxx-project4', description='description4', owner_id=1, category_id=5014, long_description=u'Long Description\n================') new_project3 = json.dumps(new_project3) res = self.app.post('/api/project', headers=headers, data=new_project3) err = json.loads(res.data) assert err['status'] == 'failed' assert err['exception_msg'] == 'category_id does not exist' assert err['status_code'] == 400 # test re-create should fail res = self.app.post('/api/project?api_key=' + users[1].api_key, data=data) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'POST', err assert err['exception_cls'] == "DBIntegrityError", err # test create with non-allowed fields should fail data = dict(name='fail', short_name='fail', link='hateoas', wrong=15) res = self.app.post('/api/project?api_key=' + users[1].api_key, data=data) err = json.loads(res.data) err_msg = "ValueError exception should be raised" assert res.status_code == 415, err assert err['action'] == 'POST', err assert err['status'] == 'failed', err assert err['exception_cls'] == "ValueError", err_msg # Now with a JSON object but not valid data = json.dumps(data) res = self.app.post('/api/project?api_key=' + users[1].api_key, data=data) err = json.loads(res.data) err_msg = "TypeError exception should be raised" assert err['action'] == 'POST', err_msg assert err['status'] == 'failed', err_msg assert err['exception_cls'] == "TypeError", err_msg assert res.status_code == 415, err_msg # test update data = {'name': 'My New Title', 'links': 'hateoas'} data = dict(name='My New Title', links='hateoas', info={}) datajson = json.dumps(data) ## anonymous res = self.app.put('/api/project/%s' % id_, data=datajson) error_msg = 'Anonymous should not be allowed to update' assert_equal(res.status, '401 UNAUTHORIZED', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['exception_cls'] == 'Unauthorized', error ### real user but not allowed as not owner! non_owner = UserFactory.create() url = '/api/project/%s?api_key=%s' % (id_, non_owner.api_key) res = self.app.put(url, data=datajson) error_msg = 'Should not be able to update projects of others' assert_equal(res.status, '403 FORBIDDEN', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['exception_cls'] == 'Forbidden', error res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) # with hateoas links assert_equal(res.status, '200 OK', res.data) out2 = project_repo.get(id_) assert_equal(out2.name, data['name']) out = json.loads(res.data) assert out.get('status') is None, error assert out.get('id') == id_, error # without hateoas links del data['links'] newdata = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=newdata) assert_equal(res.status, '200 OK', res.data) out2 = project_repo.get(id_) assert_equal(out2.name, data['name']) out = json.loads(res.data) assert out.get('status') is None, error assert out.get('id') == id_, error assert 'task_presenter' not in out.get('info').keys(), error data['info']['task_presenter'] = 'htmlpresenter' newdata = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=newdata) assert_equal(res.status, '200 OK', res.data) out2 = project_repo.get(id_) assert_equal(out2.name, data['name']) out = json.loads(res.data) assert out.get('status') is None, error assert out.get('id') == id_, error # With wrong id res = self.app.put('/api/project/5000?api_key=%s' % users[1].api_key, data=datajson) assert_equal(res.status, '404 NOT FOUND', res.data) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['exception_cls'] == 'NotFound', error # With fake data data['algo'] = 13 datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'TypeError', err # With empty fields data.pop('algo') data['name'] = None datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'DBIntegrityError', err data['name'] = '' datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'DBIntegrityError', err data['name'] = 'something' data['short_name'] = '' datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'DBIntegrityError', err # With not JSON data datajson = {'foo': 'bar'} res = self.app.put('/api/project/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'ValueError', err # With wrong args in the URL data = dict( name=name, short_name='xxxx-project', long_description=u'Long Description\n================') datajson = json.dumps(data) res = self.app.put('/api/project/%s?api_key=%s&search=select1' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'AttributeError', err # test delete ## anonymous res = self.app.delete('/api/project/%s' % id_, data=data) error_msg = 'Anonymous should not be allowed to delete' assert_equal(res.status, '401 UNAUTHORIZED', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'DELETE', error assert error['target'] == 'project', error ### real user but not allowed as not owner! url = '/api/project/%s?api_key=%s' % (id_, non_owner.api_key) res = self.app.delete(url, data=datajson) error_msg = 'Should not be able to delete projects of others' assert_equal(res.status, '403 FORBIDDEN', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'DELETE', error assert error['target'] == 'project', error url = '/api/project/%s?api_key=%s' % (id_, users[1].api_key) res = self.app.delete(url, data=datajson) assert_equal(res.status, '204 NO CONTENT', res.data) assert res.mimetype == 'application/json' # delete a project that does not exist url = '/api/project/5000?api_key=%s' % users[1].api_key res = self.app.delete(url, data=datajson) error = json.loads(res.data) assert res.status_code == 404, error assert error['status'] == 'failed', error assert error['action'] == 'DELETE', error assert error['target'] == 'project', error assert error['exception_cls'] == 'NotFound', error # delete a project that does not exist url = '/api/project/?api_key=%s' % users[1].api_key res = self.app.delete(url, data=datajson) assert res.status_code == 404, error
def test_app_post(self): """Test API project creation and auth""" users = UserFactory.create_batch(2) CategoryFactory.create() name = u'XXXX Project' data = dict( name=name, short_name='xxxx-project', description='description', owner_id=1, long_description=u'Long Description\n================') data = json.dumps(data) # no api-key res = self.app.post('/api/app', data=data) assert_equal(res.status, '401 UNAUTHORIZED', 'Should not be allowed to create') # now a real user res = self.app.post('/api/app?api_key=' + users[1].api_key, data=data) out = db.session.query(App).filter_by(name=name).one() assert out, out assert_equal(out.short_name, 'xxxx-project'), out assert_equal(out.owner.name, 'user2') id_ = out.id db.session.remove() # now a real user with headers auth headers = [('Authorization', users[1].api_key)] new_app = dict( name=name + '2', short_name='xxxx-project2', description='description2', owner_id=1, long_description=u'Long Description\n================') new_app = json.dumps(new_app) res = self.app.post('/api/app', headers=headers, data=new_app) out = db.session.query(App).filter_by(name=name + '2').one() assert out, out assert_equal(out.short_name, 'xxxx-project2'), out assert_equal(out.owner.name, 'user2') ## Test that a default category is assigned to the project assert out.category_id, "No category assigned to project" id_ = out.id db.session.remove() # test re-create should fail res = self.app.post('/api/app?api_key=' + users[1].api_key, data=data) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'POST', err assert err['exception_cls'] == "IntegrityError", err # test create with non-allowed fields should fail data = dict(name='fail', short_name='fail', link='hateoas', wrong=15) res = self.app.post('/api/app?api_key=' + users[1].api_key, data=data) err = json.loads(res.data) err_msg = "ValueError exception should be raised" assert res.status_code == 415, err assert err['action'] == 'POST', err assert err['status'] == 'failed', err assert err['exception_cls'] == "ValueError", err_msg # Now with a JSON object but not valid data = json.dumps(data) res = self.app.post('/api/app?api_key=' + users[1].api_key, data=data) err = json.loads(res.data) err_msg = "TypeError exception should be raised" assert err['action'] == 'POST', err_msg assert err['status'] == 'failed', err_msg assert err['exception_cls'] == "TypeError", err_msg assert res.status_code == 415, err_msg # test update data = {'name': 'My New Title'} datajson = json.dumps(data) ## anonymous res = self.app.put('/api/app/%s' % id_, data=data) error_msg = 'Anonymous should not be allowed to update' assert_equal(res.status, '401 UNAUTHORIZED', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['exception_cls'] == 'Unauthorized', error ### real user but not allowed as not owner! non_owner = UserFactory.create() url = '/api/app/%s?api_key=%s' % (id_, non_owner.api_key) res = self.app.put(url, data=datajson) error_msg = 'Should not be able to update apps of others' assert_equal(res.status, '403 FORBIDDEN', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['exception_cls'] == 'Forbidden', error res = self.app.put('/api/app/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) assert_equal(res.status, '200 OK', res.data) out2 = db.session.query(App).get(id_) assert_equal(out2.name, data['name']) out = json.loads(res.data) assert out.get('status') is None, error assert out.get('id') == id_, error # With wrong id res = self.app.put('/api/app/5000?api_key=%s' % users[1].api_key, data=datajson) assert_equal(res.status, '404 NOT FOUND', res.data) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'PUT', error assert error['exception_cls'] == 'NotFound', error # With fake data data['algo'] = 13 datajson = json.dumps(data) res = self.app.put('/api/app/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'TypeError', err # With empty fields data.pop('algo') data['name'] = None datajson = json.dumps(data) res = self.app.put('/api/app/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'IntegrityError', err data['name'] = '' datajson = json.dumps(data) res = self.app.put('/api/app/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'IntegrityError', err data['name'] = 'something' data['short_name'] = '' datajson = json.dumps(data) res = self.app.put('/api/app/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'IntegrityError', err # With not JSON data datajson = data res = self.app.put('/api/app/%s?api_key=%s' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'ValueError', err # With wrong args in the URL data = dict( name=name, short_name='xxxx-project', long_description=u'Long Description\n================') datajson = json.dumps(data) res = self.app.put('/api/app/%s?api_key=%s&search=select1' % (id_, users[1].api_key), data=datajson) err = json.loads(res.data) assert res.status_code == 415, err assert err['status'] == 'failed', err assert err['action'] == 'PUT', err assert err['exception_cls'] == 'AttributeError', err # test delete ## anonymous res = self.app.delete('/api/app/%s' % id_, data=data) error_msg = 'Anonymous should not be allowed to delete' assert_equal(res.status, '401 UNAUTHORIZED', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'DELETE', error assert error['target'] == 'app', error ### real user but not allowed as not owner! url = '/api/app/%s?api_key=%s' % (id_, non_owner.api_key) res = self.app.delete(url, data=datajson) error_msg = 'Should not be able to delete apps of others' assert_equal(res.status, '403 FORBIDDEN', error_msg) error = json.loads(res.data) assert error['status'] == 'failed', error assert error['action'] == 'DELETE', error assert error['target'] == 'app', error url = '/api/app/%s?api_key=%s' % (id_, users[1].api_key) res = self.app.delete(url, data=datajson) assert_equal(res.status, '204 NO CONTENT', res.data) # delete a project that does not exist url = '/api/app/5000?api_key=%s' % users[1].api_key res = self.app.delete(url, data=datajson) error = json.loads(res.data) assert res.status_code == 404, error assert error['status'] == 'failed', error assert error['action'] == 'DELETE', error assert error['target'] == 'app', error assert error['exception_cls'] == 'NotFound', error # delete a project that does not exist url = '/api/app/?api_key=%s' % users[1].api_key res = self.app.delete(url, data=datajson) assert res.status_code == 404, error
def test_query_category(self): """Test API query for category endpoint works""" categories = [] cat = CategoryFactory.create(name='thinking', short_name='thinking', info=dict(foo='monkey')) categories.append(cat.dictize()) # Test for real field url = "/api/category" res = self.app.get(url + "?short_name=thinking") data = json.loads(res.data) # Should return one result assert len(data) == 1, data # Correct result assert data[0]['short_name'] == 'thinking', data # Valid field but wrong value res = self.app.get(url + "?short_name=wrongvalue") data = json.loads(res.data) assert len(data) == 0, data # Multiple fields res = self.app.get(url + '?short_name=thinking&name=thinking') data = json.loads(res.data) # One result assert len(data) == 1, data # Correct result assert data[0]['short_name'] == 'thinking', data assert data[0]['name'] == 'thinking', data # Limits res = self.app.get(url + "?limit=1") data = json.loads(res.data) for item in data: assert item['short_name'] == 'thinking', item assert len(data) == 1, data # Keyset pagination cat = CategoryFactory.create(name='computing', short_name='computing') categories.append(cat.dictize()) res = self.app.get(url) data = json.loads(res.data) tmp = '?limit=1&last_id=%s' % data[0]['id'] res = self.app.get(url + tmp) data_new = json.loads(res.data) assert len(data_new) == 1, data_new assert data_new[0]['id'] == data[1]['id'] # Errors res = self.app.get(url + "?something") err = json.loads(res.data) err_msg = "AttributeError exception should be raised" res.status_code == 415, err_msg assert res.status_code == 415, err_msg assert err['action'] == 'GET', err_msg assert err['status'] == 'failed', err_msg assert err['exception_cls'] == 'AttributeError', err_msg # Desc filter url = "/api/category?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/category?orderby=id" res = self.app.get(url) data = json.loads(res.data) err_msg = "It should get the last item first." categories_by_id = sorted(categories, key=lambda x: x['id'], reverse=False) for i in range(len(categories)): assert categories_by_id[i]['id'] == data[i]['id'] # Desc filter url = "/api/category?orderby=id&desc=true" res = self.app.get(url) data = json.loads(res.data) err_msg = "It should get the last item first." categories_by_id = sorted(categories, key=lambda x: x['id'], reverse=True) for i in range(len(categories)): assert categories_by_id[i]['id'] == data[i]['id'] # fulltextsearch url = '/api/category?info=foo::monkey&fulltextsearch=1' res = self.app.get(url) data = json.loads(res.data) assert len(data) == 1, len(data)