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

110 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-12-06 23:17 +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.test_communities import create_community, create_group 

8from tests.test_fixtures import ( # noqa 

9 db, 

10 discussions_session, 

11 generate_user, 

12 notifications_session, 

13 process_jobs, 

14 push_collector, 

15 testconfig, 

16 threads_session, 

17) 

18 

19 

20@pytest.fixture(autouse=True) 

21def _(testconfig): 

22 pass 

23 

24 

25def test_create_discussion_errors(db): 

26 user, token = generate_user() 

27 with discussions_session(token) as api: 

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

29 api.CreateDiscussion( 

30 discussions_pb2.CreateDiscussionReq( 

31 title=None, 

32 content="dummy content", 

33 ) 

34 ) 

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

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

37 

38 with discussions_session(token) as api: 

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

40 api.CreateDiscussion( 

41 discussions_pb2.CreateDiscussionReq( 

42 title="dummy title", 

43 content=None, 

44 ) 

45 ) 

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

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

48 

49 

50def test_create_and_get_discussion(db, push_collector): 

51 generate_user() 

52 user, token = generate_user() 

53 user2, token2 = generate_user() 

54 generate_user() 

55 generate_user() 

56 

57 with notifications_session(token2) as notifications: 

58 notifications.SetNotificationSettings( 

59 notifications_pb2.SetNotificationSettingsReq( 

60 preferences=[ 

61 notifications_pb2.SingleNotificationPreference( 

62 topic="discussion", 

63 action="create", 

64 delivery_method="push", 

65 enabled=True, 

66 ) 

67 ], 

68 ) 

69 ) 

70 

71 with session_scope() as session: 

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

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

74 community_id = community.id 

75 user2_id = user2.id 

76 

77 with discussions_session(token) as api: 

78 time_before_create = now() 

79 res = api.CreateDiscussion( 

80 discussions_pb2.CreateDiscussionReq( 

81 title="dummy title", 

82 content="dummy content", 

83 owner_community_id=community_id, 

84 ) 

85 ) 

86 time_after_create = now() 

87 

88 assert res.title == "dummy title" 

89 assert res.content == "dummy content" 

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

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

92 assert res.creator_user_id == user.id 

93 assert res.owner_community_id == community_id 

94 

95 discussion_id = res.discussion_id 

96 

97 process_jobs() 

98 

99 push_collector.assert_user_has_single_matching( 

100 user2_id, 

101 title="dummy title", 

102 body=f"{user.name} created a discussion in Testing Community: dummy title\n\ndummy content", 

103 ) 

104 

105 with discussions_session(token) as api: 

106 res = api.GetDiscussion( 

107 discussions_pb2.GetDiscussionReq( 

108 discussion_id=discussion_id, 

109 ) 

110 ) 

111 

112 assert res.title == "dummy title" 

113 assert res.content == "dummy content" 

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

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

116 assert res.creator_user_id == user.id 

117 assert res.owner_community_id == community_id 

118 

119 with discussions_session(token) as api: 

120 time_before_create = now() 

121 res = api.CreateDiscussion( 

122 discussions_pb2.CreateDiscussionReq( 

123 title="dummy title", 

124 content="dummy content", 

125 owner_group_id=group_id, 

126 ) 

127 ) 

128 time_after_create = now() 

129 

130 assert res.title == "dummy title" 

131 assert res.content == "dummy content" 

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

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

134 assert res.creator_user_id == user.id 

135 assert res.owner_group_id == group_id 

136 

137 discussion_id = res.discussion_id 

138 

139 with discussions_session(token) as api: 

140 res = api.GetDiscussion( 

141 discussions_pb2.GetDiscussionReq( 

142 discussion_id=discussion_id, 

143 ) 

144 ) 

145 

146 assert res.title == "dummy title" 

147 assert res.content == "dummy content" 

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

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

150 assert res.creator_user_id == user.id 

151 assert res.owner_group_id == group_id 

152 

153 

154def test_discussion_notifications_regression(db, push_collector): 

155 generate_user() 

156 user, token = generate_user() 

157 user2, token2 = generate_user() 

158 user3, token3 = generate_user() 

159 generate_user() 

160 generate_user() 

161 

162 with session_scope() as session: 

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

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

165 community_id = community.id 

166 user2_id = user2.id 

167 

168 with discussions_session(token) as api: 

169 time_before_create = now() 

170 res = api.CreateDiscussion( 

171 discussions_pb2.CreateDiscussionReq( 

172 title="dummy title", 

173 content="dummy content", 

174 owner_community_id=community_id, 

175 ) 

176 ) 

177 time_after_create = now() 

178 

179 assert res.title == "dummy title" 

180 assert res.content == "dummy content" 

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

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

183 assert res.creator_user_id == user.id 

184 assert res.owner_community_id == community_id 

185 

186 discussion_id = res.discussion_id 

187 thread_id = res.thread.thread_id 

188 

189 with threads_session(token2) as api: 

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

191 

192 with threads_session(token3) as api: 

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

194 

195 with threads_session(token) as api: 

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

197 

198 process_jobs() 

199 

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

201 push_collector.assert_user_has_count(user2_id, 2) 

202 for i in range(2): 

203 push_collector.assert_user_push_matches_fields( 

204 user2_id, 

205 ix=i, 

206 title="dummy title", 

207 topic_action="thread:reply", 

208 ) 

209 push_collector.assert_user_has_single_matching( 

210 user3.id, 

211 title="dummy title", 

212 topic_action="thread:reply", 

213 )