server/tests: switch to pytest

This commit is contained in:
rr- 2016-04-15 14:36:00 +02:00
parent 7f8c2cfa00
commit 07ea920def
18 changed files with 859 additions and 701 deletions

2
.gitignore vendored
View file

@ -1,2 +1,4 @@
config.yaml
*/*_modules/
.coverage
.cache

View file

@ -3,4 +3,5 @@ pyyaml>=3.11
falcon>=0.3.0
psycopg2>=2.6.1
SQLAlchemy>=1.0.12
green>=2.4.0
pytest>=2.9.1
pytest-cov>=2.2.1

View file

@ -0,0 +1,78 @@
from datetime import datetime
from unittest import mock
import pytest
from szurubooru import api, db, errors
from szurubooru.util import auth, mailer
def mock_user(name, rank, email):
user = db.User()
user.name = name
user.password = 'dummy'
user.password_salt = 'dummy'
user.password_hash = 'dummy'
user.email = email
user.rank = rank
user.creation_time = datetime(1997, 1, 1)
user.avatar_style = db.User.AVATAR_GRAVATAR
return user
@pytest.fixture
def password_reset_api(config_injector):
config_injector({
'secret': 'x',
'base_url': 'http://example.com/',
'name': 'Test instance',
})
return api.PasswordResetApi()
def test_reset_non_existing(password_reset_api, context_factory):
with pytest.raises(errors.NotFoundError):
password_reset_api.get(context_factory(), 'u1')
def test_reset_without_email(password_reset_api, session, context_factory):
user = mock_user('u1', 'regular_user', None)
session.add(user)
with pytest.raises(errors.ValidationError):
password_reset_api.get(context_factory(), 'u1')
def test_reset_sending_email(password_reset_api, session, context_factory):
user = mock_user('u1', 'regular_user', 'user@example.com')
session.add(user)
for getter in ['u1', 'user@example.com']:
mailer.send_mail = mock.MagicMock()
assert password_reset_api.get(context_factory(), getter) == {}
mailer.send_mail.assert_called_once_with(
'noreply@Test instance',
'user@example.com',
'Password reset for Test instance',
'You (or someone else) requested to reset your password ' +
'on Test instance.\nIf you wish to proceed, click this l' +
'ink: http://example.com/password-reset/u1:4ac0be176fb36' +
'4f13ee6b634c43220e2\nOtherwise, please ignore this email.')
def test_confirmation_non_existing(password_reset_api, context_factory):
with pytest.raises(errors.NotFoundError):
password_reset_api.post(context_factory(), 'u1')
def test_confirmation_no_token(password_reset_api, context_factory, session):
user = mock_user('u1', 'regular_user', 'user@example.com')
session.add(user)
with pytest.raises(errors.ValidationError):
password_reset_api.post(context_factory(request={}), 'u1')
def test_confirmation_bad_token(password_reset_api, context_factory, session):
user = mock_user('u1', 'regular_user', 'user@example.com')
session.add(user)
with pytest.raises(errors.ValidationError):
password_reset_api.post(
context_factory(request={'token': 'bad'}), 'u1')
def test_confirmation_good_token(password_reset_api, context_factory, session):
user = mock_user('u1', 'regular_user', 'user@example.com')
old_hash = user.password_hash
session.add(user)
context = context_factory(
request={'token': '4ac0be176fb364f13ee6b634c43220e2'})
result = password_reset_api.post(context, 'u1')
assert user.password_hash != old_hash
assert auth.is_valid_password(user, result['password']) is True

View file

@ -1,68 +0,0 @@
from unittest import mock
from szurubooru import api, errors
from szurubooru.util import auth, mailer
from szurubooru.tests.database_test_case import DatabaseTestCase
from szurubooru.tests.api import util
class TestPasswordReset(DatabaseTestCase):
def setUp(self):
super().setUp()
util.mock_config({
'secret': 'x',
'base_url': 'http://example.com/',
'name': 'Test instance',
})
util.mock_context(self)
self.api = api.PasswordResetApi()
def test_reset_non_existing(self):
self.assertRaises(errors.NotFoundError, self.api.get, self.context, 'u1')
def test_reset_without_email(self):
user = util.mock_user('u1', 'regular_user')
user.email = None
self.session.add(user)
self.assertRaises(errors.ValidationError, self.api.get, self.context, 'u1')
def test_reset_sending_email(self):
user = util.mock_user('u1', 'regular_user')
user.email = 'user@example.com'
self.session.add(user)
for getter in ['u1', 'user@example.com']:
mailer.send_mail = mock.MagicMock()
self.assertEqual({}, self.api.get(self.context, getter))
mailer.send_mail.assert_called_once_with(
'noreply@Test instance',
'user@example.com',
'Password reset for Test instance',
'You (or someone else) requested to reset your password ' +
'on Test instance.\nIf you wish to proceed, click this l' +
'ink: http://example.com/password-reset/u1:4ac0be176fb36' +
'4f13ee6b634c43220e2\nOtherwise, please ignore this email.')
def test_confirmation_non_existing(self):
self.assertRaises(errors.NotFoundError, self.api.post, self.context, 'u1')
def test_confirmation_no_token(self):
user = util.mock_user('u1', 'regular_user')
user.email = 'user@example.com'
self.session.add(user)
self.context.request = {}
self.assertRaises(errors.ValidationError, self.api.post, self.context, 'u1')
def test_confirmation_bad_token(self):
user = util.mock_user('u1', 'regular_user')
user.email = 'user@example.com'
self.session.add(user)
self.context.request = {'token': 'bad'}
self.assertRaises(errors.ValidationError, self.api.post, self.context, 'u1')
def test_confirmation_good_token(self):
user = util.mock_user('u1', 'regular_user')
user.email = 'user@example.com'
old_hash = user.password_hash
self.session.add(user)
self.context.request = {'token': '4ac0be176fb364f13ee6b634c43220e2'}
result = self.api.post(self.context, 'u1')
self.assertNotEqual(user.password_hash, old_hash)
self.assertTrue(auth.is_valid_password(user, result['password']))

View file

@ -1,366 +0,0 @@
import tempfile
from datetime import datetime
from szurubooru import api, db, errors
from szurubooru.util import auth
from szurubooru.tests.database_test_case import DatabaseTestCase
from szurubooru.tests.api import util
class TestRetrievingUsers(DatabaseTestCase):
def setUp(self):
super().setUp()
util.mock_config({
'privileges': {
'users:list': 'regular_user',
},
'thumbnails': {'avatar_width': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
})
util.mock_context(self)
def test_retrieving_multiple(self):
user1 = util.mock_user('u1', 'mod')
user2 = util.mock_user('u2', 'mod')
self.session.add_all([user1, user2])
util.mock_params(self.context, {'query': '', 'page': 1})
self.context.user.rank = 'regular_user'
api_ = api.UserListApi()
result = api_.get(self.context)
self.assertEqual(result['query'], '')
self.assertEqual(result['page'], 1)
self.assertEqual(result['pageSize'], 100)
self.assertEqual(result['total'], 2)
self.assertEqual([u['name'] for u in result['users']], ['u1', 'u2'])
def test_retrieving_multiple_without_privileges(self):
self.context.user.rank = 'anonymous'
util.mock_params(self.context, {'query': '', 'page': 1})
api_ = api.UserListApi()
self.assertRaises(errors.AuthError, api_.get, self.context)
def test_retrieving_non_existing(self):
self.context.user.rank = 'regular_user'
util.mock_params(self.context, {'query': 'asd', 'page': 1})
api_ = api.UserListApi()
result = api_.get(self.context)
self.assertEqual(result['query'], 'asd')
self.assertEqual(result['page'], 1)
self.assertEqual(result['pageSize'], 100)
self.assertEqual(result['total'], 0)
self.assertEqual([u['name'] for u in result['users']], [])
class TestRetrievingUser(DatabaseTestCase):
def setUp(self):
super().setUp()
util.mock_config({
'privileges': {
'users:view': 'regular_user',
},
'thumbnails': {'avatar_width': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
})
util.mock_context(self)
def test_retrieving_single(self):
user = util.mock_user('u1', 'regular_user')
self.session.add(user)
self.context.user.rank = 'regular_user'
util.mock_params(self.context, {'query': '', 'page': 1})
api_ = api.UserDetailApi()
result = api_.get(self.context, 'u1')
self.assertEqual(result['user']['id'], user.user_id)
self.assertEqual(result['user']['name'], 'u1')
self.assertEqual(result['user']['rank'], 'regular_user')
self.assertEqual(result['user']['creationTime'], datetime(1997, 1, 1))
self.assertEqual(result['user']['lastLoginTime'], None)
self.assertEqual(result['user']['avatarStyle'], 'gravatar')
def test_retrieving_non_existing(self):
self.context.user.rank = 'regular_user'
util.mock_params(self.context, {'query': '', 'page': 1})
api_ = api.UserDetailApi()
self.assertRaises(errors.NotFoundError, api_.get, self.context, '-')
def test_retrieving_single_without_privileges(self):
self.context.user.rank = 'anonymous'
util.mock_params(self.context, {'query': '', 'page': 1})
api_ = api.UserDetailApi()
self.assertRaises(errors.AuthError, api_.get, self.context, '-')
class TestDeletingUser(DatabaseTestCase):
def setUp(self):
super().setUp()
util.mock_config({
'privileges': {
'users:delete:self': 'regular_user',
'users:delete:any': 'mod',
},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
})
util.mock_context(self)
def test_removing_oneself(self):
user1 = util.mock_user('u1', 'regular_user')
user2 = util.mock_user('u2', 'regular_user')
self.session.add_all([user1, user2])
self.session.commit()
self.context.user.user_id = user1.user_id
self.context.user.rank = 'regular_user'
api_ = api.UserDetailApi()
self.assertRaises(errors.AuthError, api_.delete, self.context, 'u2')
api_.delete(self.context, 'u1')
self.assertEqual(self.session.query(db.User).filter_by(name='u1').all(), [])
def test_removing_someone_else(self):
user1 = util.mock_user('u1', 'regular_user')
user2 = util.mock_user('u2', 'regular_user')
self.session.add_all([user1, user2])
self.session.commit()
self.context.user.rank = 'mod'
api_ = api.UserDetailApi()
api_.delete(self.context, 'u1')
api_.delete(self.context, 'u2')
self.assertEqual(self.session.query(db.User).filter_by(name='u1').all(), [])
self.assertEqual(self.session.query(db.User).filter_by(name='u2').all(), [])
def test_removing_non_existing(self):
self.context.user.rank = 'regular_user'
api_ = api.UserDetailApi()
self.assertRaises(errors.NotFoundError, api_.delete, self.context, 'bad')
class TestCreatingUser(DatabaseTestCase):
def setUp(self):
super().setUp()
util.mock_config({
'secret': '',
'user_name_regex': '.{3,}',
'password_regex': '.{3,}',
'default_rank': 'regular_user',
'thumbnails': {'avatar_width': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
'privileges': {
'users:create': 'anonymous',
},
})
self.api = api.UserListApi()
util.mock_context(self)
self.context.user.rank = 'anonymous'
def test_first_user_becomes_admin(self):
self.context.request = {
'name': 'chewie',
'email': 'asd@asd.asd',
'password': 'oks',
}
self.api.post(self.context)
created_user = self.session.query(db.User).filter_by(name='chewie').one()
self.assertEqual(created_user.name, 'chewie')
self.assertEqual(created_user.email, 'asd@asd.asd')
self.assertEqual(created_user.rank, 'admin')
self.assertTrue(auth.is_valid_password(created_user, 'oks'))
self.assertFalse(auth.is_valid_password(created_user, 'invalid'))
def test_subsequent_users_are_created_normally(self):
self.context.request = {
'name': 'chewie',
'email': 'asd@asd.asd',
'password': 'oks',
}
self.api.post(self.context)
self.context.request['name'] = 'chewie2'
self.api.post(self.context)
created_user = self.session.query(db.User).filter_by(name='chewie2').one()
self.assertEqual(created_user.name, 'chewie2')
self.assertEqual(created_user.email, 'asd@asd.asd')
self.assertEqual(created_user.rank, 'regular_user')
self.assertTrue(auth.is_valid_password(created_user, 'oks'))
self.assertFalse(auth.is_valid_password(created_user, 'invalid'))
def test_creating_user_that_already_exists(self):
self.context.request = {
'name': 'chewie',
'email': 'asd@asd.asd',
'password': 'oks',
}
self.api.post(self.context)
self.assertRaises(errors.IntegrityError, self.api.post, self.context)
def test_creating_user_that_already_exists_insensitive(self):
self.context.request = {
'name': 'chewie',
'email': 'asd@asd.asd',
'password': 'oks',
}
self.api.post(self.context)
self.context.name = 'chewie'
self.assertRaises(errors.IntegrityError, self.api.post, self.context)
def test_missing_field(self):
for key in ['name', 'email', 'password']:
self.context.request = {
'name': 'chewie',
'email': 'asd@asd.asd',
'password': 'oks',
}
del self.context.request[key]
self.assertRaises(errors.ValidationError, self.api.post, self.context)
class TestUpdatingUser(DatabaseTestCase):
def setUp(self):
super().setUp()
util.mock_config({
'secret': '',
'user_name_regex': '.{3,}',
'password_regex': '.{3,}',
'data_dir': tempfile.gettempdir(),
'data_url': 'http://example.com/data/',
'thumbnails': {'avatar_width': 200, 'avatar_height': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
'privileges': {
'users:edit:self:name': 'regular_user',
'users:edit:self:pass': 'regular_user',
'users:edit:self:email': 'regular_user',
'users:edit:self:rank': 'mod',
'users:edit:self:avatar': 'mod',
'users:edit:any:name': 'mod',
'users:edit:any:pass': 'mod',
'users:edit:any:email': 'mod',
'users:edit:any:rank': 'admin',
'users:edit:any:avatar': 'admin',
},
})
util.mock_context(self)
self.api = api.UserDetailApi()
def test_update_changing_nothing(self):
admin_user = util.mock_user('u1', 'admin')
self.session.add(admin_user)
self.context.user = admin_user
self.api.put(self.context, 'u1')
admin_user = self.session.query(db.User).filter_by(name='u1').one()
self.assertEqual(admin_user.name, 'u1')
self.assertEqual(admin_user.email, 'dummy')
self.assertEqual(admin_user.rank, 'admin')
def test_updating_non_existing_user(self):
admin_user = util.mock_user('u1', 'admin')
self.session.add(admin_user)
self.context.user = admin_user
self.assertRaises(errors.NotFoundError, self.api.put, self.context, 'u2')
def test_admin_updating_everything_for_themselves(self):
admin_user = util.mock_user('u1', 'admin')
self.session.add(admin_user)
self.context.user = admin_user
self.context.request = {
'name': 'chewie',
'email': 'asd@asd.asd',
'password': 'oks',
'rank': 'mod',
'avatarStyle': 'gravatar',
}
self.api.put(self.context, 'u1')
admin_user = self.session.query(db.User).filter_by(name='chewie').one()
self.assertEqual(admin_user.name, 'chewie')
self.assertEqual(admin_user.email, 'asd@asd.asd')
self.assertEqual(admin_user.rank, 'mod')
self.assertEqual(admin_user.avatar_style, admin_user.AVATAR_GRAVATAR)
self.assertTrue(auth.is_valid_password(admin_user, 'oks'))
self.assertFalse(auth.is_valid_password(admin_user, 'invalid'))
def test_removing_email(self):
admin_user = util.mock_user('u1', 'admin')
self.session.add(admin_user)
self.context.user = admin_user
self.context.request = {'email': ''}
self.api.put(self.context, 'u1')
admin_user = self.session.query(db.User).filter_by(name='u1').one()
self.assertEqual(admin_user.email, None)
def test_invalid_inputs(self):
admin_user = util.mock_user('u1', 'admin')
self.session.add(admin_user)
self.context.user = admin_user
self.context.request = {'name': '.'}
self.assertRaises(
errors.ValidationError, self.api.put, self.context, 'u1')
self.context.request = {'password': '.'}
self.assertRaises(
errors.ValidationError, self.api.put, self.context, 'u1')
self.context.request = {'rank': '.'}
self.assertRaises(
errors.ValidationError, self.api.put, self.context, 'u1')
self.context.request = {'email': '.'}
self.assertRaises(
errors.ValidationError, self.api.put, self.context, 'u1')
self.context.request = {'avatarStyle': 'manual'}
self.assertRaises(
errors.ValidationError, self.api.put, self.context, 'u1')
def test_user_trying_to_update_someone_else(self):
user1 = util.mock_user('u1', 'regular_user')
user2 = util.mock_user('u2', 'regular_user')
self.session.add_all([user1, user2])
self.context.user = user1
for request in [
{'name': 'whatever'},
{'email': 'whatever'},
{'rank': 'whatever'},
{'password': 'whatever'}]:
self.context.request = request
self.assertRaises(
errors.AuthError, self.api.put, self.context, user2.name)
def test_user_trying_to_become_someone_else(self):
user1 = util.mock_user('me', 'regular_user')
user2 = util.mock_user('her', 'regular_user')
self.session.add_all([user1, user2])
self.context.user = user1
self.context.request = {'name': 'her'}
self.assertRaises(
errors.IntegrityError, self.api.put, self.context, 'me')
self.session.rollback()
def test_user_trying_to_become_someone_else_insensitive(self):
user1 = util.mock_user('me', 'regular_user')
user2 = util.mock_user('her', 'regular_user')
self.session.add_all([user1, user2])
self.context.user = user1
self.context.request = {'name': 'HER'}
self.assertRaises(
errors.IntegrityError, self.api.put, self.context, 'me')
self.session.rollback()
def test_mods_trying_to_become_admin(self):
user1 = util.mock_user('u1', 'mod')
user2 = util.mock_user('u2', 'mod')
self.session.add_all([user1, user2])
self.context.user = user1
self.context.request = {'rank': 'admin'}
self.assertRaises(
errors.AuthError, self.api.put, self.context, user1.name)
self.assertRaises(
errors.AuthError, self.api.put, self.context, user2.name)
def test_uploading_avatar(self):
user = util.mock_user('u1', 'mod')
self.session.add(user)
self.context.user = user
self.context.request = {
'avatarStyle': 'manual',
}
empty_pixel = \
b'\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00' \
b'\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x01\x00\x2c\x00\x00\x00\x00' \
b'\x01\x00\x01\x00\x00\x02\x02\x4c\x01\x00\x3b'
self.context.files['avatar'] = empty_pixel
response = self.api.put(self.context, 'u1')
user = self.session.query(db.User).filter_by(name='u1').one()
self.assertEqual(user.avatar_style, user.AVATAR_MANUAL)
self.assertEqual(
response['user']['avatarUrl'],
'http://example.com/data/avatars/u1.jpg')

View file

@ -0,0 +1,112 @@
import pytest
from datetime import datetime
from szurubooru import api, db, errors
from szurubooru.util import auth
@pytest.fixture
def user_list_api():
return api.UserListApi()
def test_creating_users(
session,
config_injector,
context_factory,
user_factory,
user_list_api):
config_injector({
'secret': '',
'user_name_regex': '.{3,}',
'password_regex': '.{3,}',
'default_rank': 'regular_user',
'thumbnails': {'avatar_width': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
'privileges': {'users:create': 'anonymous'},
})
user_list_api.post(
context_factory(
request={
'name': 'chewie1',
'email': 'asd@asd.asd',
'password': 'oks',
},
user=user_factory(rank='regular_user')))
user_list_api.post(
context_factory(
request={
'name': 'chewie2',
'email': 'asd@asd.asd',
'password': 'sok',
},
user=user_factory(rank='regular_user')))
first_user = session.query(db.User).filter_by(name='chewie1').one()
other_user = session.query(db.User).filter_by(name='chewie2').one()
assert first_user.name == 'chewie1'
assert first_user.email == 'asd@asd.asd'
assert first_user.rank == 'admin'
assert auth.is_valid_password(first_user, 'oks') is True
assert auth.is_valid_password(first_user, 'invalid') is False
assert other_user.name == 'chewie2'
assert other_user.email == 'asd@asd.asd'
assert other_user.rank == 'regular_user'
assert auth.is_valid_password(other_user, 'sok') is True
assert auth.is_valid_password(other_user, 'invalid') is False
def test_creating_user_that_already_exists(
config_injector, context_factory, user_factory, user_list_api):
config_injector({
'secret': '',
'user_name_regex': '.{3,}',
'password_regex': '.{3,}',
'default_rank': 'regular_user',
'thumbnails': {'avatar_width': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
'privileges': {'users:create': 'anonymous'},
})
user_list_api.post(
context_factory(
request={
'name': 'chewie',
'email': 'asd@asd.asd',
'password': 'oks',
},
user=user_factory(rank='regular_user')))
with pytest.raises(errors.IntegrityError):
user_list_api.post(
context_factory(
request={
'name': 'chewie',
'email': 'asd@asd.asd',
'password': 'oks',
},
user=user_factory(rank='regular_user')))
with pytest.raises(errors.IntegrityError):
user_list_api.post(
context_factory(
request={
'name': 'CHEWIE',
'email': 'asd@asd.asd',
'password': 'oks',
},
user=user_factory(rank='regular_user')))
@pytest.mark.parametrize('field', ['name', 'email', 'password'])
def test_missing_field(
config_injector, context_factory, user_factory, user_list_api, field):
config_injector({
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'privileges': {'users:create': 'anonymous'},
})
request = {
'name': 'chewie',
'email': 'asd@asd.asd',
'password': 'oks',
}
del request[field]
with pytest.raises(errors.ValidationError):
user_list_api.post(
context_factory(
request=request, user=user_factory(rank='regular_user')))

View file

@ -0,0 +1,65 @@
import pytest
from datetime import datetime
from szurubooru import api, db, errors
@pytest.fixture
def user_detail_api():
return api.UserDetailApi()
def test_removing_oneself(
session,
config_injector,
context_factory,
user_factory,
user_detail_api):
config_injector({
'privileges': {
'users:delete:self': 'regular_user',
'users:delete:any': 'mod',
},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
})
user1 = user_factory(name='u1', rank='regular_user')
user2 = user_factory(name='u2', rank='regular_user')
session.add_all([user1, user2])
session.commit()
with pytest.raises(errors.AuthError):
user_detail_api.delete(context_factory(user=user1), 'u2')
user_detail_api.delete(context_factory(user=user1), 'u1')
assert [u.name for u in session.query(db.User).all()] == ['u2']
def test_removing_someone_else(
session,
config_injector,
context_factory,
user_factory,
user_detail_api):
config_injector({
'privileges': {
'users:delete:self': 'regular_user',
'users:delete:any': 'mod',
},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
})
user1 = user_factory(name='u1', rank='regular_user')
user2 = user_factory(name='u2', rank='regular_user')
mod_user = user_factory(rank='mod')
session.add_all([user1, user2])
session.commit()
user_detail_api.delete(context_factory(user=mod_user), 'u1')
user_detail_api.delete(context_factory(user=mod_user), 'u2')
assert session.query(db.User).all() == []
def test_removing_non_existing(
context_factory, config_injector, user_factory, user_detail_api):
config_injector({
'privileges': {
'users:delete:self': 'regular_user',
'users:delete:any': 'mod',
},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
})
with pytest.raises(errors.NotFoundError):
user_detail_api.delete(
context_factory(user=user_factory(rank='regular_user')), 'bad')

View file

@ -0,0 +1,116 @@
import pytest
from datetime import datetime
from szurubooru import api, db, errors
@pytest.fixture
def user_list_api():
return api.UserListApi()
@pytest.fixture
def user_detail_api():
return api.UserDetailApi()
def test_retrieving_multiple(
session,
config_injector,
context_factory,
user_factory,
user_list_api):
config_injector({
'privileges': {'users:list': 'regular_user'},
'thumbnails': {'avatar_width': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
})
user1 = user_factory(name='u1', rank='mod')
user2 = user_factory(name='u2', rank='mod')
session.add_all([user1, user2])
result = user_list_api.get(
context_factory(
params={'query': '', 'page': 1},
user=user_factory(rank='regular_user')))
assert result['query'] == ''
assert result['page'] == 1
assert result['pageSize'] == 100
assert result['total'] == 2
assert [u['name'] for u in result['users']] == ['u1', 'u2']
def test_retrieving_multiple_without_privileges(
context_factory, config_injector, user_factory, user_list_api):
config_injector({
'privileges': {'users:list': 'regular_user'},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
})
with pytest.raises(errors.AuthError):
user_list_api.get(
context_factory(
params={'query': '', 'page': 1},
user=user_factory(rank='anonymous')))
def test_retrieving_multiple_with_privileges(
context_factory, config_injector, user_factory, user_list_api):
config_injector({
'privileges': {'users:list': 'regular_user'},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
})
result = user_list_api.get(
context_factory(
params={'query': 'asd', 'page': 1},
user=user_factory(rank='regular_user')))
assert result['query'] == 'asd'
assert result['page'] == 1
assert result['pageSize'] == 100
assert result['total'] == 0
assert [u['name'] for u in result['users']] == []
def test_retrieving_single(
session,
config_injector,
context_factory,
user_factory,
user_detail_api):
config_injector({
'privileges': {'users:view': 'regular_user'},
'thumbnails': {'avatar_width': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
})
user = user_factory(name='u1', rank='regular_user')
session.add(user)
result = user_detail_api.get(
context_factory(
params={'query': '', 'page': 1},
user=user_factory(rank='regular_user')),
'u1')
assert result['user']['id'] == user.user_id
assert result['user']['name'] == 'u1'
assert result['user']['rank'] == 'regular_user'
assert result['user']['creationTime'] == datetime(1997, 1, 1)
assert result['user']['lastLoginTime'] == None
assert result['user']['avatarStyle'] == 'gravatar'
def test_retrieving_non_existing(
context_factory, config_injector, user_factory, user_detail_api):
config_injector({
'privileges': {'users:view': 'regular_user'},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
})
with pytest.raises(errors.NotFoundError):
user_detail_api.get(
context_factory(
params={'query': '', 'page': 1},
user=user_factory(rank='regular_user')),
'-')
def test_retrieving_single_without_privileges(
context_factory, config_injector, user_factory, user_detail_api):
config_injector({
'privileges': {'users:view': 'regular_user'},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
})
with pytest.raises(errors.AuthError):
user_detail_api.get(
context_factory(
params={'query': '', 'page': 1},
user=user_factory(rank='anonymous')),
'-')

View file

@ -0,0 +1,237 @@
import pytest
from szurubooru import api, db, errors
from szurubooru.util import auth
@pytest.fixture
def user_detail_api():
return api.UserDetailApi()
def test_updating_user(
session,
config_injector,
context_factory,
user_factory,
user_detail_api):
config_injector({
'secret': '',
'user_name_regex': '.{3,}',
'password_regex': '.{3,}',
'thumbnails': {'avatar_width': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
'privileges': {
'users:edit:self:name': 'regular_user',
'users:edit:self:pass': 'regular_user',
'users:edit:self:email': 'regular_user',
'users:edit:self:rank': 'mod',
'users:edit:self:avatar': 'mod',
},
})
user = user_factory(name='u1', rank='admin')
session.add(user)
user_detail_api.put(
context_factory(
request={
'name': 'chewie',
'email': 'asd@asd.asd',
'password': 'oks',
'rank': 'mod',
'avatarStyle': 'gravatar',
},
user=user),
'u1')
user = session.query(db.User).filter_by(name='chewie').one()
assert user.name == 'chewie'
assert user.email == 'asd@asd.asd'
assert user.rank == 'mod'
assert user.avatar_style == user.AVATAR_GRAVATAR
assert auth.is_valid_password(user, 'oks') is True
assert auth.is_valid_password(user, 'invalid') is False
def test_update_changing_nothing(
session,
config_injector,
context_factory,
user_factory,
user_detail_api):
config_injector({
'thumbnails': {'avatar_width': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
})
user = user_factory(name='u1', rank='admin')
session.add(user)
user_detail_api.put(context_factory(user=user), 'u1')
user = session.query(db.User).filter_by(name='u1').one()
assert user.name == 'u1'
assert user.email == 'dummy'
assert user.rank == 'admin'
def test_updating_non_existing_user(
session,
config_injector,
context_factory,
user_factory,
user_detail_api):
config_injector({
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
})
user = user_factory(name='u1', rank='admin')
session.add(user)
with pytest.raises(errors.NotFoundError):
user_detail_api.put(context_factory(user=user), 'u2')
def test_removing_email(
session,
config_injector,
context_factory,
user_factory,
user_detail_api):
config_injector({
'thumbnails': {'avatar_width': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
'privileges': {'users:edit:self:email': 'regular_user'},
})
user = user_factory(name='u1', rank='admin')
session.add(user)
user_detail_api.put(
context_factory(request={'email': ''}, user=user), 'u1')
assert session.query(db.User).filter_by(name='u1').one().email is None
@pytest.mark.parametrize('request', [
{'name': '.'},
{'password': '.'},
{'rank': '.'},
{'email': '.'},
{'avatarStyle': 'manual'},
])
def test_invalid_inputs(
session,
config_injector,
context_factory,
user_factory,
user_detail_api,
request):
config_injector({
'user_name_regex': '.{3,}',
'password_regex': '.{3,}',
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'privileges': {
'users:edit:self:name': 'regular_user',
'users:edit:self:pass': 'regular_user',
'users:edit:self:email': 'regular_user',
'users:edit:self:rank': 'mod',
'users:edit:self:avatar': 'mod',
},
})
user = user_factory(name='u1', rank='admin')
session.add(user)
with pytest.raises(errors.ValidationError):
user_detail_api.put(context_factory(request=request, user=user), 'u1')
@pytest.mark.parametrize('request', [
{'name': 'whatever'},
{'email': 'whatever'},
{'rank': 'whatever'},
{'password': 'whatever'},
{'avatarStyle': 'whatever'},
])
def test_user_trying_to_update_someone_else(
session,
config_injector,
context_factory,
user_factory,
user_detail_api,
request):
config_injector({
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'privileges': {
'users:edit:any:name': 'mod',
'users:edit:any:pass': 'mod',
'users:edit:any:email': 'mod',
'users:edit:any:rank': 'admin',
'users:edit:any:avatar': 'admin',
},
})
user1 = user_factory(name='u1', rank='regular_user')
user2 = user_factory(name='u2', rank='regular_user')
session.add_all([user1, user2])
with pytest.raises(errors.AuthError):
user_detail_api.put(
context_factory(request=request, user=user1), user2.name)
def test_user_trying_to_become_someone_else(
session,
config_injector,
context_factory,
user_factory,
user_detail_api):
config_injector({
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'privileges': {'users:edit:self:name': 'regular_user'},
})
user1 = user_factory(name='me', rank='regular_user')
user2 = user_factory(name='her', rank='regular_user')
session.add_all([user1, user2])
with pytest.raises(errors.IntegrityError):
user_detail_api.put(
context_factory(request={'name': 'her'}, user=user1),
'me')
with pytest.raises(errors.IntegrityError):
user_detail_api.put(
context_factory(request={'name': 'HER'}, user=user1), 'me')
def test_mods_trying_to_become_admin(
session,
config_injector,
context_factory,
user_factory,
user_detail_api):
config_injector({
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'privileges': {
'users:edit:self:rank': 'mod',
'users:edit:any:rank': 'admin',
},
})
user1 = user_factory(name='u1', rank='mod')
user2 = user_factory(name='u2', rank='mod')
session.add_all([user1, user2])
context = context_factory(request={'rank': 'admin'}, user=user1)
with pytest.raises(errors.AuthError):
user_detail_api.put(context, user1.name)
with pytest.raises(errors.AuthError):
user_detail_api.put(context, user2.name)
def test_uploading_avatar(
tmpdir,
session,
config_injector,
context_factory,
user_factory,
user_detail_api):
config_injector({
'data_dir': str(tmpdir.mkdir('data')),
'data_url': 'http://example.com/data/',
'thumbnails': {'avatar_width': 200, 'avatar_height': 200},
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
'rank_names': {},
'privileges': {'users:edit:self:avatar': 'mod'},
})
user = user_factory(name='u1', rank='mod')
session.add(user)
empty_pixel = \
b'\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00' \
b'\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x01\x00\x2c\x00\x00\x00\x00' \
b'\x01\x00\x01\x00\x00\x02\x02\x4c\x01\x00\x3b'
response = user_detail_api.put(
context_factory(
request={'avatarStyle': 'manual'},
files={'avatar': empty_pixel},
user=user),
'u1')
user = session.query(db.User).filter_by(name='u1').one()
assert user.avatar_style == user.AVATAR_MANUAL
assert response['user']['avatarUrl'] == \
'http://example.com/data/avatars/u1.jpg'

View file

@ -1,42 +0,0 @@
from datetime import datetime
from szurubooru import config, db
from szurubooru.util import misc
def mock_config(config_mock):
config.config = config_mock
def mock_user(name, rank='admin'):
user = db.User()
user.name = name
user.password = 'dummy'
user.password_salt = 'dummy'
user.password_hash = 'dummy'
user.email = 'dummy'
user.rank = rank
user.creation_time = datetime(1997, 1, 1)
user.avatar_style = db.User.AVATAR_GRAVATAR
return user
def mock_context(parent):
context = misc.dotdict()
context.session = parent.session
context.request = {}
context.files = {}
context.user = db.User()
parent.context = context
def mock_params(context, params):
def get_param_as_string(key, default=None, required=False):
if key not in params:
if required:
raise RuntimeError('Param is missing!')
return default
return params[key]
def get_param_as_int(key, default=None, required=False):
if key not in params:
if required:
raise RuntimeError('Param is missing!')
return default
return int(params[key])
context.get_param_as_string = get_param_as_string
context.get_param_as_int = get_param_as_int

View file

@ -0,0 +1,61 @@
from datetime import datetime
import pytest
import sqlalchemy
from szurubooru import db, config
from szurubooru.util import misc
@pytest.fixture
def session():
engine = sqlalchemy.create_engine('sqlite:///:memory:')
session_maker = sqlalchemy.orm.sessionmaker(bind=engine)
session_instance = sqlalchemy.orm.scoped_session(session_maker)
db.Base.query = session_instance.query_property()
db.Base.metadata.create_all(bind=engine)
return session_instance
@pytest.fixture
def context_factory(session):
def factory(request=None, params=None, files=None, user=None):
params = params or {}
def get_param_as_string(key, default=None, required=False):
if key not in params:
if required:
raise RuntimeError('Param is missing!')
return default
return params[key]
def get_param_as_int(key, default=None, required=False):
if key not in params:
if required:
raise RuntimeError('Param is missing!')
return default
return int(params[key])
context = misc.dotdict()
context.session = session
context.request = request or {}
context.files = files or {}
context.user = user or db.User()
context.get_param_as_string = get_param_as_string
context.get_param_as_int = get_param_as_int
return context
return factory
@pytest.fixture
def config_injector():
def injector(new_config_content):
config.config = new_config_content
return injector
@pytest.fixture
def user_factory():
def factory(name='dummy', rank='regular_user'):
user = db.User()
user.name = name
user.password = 'dummy'
user.password_salt = 'dummy'
user.password_hash = 'dummy'
user.email = 'dummy'
user.rank = rank
user.creation_time = datetime(1997, 1, 1)
user.avatar_style = db.User.AVATAR_GRAVATAR
return user
return factory

View file

@ -1,11 +0,0 @@
import unittest
import sqlalchemy
from szurubooru import db
class DatabaseTestCase(unittest.TestCase):
def setUp(self):
engine = sqlalchemy.create_engine('sqlite:///:memory:')
session_maker = sqlalchemy.orm.sessionmaker(bind=engine)
self.session = sqlalchemy.orm.scoped_session(session_maker)
db.Base.query = self.session.query_property()
db.Base.metadata.create_all(bind=engine)

View file

@ -1,192 +1,170 @@
from datetime import datetime
from szurubooru import errors, search
from szurubooru.tests.database_test_case import DatabaseTestCase
from szurubooru.tests.api import util
import pytest
from szurubooru import db, errors, search
class TestUserSearchExecutor(DatabaseTestCase):
def setUp(self):
super().setUp()
self.search_config = search.UserSearchConfig()
self.executor = search.SearchExecutor(self.search_config)
def mock_user(name):
user = db.User()
user.name = name
user.password = 'dummy'
user.password_salt = 'dummy'
user.password_hash = 'dummy'
user.email = 'dummy'
user.rank = 'dummy'
user.creation_time = datetime(1997, 1, 1)
user.avatar_style = db.User.AVATAR_GRAVATAR
return user
def _test(self, query, page, page_size, expected_count, expected_user_names):
count, users = self.executor.execute(self.session, query, page, page_size)
self.assertEqual(count, expected_count)
self.assertEqual([u.name for u in users], expected_user_names)
@pytest.fixture
def executor(session):
search_config = search.UserSearchConfig()
return search.SearchExecutor(search_config)
def _test_raises(self, query, page, page_size):
self.assertRaises(
errors.SearchError,
self.executor.execute,
self.session,
query,
page,
page_size)
@pytest.fixture
def verify_unpaged(session, executor):
def verify(input, expected_user_names):
actual_count, actual_users = executor.execute(
session, input, page=1, page_size=100)
actual_user_names = [u.name for u in actual_users]
assert actual_count == len(expected_user_names)
assert actual_user_names == expected_user_names
return verify
def test_filter_by_creation_time(self):
user1 = util.mock_user('u1')
user2 = util.mock_user('u2')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2015, 1, 1)
self.session.add_all([user1, user2])
for alias in ['creation-time', 'creation-date']:
self._test('%s:2014' % alias, 1, 100, 1, ['u1'])
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_user_names', [
('creation-time:2014', ['u1', 'u2']),
('creation-date:2014', ['u1', 'u2']),
('-creation-time:2014', ['u3']),
('-creation-date:2014', ['u3']),
('creation-time:2014..2014-06', ['u1', 'u2']),
('creation-time:2014-06..2015-01-01', ['u2', 'u3']),
('creation-time:2014-06..', ['u2', 'u3']),
('creation-time:..2014-06', ['u1', 'u2']),
('-creation-time:2014..2014-06', ['u3']),
('-creation-time:2014-06..2015-01-01', ['u1']),
('creation-date:2014..2014-06', ['u1', 'u2']),
('creation-date:2014-06..2015-01-01', ['u2', 'u3']),
('creation-date:2014-06..', ['u2', 'u3']),
('creation-date:..2014-06', ['u1', 'u2']),
('-creation-date:2014..2014-06', ['u3']),
('-creation-date:2014-06..2015-01-01', ['u1']),
('creation-time:2014-01,2015', ['u1', 'u3']),
('creation-date:2014-01,2015', ['u1', 'u3']),
('-creation-time:2014-01,2015', ['u2']),
('-creation-date:2014-01,2015', ['u2']),
])
def test_filter_by_creation_time(
verify_unpaged, session, input, expected_user_names):
user1 = mock_user('u1')
user2 = mock_user('u2')
user3 = mock_user('u3')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2014, 6, 1)
user3.creation_time = datetime(2015, 1, 1)
session.add_all([user1, user2, user3])
verify_unpaged(input, expected_user_names)
def test_filter_by_negated_creation_time(self):
user1 = util.mock_user('u1')
user2 = util.mock_user('u2')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2015, 1, 1)
self.session.add_all([user1, user2])
for alias in ['creation-time', 'creation-date']:
self._test('-%s:2014' % alias, 1, 100, 1, ['u2'])
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_user_names', [
('name:user1', ['user1']),
('name:user2', ['user2']),
('name:none', []),
('name:', []),
('name:*1', ['user1']),
('name:*2', ['user2']),
('name:*', ['user1', 'user2', 'user3']),
('name:u*', ['user1', 'user2', 'user3']),
('name:*ser*', ['user1', 'user2', 'user3']),
('name:*zer*', []),
('name:zer*', []),
('name:*zer', []),
('-name:user1', ['user2', 'user3']),
('-name:user2', ['user1', 'user3']),
('name:user1,user2', ['user1', 'user2']),
('-name:user1,user3', ['user2']),
])
def test_filter_by_name(session, verify_unpaged, input, expected_user_names):
session.add(mock_user('user1'))
session.add(mock_user('user2'))
session.add(mock_user('user3'))
verify_unpaged(input, expected_user_names)
def test_filter_by_ranged_creation_time(self):
user1 = util.mock_user('u1')
user2 = util.mock_user('u2')
user3 = util.mock_user('u3')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2014, 6, 1)
user3.creation_time = datetime(2015, 1, 1)
self.session.add_all([user1, user2, user3])
for alias in ['creation-time', 'creation-date']:
self._test('%s:2014..2014-06' % alias, 1, 100, 2, ['u1', 'u2'])
self._test('%s:2014-06..2015-01-01' % alias, 1, 100, 2, ['u2', 'u3'])
self._test('%s:2014-06..' % alias, 1, 100, 2, ['u2', 'u3'])
self._test('%s:..2014-06' % alias, 1, 100, 2, ['u1', 'u2'])
self._test_raises('%s:..' % alias, 1, 100)
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_user_names', [
('', ['u1', 'u2']),
('u1', ['u1']),
('u2', ['u2']),
('u1,u2', ['u1', 'u2']),
])
def test_anonymous(session, verify_unpaged, input, expected_user_names):
session.add(mock_user('u1'))
session.add(mock_user('u2'))
verify_unpaged(input, expected_user_names)
def test_filter_by_negated_ranged_creation_time(self):
user1 = util.mock_user('u1')
user2 = util.mock_user('u2')
user3 = util.mock_user('u3')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2014, 6, 1)
user3.creation_time = datetime(2015, 1, 1)
self.session.add_all([user1, user2, user3])
for alias in ['creation-time', 'creation-date']:
self._test('-%s:2014..2014-06' % alias, 1, 100, 1, ['u3'])
self._test('-%s:2014-06..2015-01-01' % alias, 1, 100, 1, ['u1'])
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_user_names', [
('creation-time:2014 u1', ['u1']),
('creation-time:2014 u2', ['u2']),
('creation-time:2016 u2', []),
])
def test_combining_tokens(session, verify_unpaged, input, expected_user_names):
user1 = mock_user('u1')
user2 = mock_user('u2')
user3 = mock_user('u3')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2014, 6, 1)
user3.creation_time = datetime(2015, 1, 1)
session.add_all([user1, user2, user3])
verify_unpaged(input, expected_user_names)
def test_filter_by_composite_creation_time(self):
user1 = util.mock_user('u1')
user2 = util.mock_user('u2')
user3 = util.mock_user('u3')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2014, 6, 1)
user3.creation_time = datetime(2015, 1, 1)
self.session.add_all([user1, user2, user3])
for alias in ['creation-time', 'creation-date']:
self._test('%s:2014-01,2015' % alias, 1, 100, 2, ['u1', 'u3'])
# -----------------------------------------------------------------------------
@pytest.mark.parametrize(
'page,page_size,expected_total_count,expected_user_names', [
(1, 1, 2, ['u1']),
(2, 1, 2, ['u2']),
(3, 1, 2, []),
(0, 1, 2, ['u1']),
(0, 0, 2, ['u1']),
])
def test_paging(
session, executor, page, page_size,
expected_total_count, expected_user_names):
session.add(mock_user('u1'))
session.add(mock_user('u2'))
actual_count, actual_users = executor.execute(
session, '', page=page, page_size=page_size)
actual_user_names = [u.name for u in actual_users]
assert actual_count == expected_total_count
assert actual_user_names == expected_user_names
def test_filter_by_negated_composite_creation_time(self):
user1 = util.mock_user('u1')
user2 = util.mock_user('u2')
user3 = util.mock_user('u3')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2014, 6, 1)
user3.creation_time = datetime(2015, 1, 1)
self.session.add_all([user1, user2, user3])
for alias in ['creation-time', 'creation-date']:
self._test('-%s:2014-01,2015' % alias, 1, 100, 1, ['u2'])
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_user_names', [
('', ['u1', 'u2']),
('order:name', ['u1', 'u2']),
('-order:name', ['u2', 'u1']),
('order:name,asc', ['u1', 'u2']),
('order:name,desc', ['u2', 'u1']),
('-order:name,asc', ['u2', 'u1']),
('-order:name,desc', ['u1', 'u2']),
])
def test_order_by_name(session, verify_unpaged, input, expected_user_names):
session.add(mock_user('u2'))
session.add(mock_user('u1'))
verify_unpaged(input, expected_user_names)
def test_filter_by_name(self):
self.session.add(util.mock_user('u1'))
self.session.add(util.mock_user('u2'))
self._test('name:u1', 1, 100, 1, ['u1'])
self._test('name:u2', 1, 100, 1, ['u2'])
def test_filter_by_name_wildcards(self):
self.session.add(util.mock_user('user1'))
self.session.add(util.mock_user('user2'))
self._test('name:*1', 1, 100, 1, ['user1'])
self._test('name:*2', 1, 100, 1, ['user2'])
self._test('name:*', 1, 100, 2, ['user1', 'user2'])
self._test('name:u*', 1, 100, 2, ['user1', 'user2'])
self._test('name:*ser*', 1, 100, 2, ['user1', 'user2'])
self._test('name:*zer*', 1, 100, 0, [])
self._test('name:zer*', 1, 100, 0, [])
self._test('name:*zer', 1, 100, 0, [])
def test_filter_by_negated_name(self):
self.session.add(util.mock_user('u1'))
self.session.add(util.mock_user('u2'))
self._test('-name:u1', 1, 100, 1, ['u2'])
self._test('-name:u2', 1, 100, 1, ['u1'])
def test_filter_by_composite_name(self):
self.session.add(util.mock_user('u1'))
self.session.add(util.mock_user('u2'))
self.session.add(util.mock_user('u3'))
self._test('name:u1,u2', 1, 100, 2, ['u1', 'u2'])
def test_filter_by_negated_composite_name(self):
self.session.add(util.mock_user('u1'))
self.session.add(util.mock_user('u2'))
self.session.add(util.mock_user('u3'))
self._test('-name:u1,u3', 1, 100, 1, ['u2'])
def test_filter_by_ranged_name(self):
self._test_raises('name:u1..u2', 1, 100)
def test_paging(self):
self.session.add(util.mock_user('u1'))
self.session.add(util.mock_user('u2'))
self._test('', 1, 1, 2, ['u1'])
self._test('', 2, 1, 2, ['u2'])
self._test('', 3, 1, 2, [])
self._test('', 0, 1, 2, ['u1'])
self._test('', 0, 0, 2, ['u1'])
def test_order_by_name(self):
self.session.add(util.mock_user('u2'))
self.session.add(util.mock_user('u1'))
self._test('', 1, 100, 2, ['u1', 'u2'])
self._test('order:name', 1, 100, 2, ['u1', 'u2'])
self._test('-order:name', 1, 100, 2, ['u2', 'u1'])
self._test('order:name,asc', 1, 100, 2, ['u1', 'u2'])
self._test('order:name,desc', 1, 100, 2, ['u2', 'u1'])
self._test('-order:name,asc', 1, 100, 2, ['u2', 'u1'])
self._test('-order:name,desc', 1, 100, 2, ['u1', 'u2'])
def test_invalid_tokens(self):
for query in [
'order:',
'order:nam',
'order:name,as',
'order:name,asc,desc',
'bad:x',
'special:unsupported']:
self._test_raises(query, 1, 100)
def test_anonymous(self):
self.session.add(util.mock_user('u1'))
self.session.add(util.mock_user('u2'))
self._test('u1', 1, 100, 1, ['u1'])
self._test('u2', 1, 100, 1, ['u2'])
def test_empty_search(self):
self.session.add(util.mock_user('u1'))
self.session.add(util.mock_user('u2'))
self._test('', 1, 100, 2, ['u1', 'u2'])
def test_negated_anonymous(self):
self.session.add(util.mock_user('u1'))
self.session.add(util.mock_user('u2'))
self._test('-u1', 1, 100, 1, ['u2'])
self._test('-u2', 1, 100, 1, ['u1'])
def test_combining(self):
user1 = util.mock_user('u1')
user2 = util.mock_user('u2')
user3 = util.mock_user('u3')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2014, 6, 1)
user3.creation_time = datetime(2015, 1, 1)
self.session.add_all([user1, user2, user3])
self._test('creation-time:2014 u1', 1, 100, 1, ['u1'])
self._test('creation-time:2014 u2', 1, 100, 1, ['u2'])
self._test('creation-time:2016 u2', 1, 100, 0, [])
def test_special(self):
self._test_raises('special:-', 1, 100)
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_error', [
('creation-date:..', errors.SearchError),
('creation-date:bad..', errors.ValidationError),
('creation-date:..bad', errors.ValidationError),
('creation-date:bad..bad', errors.ValidationError),
('name:a..b', errors.SearchError),
('order:', errors.SearchError),
('order:nam', errors.SearchError),
('order:name,as', errors.SearchError),
('order:name,asc,desc', errors.SearchError),
('bad:x', errors.SearchError),
('special:unsupported', errors.SearchError),
])
def test_bad_tokens(executor, session, input, expected_error):
with pytest.raises(expected_error):
executor.execute(session, input, page=1, page_size=100)

View file

@ -1,42 +1,30 @@
import unittest
import pytest
from datetime import datetime
from szurubooru import errors
from szurubooru.util import misc
dt = datetime
class FakeDatetime(datetime):
@staticmethod
def now(tz=None):
return datetime(1997, 1, 2, 3, 4, 5, tzinfo=tz)
class TestParseTime(unittest.TestCase):
def test_empty(self):
self.assertRaises(errors.ValidationError, misc.parse_time_range, '')
def test_parsing_empty_date_time():
with pytest.raises(errors.ValidationError):
misc.parse_time_range('')
def test_today(self):
misc.datetime.datetime = FakeDatetime
date_min, date_max = misc.parse_time_range('today')
self.assertEqual(date_min, datetime(1997, 1, 2, 0, 0, 0))
self.assertEqual(date_max, datetime(1997, 1, 2, 23, 59, 59))
def test_yesterday(self):
misc.datetime.datetime = FakeDatetime
date_min, date_max = misc.parse_time_range('yesterday')
self.assertEqual(date_min, datetime(1997, 1, 1, 0, 0, 0))
self.assertEqual(date_max, datetime(1997, 1, 1, 23, 59, 59))
def test_year(self):
date_min, date_max = misc.parse_time_range('1999')
self.assertEqual(date_min, datetime(1999, 1, 1, 0, 0, 0))
self.assertEqual(date_max, datetime(1999, 12, 31, 23, 59, 59))
def test_month(self):
for text in ['1999-2', '1999-02']:
date_min, date_max = misc.parse_time_range(text)
self.assertEqual(date_min, datetime(1999, 2, 1, 0, 0, 0))
self.assertEqual(date_max, datetime(1999, 2, 28, 23, 59, 59))
def test_day(self):
for text in ['1999-2-6', '1999-02-6', '1999-2-06', '1999-02-06']:
date_min, date_max = misc.parse_time_range(text)
self.assertEqual(date_min, datetime(1999, 2, 6, 0, 0, 0))
self.assertEqual(date_max, datetime(1999, 2, 6, 23, 59, 59))
@pytest.mark.parametrize('input,output', [
('today', (dt(1997, 1, 2, 0, 0, 0), dt(1997, 1, 2, 23, 59, 59))),
('yesterday', (dt(1997, 1, 1, 0, 0, 0), dt(1997, 1, 1, 23, 59, 59))),
('1999', (dt(1999, 1, 1, 0, 0, 0), dt(1999, 12, 31, 23, 59, 59))),
('1999-2', (dt(1999, 2, 1, 0, 0, 0), dt(1999, 2, 28, 23, 59, 59))),
('1999-02', (dt(1999, 2, 1, 0, 0, 0), dt(1999, 2, 28, 23, 59, 59))),
('1999-2-6', (dt(1999, 2, 6, 0, 0, 0), dt(1999, 2, 6, 23, 59, 59))),
('1999-02-6', (dt(1999, 2, 6, 0, 0, 0), dt(1999, 2, 6, 23, 59, 59))),
('1999-2-06', (dt(1999, 2, 6, 0, 0, 0), dt(1999, 2, 6, 23, 59, 59))),
('1999-02-06', (dt(1999, 2, 6, 0, 0, 0), dt(1999, 2, 6, 23, 59, 59))),
])
def test_parsing_date_time(input, output):
misc.datetime.datetime = FakeDatetime
assert misc.parse_time_range(input) == output

7
server/test Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env python3
import pytest
import sys
pytest.main(' '.join([
'--cov-report=term-missing',
'--cov=szurubooru',
'szurubooru'] + sys.argv[1:]))