Compare commits
3 Commits
f788e11077
...
243df40ac7
Author | SHA1 | Date |
---|---|---|
Tim Van Baak | 243df40ac7 | |
Tim Van Baak | 1df96107a1 | |
Tim Van Baak | 1268b53d2a |
|
@ -1,8 +1,10 @@
|
||||||
"""
|
"""
|
||||||
Membership query interface
|
Character query interface
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from amanuensis.db import DbContext, Character
|
from sqlalchemy import select, func
|
||||||
|
|
||||||
|
from amanuensis.db import *
|
||||||
from amanuensis.errors import ArgumentError
|
from amanuensis.errors import ArgumentError
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,19 +17,41 @@ def create(
|
||||||
"""
|
"""
|
||||||
Create a new character for a user.
|
Create a new character for a user.
|
||||||
"""
|
"""
|
||||||
# Quick argument verification
|
# Verify argument types are correct
|
||||||
if not isinstance(lexicon_id, int):
|
if not isinstance(lexicon_id, int):
|
||||||
raise ArgumentError('lexicon_id')
|
raise ArgumentError('lexicon_id')
|
||||||
if not isinstance(user_id, int):
|
if not isinstance(user_id, int):
|
||||||
raise ArgumentError('user_id')
|
raise ArgumentError('user_id')
|
||||||
|
|
||||||
# Verify character information
|
|
||||||
if not isinstance(name, str):
|
if not isinstance(name, str):
|
||||||
raise ArgumentError('Character name must be a string')
|
raise ArgumentError('name')
|
||||||
|
if signature is not None and not isinstance(signature, str):
|
||||||
|
raise ArgumentError('signature')
|
||||||
|
|
||||||
|
# Verify character name is valid
|
||||||
if not name.strip():
|
if not name.strip():
|
||||||
raise ArgumentError('Character name cannot be blank')
|
raise ArgumentError('Character name cannot be blank')
|
||||||
if signature is not None and not isinstance(signature, str):
|
|
||||||
raise ArgumentError('Signature must be a string')
|
# If no signature is provided, use a default signature
|
||||||
|
if not signature or not signature.strip():
|
||||||
|
signature = f'~{name}'
|
||||||
|
|
||||||
|
# Check that the user is a member of this lexicon
|
||||||
|
mem: Membership = db(
|
||||||
|
select(Membership)
|
||||||
|
.where(Membership.user_id == user_id)
|
||||||
|
.where(Membership.lexicon_id == lexicon_id)
|
||||||
|
).scalar_one_or_none()
|
||||||
|
if not mem:
|
||||||
|
raise ArgumentError('User is not a member of lexicon')
|
||||||
|
|
||||||
|
# Check that this user is below the limit for creating characters
|
||||||
|
num_user_chars = db(
|
||||||
|
select(func.count(Character.id))
|
||||||
|
.where(Character.lexicon_id == lexicon_id)
|
||||||
|
.where(Character.user_id == user_id)
|
||||||
|
).scalar()
|
||||||
|
if mem.lexicon.character_limit is not None and num_user_chars >= mem.lexicon.character_limit:
|
||||||
|
raise ArgumentError('User is at character limit')
|
||||||
|
|
||||||
new_character = Character(
|
new_character = Character(
|
||||||
lexicon_id=lexicon_id,
|
lexicon_id=lexicon_id,
|
||||||
|
|
|
@ -14,6 +14,9 @@ SQLAlchemy = "^1.4.12"
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
pytest = "^5.2"
|
pytest = "^5.2"
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
addopts = "--show-capture=log"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
[pytest]
|
||||||
|
addopts = --show-capture=log
|
||||||
|
; pytest should be able to read the pyproject.toml file, but for some reason it
|
||||||
|
; doesn't seem to be working here. This file is a temporary fix until that gets
|
||||||
|
; resolved.
|
|
@ -12,7 +12,7 @@ import amanuensis.backend.user as userq
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def db():
|
def db():
|
||||||
"""Provides an initialized database in memory."""
|
"""Provides an initialized database in memory."""
|
||||||
db = DbContext('sqlite:///:memory:', debug=True)
|
db = DbContext('sqlite:///:memory:', debug=False)
|
||||||
db.create_all()
|
db.create_all()
|
||||||
return db
|
return db
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,73 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
from amanuensis.db import *
|
from amanuensis.db import *
|
||||||
import amanuensis.backend.lexicon as lexiq
|
import amanuensis.backend.character as charq
|
||||||
import amanuensis.backend.membership as memq
|
from amanuensis.errors import ArgumentError
|
||||||
import amanuensis.backend.user as userq
|
|
||||||
|
|
||||||
from .test_db import db
|
|
||||||
|
|
||||||
|
|
||||||
def test_create_character(db: DbContext):
|
def test_create_character(db: DbContext, lexicon_with_editor, make_user):
|
||||||
"""Test creating a character."""
|
"""Test creating a character."""
|
||||||
# Set up a user and lexicon
|
lexicon, user = lexicon_with_editor
|
||||||
new_user = userq.create(db, 'username', 'password', 'user', 'a@b.c', False)
|
kwargs = {
|
||||||
assert new_user.id, 'Failed to create user'
|
'db': db,
|
||||||
new_lexicon = lexiq.create(db, 'Test', None, 'prompt')
|
'user_id': user.id,
|
||||||
assert new_lexicon.id, 'Failed to create lexicon'
|
'lexicon_id': lexicon.id,
|
||||||
mem = memq.create(db, new_user.id, new_lexicon.id, True)
|
'name': 'Character Name',
|
||||||
assert mem, 'Failed to create membership'
|
'signature': 'Signature',
|
||||||
|
}
|
||||||
|
|
||||||
#
|
# Bad argument types
|
||||||
|
with pytest.raises(ArgumentError):
|
||||||
|
charq.create(**{**kwargs, 'name': b'bytestring'})
|
||||||
|
with pytest.raises(ArgumentError):
|
||||||
|
charq.create(**{**kwargs, 'name': None})
|
||||||
|
with pytest.raises(ArgumentError):
|
||||||
|
charq.create(**{**kwargs, 'signature': b'bytestring'})
|
||||||
|
|
||||||
|
# Bad character name
|
||||||
|
with pytest.raises(ArgumentError):
|
||||||
|
charq.create(**{**kwargs, 'name': ' '})
|
||||||
|
|
||||||
|
# Signature is auto-populated
|
||||||
|
char = charq.create(**{**kwargs, 'signature': None})
|
||||||
|
assert char.signature is not None
|
||||||
|
|
||||||
|
# User must be in lexicon
|
||||||
|
new_user = make_user()
|
||||||
|
with pytest.raises(ArgumentError):
|
||||||
|
charq.create(**{**kwargs, 'user_id': new_user.id})
|
||||||
|
|
||||||
|
|
||||||
|
def test_character_limits(db: DbContext, lexicon_with_editor):
|
||||||
|
"""Test lexicon settings limiting character creation."""
|
||||||
|
lexicon: Lexicon
|
||||||
|
user: User
|
||||||
|
lexicon, user = lexicon_with_editor
|
||||||
|
|
||||||
|
# Set character limit to one and create a character
|
||||||
|
lexicon.character_limit = 1
|
||||||
|
db.session.commit()
|
||||||
|
char1 = charq.create(db, lexicon.id, user.id, 'Test Character 1', signature=None)
|
||||||
|
assert char1.id, 'Failed to create character 1'
|
||||||
|
|
||||||
|
# Creating a second character should fail
|
||||||
|
with pytest.raises(ArgumentError):
|
||||||
|
char2 = charq.create(db, lexicon.id, user.id, 'Test Character 2', signature=None)
|
||||||
|
assert char2
|
||||||
|
|
||||||
|
# Raising the limit to 2 should allow a second character
|
||||||
|
lexicon.character_limit = 2
|
||||||
|
db.session.commit()
|
||||||
|
char2 = charq.create(db, lexicon.id, user.id, 'Test Character 2', signature=None)
|
||||||
|
assert char2.id, 'Failed to create character 2'
|
||||||
|
|
||||||
|
# Creating a third character should fail
|
||||||
|
with pytest.raises(ArgumentError):
|
||||||
|
char3 = charq.create(db, lexicon.id, user.id, 'Test Character 3', signature=None)
|
||||||
|
assert char3
|
||||||
|
|
||||||
|
# Setting the limit to null should allow a third character
|
||||||
|
lexicon.character_limit = None
|
||||||
|
db.session.commit()
|
||||||
|
char2 = charq.create(db, lexicon.id, user.id, 'Test Character 3', signature=None)
|
||||||
|
assert char2.id, 'Failed to create character 3'
|
||||||
|
|
Loading…
Reference in New Issue