Coverage for app / backend / src / tests / test_discussions.py: 100%

119 statements  

« prev     ^ index     » next       coverage.py v7.13.2, created at 2026-02-03 06:18 +0000

1import grpc 

2import pytest 

3 

4from couchers.db import session_scope 

5from couchers.proto import discussions_pb2, notifications_pb2, threads_pb2 

6from couchers.utils import now, to_aware_datetime 

7from tests.fixtures.db import generate_user 

8from tests.fixtures.misc import PushCollector, process_jobs 

9from tests.fixtures.sessions import discussions_session, notifications_session, threads_session 

10from tests.test_communities import create_community, create_group 

11 

12 

13@pytest.fixture(autouse=True) 

14def _(testconfig): 

15 pass 

16 

17 

18def test_create_discussion_errors(db): 

19 user, token = generate_user() 

20 with discussions_session(token) as api: 

21 with pytest.raises(grpc.RpcError) as e: 

22 api.CreateDiscussion( 

23 discussions_pb2.CreateDiscussionReq( 

24 title=None, 

25 content="dummy content", 

26 ) 

27 ) 

28 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

29 assert e.value.details() == "Missing discussion title." 

30 

31 with discussions_session(token) as api: 

32 with pytest.raises(grpc.RpcError) as e: 

33 api.CreateDiscussion( 

34 discussions_pb2.CreateDiscussionReq( 

35 title="dummy title", 

36 content=None, 

37 ) 

38 ) 

39 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

40 assert e.value.details() == "Missing discussion content." 

41 

42 

43def test_create_and_get_discussion(db, push_collector: PushCollector): 

44 generate_user() 

45 user, token = generate_user() 

46 user2, token2 = generate_user() 

47 generate_user() 

48 generate_user() 

49 

50 with notifications_session(token2) as notifications: 

51 notifications.SetNotificationSettings( 

52 notifications_pb2.SetNotificationSettingsReq( 

53 preferences=[ 

54 notifications_pb2.SingleNotificationPreference( 

55 topic="discussion", 

56 action="create", 

57 delivery_method="push", 

58 enabled=True, 

59 ) 

60 ], 

61 ) 

62 ) 

63 

64 with session_scope() as session: 

65 community = create_community(session, 0, 1, "Testing Community", [user2], [], None) 

66 group_id = create_group(session, "Testing Group", [user2], [], community).id 

67 community_id = community.id 

68 user2_id = user2.id 

69 

70 with discussions_session(token) as api: 

71 time_before_create = now() 

72 res = api.CreateDiscussion( 

73 discussions_pb2.CreateDiscussionReq( 

74 title="dummy title", 

75 content="dummy content", 

76 owner_community_id=community_id, 

77 ) 

78 ) 

79 time_after_create = now() 

80 

81 assert res.title == "dummy title" 

82 assert res.content == "dummy content" 

83 assert res.slug == "dummy-title" 

84 assert time_before_create <= to_aware_datetime(res.created) <= time_after_create 

85 assert res.creator_user_id == user.id 

86 assert res.owner_community_id == community_id 

87 

88 discussion_id = res.discussion_id 

89 

90 process_jobs() 

91 

92 push = push_collector.pop_for_user(user2_id, last=True) 

93 assert push.content.title == "New discussion: dummy title" 

94 assert push.content.body == f"{user.name} started the discussion in Testing Community." 

95 

96 with discussions_session(token) as api: 

97 res = api.GetDiscussion( 

98 discussions_pb2.GetDiscussionReq( 

99 discussion_id=discussion_id, 

100 ) 

101 ) 

102 

103 assert res.title == "dummy title" 

104 assert res.content == "dummy content" 

105 assert res.slug == "dummy-title" 

106 assert time_before_create <= to_aware_datetime(res.created) <= time_after_create 

107 assert res.creator_user_id == user.id 

108 assert res.owner_community_id == community_id 

109 

110 with discussions_session(token) as api: 

111 time_before_create = now() 

112 res = api.CreateDiscussion( 

113 discussions_pb2.CreateDiscussionReq( 

114 title="dummy title", 

115 content="dummy content", 

116 owner_group_id=group_id, 

117 ) 

118 ) 

119 time_after_create = now() 

120 

121 assert res.title == "dummy title" 

122 assert res.content == "dummy content" 

123 assert res.slug == "dummy-title" 

124 assert time_before_create <= to_aware_datetime(res.created) <= time_after_create 

125 assert res.creator_user_id == user.id 

126 assert res.owner_group_id == group_id 

127 

128 discussion_id = res.discussion_id 

129 

130 with discussions_session(token) as api: 

131 res = api.GetDiscussion( 

132 discussions_pb2.GetDiscussionReq( 

133 discussion_id=discussion_id, 

134 ) 

135 ) 

136 

137 assert res.title == "dummy title" 

138 assert res.content == "dummy content" 

139 assert res.slug == "dummy-title" 

140 assert time_before_create <= to_aware_datetime(res.created) <= time_after_create 

141 assert res.creator_user_id == user.id 

142 assert res.owner_group_id == group_id 

143 

144 

145def test_discussion_notifications_regression(db, push_collector: PushCollector): 

146 generate_user() 

147 user, token = generate_user() 

148 user2, token2 = generate_user() 

149 user3, token3 = generate_user() 

150 generate_user() 

151 generate_user() 

152 

153 with session_scope() as session: 

154 community = create_community(session, 0, 1, "Testing Community", [user2], [], None) 

155 group_id = create_group(session, "Testing Group", [user2], [], community).id 

156 community_id = community.id 

157 user2_id = user2.id 

158 

159 with discussions_session(token) as api: 

160 time_before_create = now() 

161 res = api.CreateDiscussion( 

162 discussions_pb2.CreateDiscussionReq( 

163 title="dummy title", 

164 content="dummy content", 

165 owner_community_id=community_id, 

166 ) 

167 ) 

168 time_after_create = now() 

169 

170 assert res.title == "dummy title" 

171 assert res.content == "dummy content" 

172 assert res.slug == "dummy-title" 

173 assert time_before_create <= to_aware_datetime(res.created) <= time_after_create 

174 assert res.creator_user_id == user.id 

175 assert res.owner_community_id == community_id 

176 

177 discussion_id = res.discussion_id 

178 thread_id = res.thread.thread_id 

179 

180 with threads_session(token2) as api: 

181 comment_thread_id = api.PostReply(threads_pb2.PostReplyReq(thread_id=thread_id, content="comment")).thread_id 

182 

183 with threads_session(token3) as api: 

184 api.PostReply(threads_pb2.PostReplyReq(thread_id=comment_thread_id, content="reply to comment")) 

185 

186 with threads_session(token) as api: 

187 api.PostReply(threads_pb2.PostReplyReq(thread_id=comment_thread_id, content="reply to reply to comment")) 

188 

189 process_jobs() 

190 

191 # User2 should get 2 notifications about 2 replies to their comment, User3 should get 1 notification about 1 reply 

192 push = push_collector.pop_for_user(user2_id, last=False) 

193 assert push.content.title == f"{user3.name} • dummy title" 

194 assert push.topic_action == "thread:reply" 

195 

196 push = push_collector.pop_for_user(user2_id, last=True) 

197 assert push.content.title == f"{user.name} • dummy title" 

198 assert push.topic_action == "thread:reply" 

199 

200 push = push_collector.pop_for_user(user3.id, last=True) 

201 assert push.content.title == f"{user.name} • dummy title" 

202 assert push.topic_action == "thread:reply"