1+ from djangocms_moderation import constants
12from djangocms_moderation .models import ModerationCollection
23
34from .utils .base import BaseTestCase
@@ -12,3 +13,206 @@ def test_reviewers_wont_execute_too_many_queries(self):
1213 colls = ModerationCollection .objects .all ().prefetch_reviewers ()
1314 for collection in colls :
1415 ModerationCollection .objects .reviewers (collection )
16+
17+ def test_reviewers_returns_users_from_actions (self ):
18+ """Test that reviewers method returns users assigned to actions"""
19+ # collection1 has moderation_request1 with action assigned to user2
20+ reviewers = ModerationCollection .objects .reviewers (self .collection1 )
21+
22+ self .assertIn (self .user2 , reviewers )
23+ self .assertEqual (len (reviewers ), 1 )
24+
25+ def test_reviewers_returns_multiple_users_from_actions (self ):
26+ """Test that reviewers method returns all users from multiple actions"""
27+ # collection2 has moderation_request2 with multiple actions to user2
28+ reviewers = ModerationCollection .objects .reviewers (self .collection2 )
29+
30+ self .assertIn (self .user2 , reviewers )
31+ self .assertEqual (len (reviewers ), 1 )
32+
33+ def test_reviewers_returns_unique_users (self ):
34+ """Test that reviewers method returns unique users even if assigned multiple times"""
35+ # Add another action with the same user to collection1
36+ self .moderation_request1 .actions .create (
37+ to_user = self .user2 ,
38+ by_user = self .user ,
39+ action = constants .ACTION_APPROVED ,
40+ step_approved = self .wf1st1 ,
41+ )
42+
43+ reviewers = ModerationCollection .objects .reviewers (self .collection1 )
44+
45+ # Should still be just one user (unique)
46+ self .assertEqual (len (reviewers ), 1 )
47+ self .assertIn (self .user2 , reviewers )
48+
49+ def test_reviewers_falls_back_to_first_step_role_when_no_actions_with_users (self ):
50+ """Test that reviewers falls back to first step role users when actions have no to_user"""
51+ # Create a new collection with no actions or actions without to_user
52+ collection = ModerationCollection .objects .create (
53+ author = self .user ,
54+ name = "Collection No Actions" ,
55+ workflow = self .wf1 ,
56+ status = constants .IN_REVIEW # Not COLLECTING
57+ )
58+
59+ # Create a moderation request without actions with to_user
60+ from djangocms_versioning .test_utils .factories import PageVersionFactory
61+ version = PageVersionFactory ()
62+ mr = collection .moderation_requests .create (
63+ version = version ,
64+ language = "en" ,
65+ author = self .user ,
66+ is_active = True ,
67+ )
68+
69+ # Create action without to_user
70+ mr .actions .create (
71+ by_user = self .user ,
72+ action = constants .ACTION_STARTED ,
73+ to_user = None , # No specific user assigned
74+ )
75+
76+ reviewers = ModerationCollection .objects .reviewers (collection )
77+
78+ # Should include user from first step's role (role1 -> user)
79+ self .assertIn (self .user , reviewers )
80+
81+ def test_reviewers_does_not_fall_back_when_status_is_collecting (self ):
82+ """Test that reviewers does not fall back to role users when status is COLLECTING"""
83+ # Create collection with COLLECTING status
84+ collection = ModerationCollection .objects .create (
85+ author = self .user ,
86+ name = "Collection Collecting" ,
87+ workflow = self .wf1 ,
88+ status = constants .COLLECTING
89+ )
90+
91+ from djangocms_versioning .test_utils .factories import PageVersionFactory
92+ version = PageVersionFactory ()
93+ mr = collection .moderation_requests .create (
94+ version = version ,
95+ language = "en" ,
96+ author = self .user ,
97+ is_active = True ,
98+ )
99+
100+ # Create action without to_user
101+ mr .actions .create (
102+ by_user = self .user ,
103+ action = constants .ACTION_STARTED ,
104+ to_user = None ,
105+ )
106+
107+ reviewers = ModerationCollection .objects .reviewers (collection )
108+
109+ # Should be empty since status is COLLECTING and no actions have to_user
110+ self .assertEqual (len (reviewers ), 0 )
111+
112+ def test_reviewers_includes_group_users_from_first_step (self ):
113+ """Test that reviewers includes all users from a group role in first step"""
114+ # Create collection with workflow that has group role as first step
115+ collection = ModerationCollection .objects .create (
116+ author = self .user ,
117+ name = "Collection Group Role" ,
118+ workflow = self .wf2 , # wf2st1 has role1 (user), wf2st2 has role3 (group)
119+ status = constants .IN_REVIEW
120+ )
121+
122+ # Change first step to use group role
123+ self .wf2st1 .delete ()
124+
125+ from djangocms_versioning .test_utils .factories import PageVersionFactory
126+ version = PageVersionFactory ()
127+ mr = collection .moderation_requests .create (
128+ version = version ,
129+ language = "en" ,
130+ author = self .user ,
131+ is_active = True ,
132+ )
133+
134+ # Create action without to_user
135+ mr .actions .create (
136+ by_user = self .user ,
137+ action = constants .ACTION_STARTED ,
138+ to_user = None ,
139+ )
140+
141+ reviewers = ModerationCollection .objects .reviewers (collection )
142+
143+ # Should include users from group (user2 and user3)
144+ self .assertIn (self .user2 , reviewers )
145+ self .assertIn (self .user3 , reviewers )
146+ self .assertGreaterEqual (len (reviewers ), 2 )
147+
148+ def test_reviewers_returns_empty_set_when_no_moderation_requests (self ):
149+ """Test that reviewers returns empty set when collection has no moderation requests"""
150+ # Create collection without moderation requests
151+ collection = ModerationCollection .objects .create (
152+ author = self .user ,
153+ name = "Empty Collection" ,
154+ workflow = self .wf1 ,
155+ )
156+
157+ reviewers = ModerationCollection .objects .reviewers (collection )
158+
159+ self .assertEqual (len (reviewers ), 0 )
160+ self .assertIsInstance (reviewers , set )
161+
162+ def test_reviewers_handles_workflow_without_first_step (self ):
163+ """Test that reviewers handles workflow with no first step gracefully"""
164+ # Create workflow with no steps
165+ workflow = self .wf1
166+ workflow .steps .all ().delete ()
167+
168+ collection = ModerationCollection .objects .create (
169+ author = self .user ,
170+ name = "Collection No Steps" ,
171+ workflow = workflow ,
172+ status = constants .IN_REVIEW
173+ )
174+
175+ from djangocms_versioning .test_utils .factories import PageVersionFactory
176+ version = PageVersionFactory ()
177+ mr = collection .moderation_requests .create (
178+ version = version ,
179+ language = "en" ,
180+ author = self .user ,
181+ is_active = True ,
182+ )
183+
184+ # Create action without to_user
185+ mr .actions .create (
186+ by_user = self .user ,
187+ action = constants .ACTION_STARTED ,
188+ to_user = None ,
189+ )
190+
191+ # Should not raise an error
192+ reviewers = ModerationCollection .objects .reviewers (collection )
193+
194+ self .assertEqual (len (reviewers ), 0 )
195+
196+ def test_reviewers_aggregates_from_multiple_moderation_requests (self ):
197+ """Test that reviewers aggregates users from multiple moderation requests in collection"""
198+ # collection3 has two moderation requests with different users
199+ reviewers = ModerationCollection .objects .reviewers (self .collection3 )
200+
201+ # Both requests have actions assigned to user2
202+ self .assertIn (self .user2 , reviewers )
203+
204+ # moderation_request4 was rejected by user3
205+ # Note: rejected actions don't have to_user in the base setup,
206+ # but let's verify the behavior
207+ self .assertGreaterEqual (len (reviewers ), 1 )
208+
209+ def test_reviewers_with_prefetch_is_efficient (self ):
210+ """Test that using prefetch_reviewers makes the reviewers method efficient"""
211+ # This test verifies the relationship between prefetch and reviewers method
212+ collection = ModerationCollection .objects .prefetch_reviewers ().get (pk = self .collection1 .pk )
213+
214+ # With prefetch, this should not trigger additional queries
215+ with self .assertNumQueries (0 ):
216+ reviewers = ModerationCollection .objects .reviewers (collection )
217+
218+ self .assertIn (self .user2 , reviewers )
0 commit comments