Coverage for app/backend/src/tests/test_visible_users.py: 100%
80 statements
« prev ^ index » next coverage.py v7.14.2, created at 2026-06-21 09:29 +0000
« prev ^ index » next coverage.py v7.14.2, created at 2026-06-21 09:29 +0000
1from typing import cast
3from sqlalchemy import select, update
4from sqlalchemy.sql import func
6from couchers.context import CouchersContext
7from couchers.db import session_scope
8from couchers.models import FriendRelationship, User
9from couchers.sql import users_visible, where_users_column_visible
10from tests.fixtures.db import generate_user, make_friends, make_user_block, make_user_invisible
13class _FakeContext:
14 def __init__(self, user_id):
15 self.user_id = user_id
17 def is_logged_in(self):
18 return self.user_id is not None and self.user_id != 0
21# Also tests different ways to make users invisible
22def test_is_visible_property(db):
23 user1, token1 = generate_user()
24 user2, token2 = generate_user()
25 user3, token3 = generate_user()
26 user4, token4 = generate_user()
27 user5, token5 = generate_user(delete_user=True)
29 with session_scope() as session:
30 session.execute(update(User).where(User.id == user2.id).values(banned_at=func.now()))
31 session.execute(update(User).where(User.id == user3.id).values(deleted_at=func.now()))
32 session.execute(update(User).where(User.id == user4.id).values(banned_at=func.now()))
34 visible_users = session.execute(select(User.id).where(User.is_visible)).scalars().all()
36 assert visible_users[0] == user1.id
39def test_select_dot_where_users_visible(db):
40 user1, token1 = generate_user()
41 user2, token2 = generate_user(delete_user=True)
42 user3, token3 = generate_user()
43 user4, token4 = generate_user()
45 make_user_block(user1, user3)
46 make_user_block(user4, user1)
48 context = cast(CouchersContext, _FakeContext(user1.id))
49 with session_scope() as session:
50 assert session.execute(select(func.count()).select_from(User).where(users_visible(context))).scalar_one() == 1
53def test_select_dot_where_users_column_visible(db):
54 user1, token1 = generate_user()
55 user2, token2 = generate_user()
56 user3, token3 = generate_user()
57 user4, token4 = generate_user()
58 user5, token5 = generate_user()
60 make_friends(user1, user2)
61 make_friends(user1, user3)
62 make_friends(user1, user4)
63 make_friends(user1, user5)
65 make_user_invisible(user3.id)
66 make_user_block(user1, user4)
67 make_user_block(user5, user1)
69 context = cast(CouchersContext, _FakeContext(user1.id))
70 with session_scope() as session:
71 assert (
72 session.execute(
73 where_users_column_visible(
74 select(func.count()).select_from(FriendRelationship), context, FriendRelationship.to_user_id
75 )
76 ).scalar_one()
77 == 1
78 )
81def test_shadowed_user_hidden_from_others_visible_to_self(db):
82 user1, _ = generate_user()
83 user2, _ = generate_user()
85 with session_scope() as session:
86 session.execute(update(User).where(User.id == user2.id).values(shadowed_at=func.now()))
88 other_context = cast(CouchersContext, _FakeContext(user1.id))
89 self_context = cast(CouchersContext, _FakeContext(user2.id))
90 anon_context = cast(CouchersContext, _FakeContext(None))
92 with session_scope() as session:
93 # user1 (other) does not see shadowed user2
94 visible_to_other = (
95 session.execute(select(User.id).where(users_visible(other_context)).where(User.id == user2.id))
96 .scalars()
97 .all()
98 )
99 assert visible_to_other == []
101 # user2 (self) sees themselves
102 visible_to_self = (
103 session.execute(select(User.id).where(users_visible(self_context)).where(User.id == user2.id))
104 .scalars()
105 .all()
106 )
107 assert visible_to_self == [user2.id]
109 # anonymous viewer does not see shadowed user2
110 visible_to_anon = (
111 session.execute(select(User.id).where(users_visible(anon_context)).where(User.id == user2.id))
112 .scalars()
113 .all()
114 )
115 assert visible_to_anon == []
118def test_shadowed_user_column_visible_with_self_exception(db):
119 user1, _ = generate_user()
120 user2, _ = generate_user()
121 make_friends(user1, user2)
123 with session_scope() as session:
124 session.execute(update(User).where(User.id == user2.id).values(shadowed_at=func.now()))
126 # user1 (other): friendship to shadowed user2 is filtered out
127 context_other = cast(CouchersContext, _FakeContext(user1.id))
128 with session_scope() as session:
129 count = session.execute(
130 where_users_column_visible(
131 select(func.count()).select_from(FriendRelationship), context_other, FriendRelationship.to_user_id
132 )
133 ).scalar_one()
134 assert count == 0
136 # user2 (self): can see the friendship pointing at themselves
137 context_self = cast(CouchersContext, _FakeContext(user2.id))
138 with session_scope() as session:
139 count = session.execute(
140 where_users_column_visible(
141 select(func.count()).select_from(FriendRelationship), context_self, FriendRelationship.to_user_id
142 )
143 ).scalar_one()
144 assert count == 1