From 5497ef4b0b6416a49716a2908ba73c5d524f64c1 Mon Sep 17 00:00:00 2001 From: Nikolai Date: Mon, 7 Jun 2021 16:29:16 -0700 Subject: [PATCH 1/2] membership.create() checks for joinable and player limit; factory creates joinable lexicons by default --- amanuensis/backend/membership.py | 22 ++++++++++++++++++++++ tests/conftest.py | 4 +++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/amanuensis/backend/membership.py b/amanuensis/backend/membership.py index 7440353..3161a89 100644 --- a/amanuensis/backend/membership.py +++ b/amanuensis/backend/membership.py @@ -5,6 +5,7 @@ Membership query interface from sqlalchemy import select, func from amanuensis.db import DbContext, Membership +from amanuensis.db.models import Lexicon from amanuensis.errors import ArgumentError @@ -36,6 +37,27 @@ def create( ): raise ArgumentError("User is already a member of lexicon") + # get reference to lexicon for next few checks + lex: Lexicon = db( + select(Lexicon) + .where(Lexicon.id == lexicon_id) + ).scalar_one_or_none() + + # Verify lexicon is joinable; current no Lexicons are joinable so this is commented out + if not lex.joinable: + raise ArgumentError("Can't join: Lexicon is not joinable") + + # Verify lexicon is not full + if lex.player_limit: + if ( + db( + select(func.count()) + .where(Membership.lexicon_id == lexicon_id) + ).scalar() + >= lex.player_limit + ): + raise ArgumentError("Can't join: Lexicon is full") + new_membership = Membership( user_id=user_id, lexicon_id=lexicon_id, diff --git a/tests/conftest.py b/tests/conftest.py index a93b93c..0cd436f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -49,7 +49,9 @@ def make_lexicon(db: DbContext): } state["nonce"] += 1 updated_kwargs = {**default_kwargs, **kwargs} - return lexiq.create(db, **updated_kwargs) + lex = lexiq.create(db, **updated_kwargs) + lex.joinable = True + return lex return lexicon_factory -- 2.44.1 From 06ec2e168e9fc21cc2879e4cac6e4a1290255064 Mon Sep 17 00:00:00 2001 From: Nikolai Date: Wed, 9 Jun 2021 21:40:34 -0700 Subject: [PATCH 2/2] membership unit test checks joinability and player limit; post.create() checks allow_post --- amanuensis/backend/membership.py | 16 +++++++--------- amanuensis/backend/post.py | 11 ++++++++++- tests/conftest.py | 1 + tests/test_membership.py | 23 ++++++++++++++++++++++- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/amanuensis/backend/membership.py b/amanuensis/backend/membership.py index 3161a89..5e9af13 100644 --- a/amanuensis/backend/membership.py +++ b/amanuensis/backend/membership.py @@ -39,22 +39,20 @@ def create( # get reference to lexicon for next few checks lex: Lexicon = db( - select(Lexicon) - .where(Lexicon.id == lexicon_id) + select(Lexicon).where(Lexicon.id == lexicon_id) ).scalar_one_or_none() + if not lex: + raise ArgumentError("could not find lexicon") - # Verify lexicon is joinable; current no Lexicons are joinable so this is commented out + # Verify lexicon is joinable if not lex.joinable: raise ArgumentError("Can't join: Lexicon is not joinable") # Verify lexicon is not full - if lex.player_limit: + if lex.player_limit is not None: if ( - db( - select(func.count()) - .where(Membership.lexicon_id == lexicon_id) - ).scalar() - >= lex.player_limit + db(select(func.count()).where(Membership.lexicon_id == lexicon_id)).scalar() + >= lex.player_limit ): raise ArgumentError("Can't join: Lexicon is full") diff --git a/amanuensis/backend/post.py b/amanuensis/backend/post.py index 3544b90..0a6373f 100644 --- a/amanuensis/backend/post.py +++ b/amanuensis/backend/post.py @@ -4,9 +4,10 @@ Post query interface import re -from sqlalchemy import select, func +from sqlalchemy import select from amanuensis.db import DbContext, Post +from amanuensis.db.models import Lexicon from amanuensis.errors import ArgumentError @@ -34,6 +35,14 @@ def create( if not body.strip(): raise ArgumentError("Post body cannot be empty.") + # Check that the lexicon allows posting + if not ( + db(select(Lexicon).where(Lexicon.id == lexicon_id)) + .scalar_one_or_none() + .allow_post + ): + raise ArgumentError("Lexicon does not allow posting.") + new_post = Post(lexicon_id=lexicon_id, user_id=user_id, body=body) db.session.add(new_post) db.session.commit() diff --git a/tests/conftest.py b/tests/conftest.py index 0cd436f..5bd0b03 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -51,6 +51,7 @@ def make_lexicon(db: DbContext): updated_kwargs = {**default_kwargs, **kwargs} lex = lexiq.create(db, **updated_kwargs) lex.joinable = True + db.session.commit() return lex return lexicon_factory diff --git a/tests/test_membership.py b/tests/test_membership.py index 45e70a1..d6a0637 100644 --- a/tests/test_membership.py +++ b/tests/test_membership.py @@ -15,7 +15,15 @@ def test_create_membership(db: DbContext, make): new_lexicon: Lexicon = make.lexicon() assert new_lexicon.id, "Failed to create lexicon" - # Add the user to the lexicon as an editor + # Joining doesn't work when joinable is false + new_lexicon.joinable = False + db.session.commit() + with pytest.raises(ArgumentError): + memq.create(db, new_user.id, new_lexicon.id, True) + + # Joining works when joinable is true + new_lexicon.joinable = True + db.session.commit() mem: Membership = memq.create(db, new_user.id, new_lexicon.id, True) assert mem, "Failed to create membership" @@ -38,3 +46,16 @@ def test_create_membership(db: DbContext, make): # Check that joining twice is not allowed with pytest.raises(ArgumentError): memq.create(db, new_user.id, new_lexicon.id, False) + + # Check that joining full lexicon not allowed + new_lexicon.player_limit = 1 + db.session.commit() + two_user: User = make.user() + + with pytest.raises(ArgumentError): + memq.create(db, two_user.id, new_lexicon.id, False) + + new_lexicon.player_limit = 2 + db.session.commit() + mem2: Membership = memq.create(db, two_user.id, new_lexicon.id, False) + assert mem2, "Failed to join lexicon with open player slots" -- 2.44.1