@@ -12,5 +12,159 @@ def _obtain_auth_token(self, username="operator", password="tester"):
1212 return response .data ["token" ]
1313
1414
15- class APITestCase (TestMultitenantAdminMixin , AuthenticationMixin , TestCase ):
15+ class TestMultitenantApiMixin (TestMultitenantAdminMixin ):
16+ def _test_access_shared_object (
17+ self ,
18+ token ,
19+ listview_name = None ,
20+ listview_path = None ,
21+ detailview_name = None ,
22+ detailview_path = None ,
23+ create_payload = None ,
24+ update_payload = None ,
25+ expected_count = 0 ,
26+ expected_status_codes = None ,
27+ ):
28+ auth = dict (HTTP_AUTHORIZATION = f"Bearer { token } " )
29+ create_payload = create_payload or {}
30+ update_payload = update_payload or {}
31+ expected_status_codes = expected_status_codes or {}
32+
33+ if listview_name or listview_path :
34+ listview_path = listview_path or reverse (listview_name )
35+ with self .subTest ("HEAD and OPTION methods" ):
36+ response = self .client .head (listview_path , ** auth )
37+ self .assertEqual (response .status_code , expected_status_codes ["head" ])
38+
39+ response = self .client .options (listview_path , ** auth )
40+ self .assertEqual (response .status_code , expected_status_codes ["option" ])
41+
42+ with self .subTest ("Create shared object" ):
43+ response = self .client .post (
44+ listview_path ,
45+ data = create_payload ,
46+ content_type = "application/json" ,
47+ ** auth ,
48+ )
49+ self .assertEqual (response .status_code , expected_status_codes ["create" ])
50+ if expected_status_codes ["create" ] == 400 :
51+ self .assertEqual (
52+ str (response .data ["organization" ][0 ]),
53+ "This field may not be null." ,
54+ )
55+
56+ with self .subTest ("List all shared objects" ):
57+ response = self .client .get (listview_path , ** auth )
58+ self .assertEqual (response .status_code , expected_status_codes ["list" ])
59+ data = response .data
60+ if not isinstance (response .data , list ):
61+ data = data .get ("results" , data )
62+ self .assertEqual (len (data ), expected_count )
63+
64+ if detailview_name or detailview_path :
65+ if not detailview_path and listview_name and expected_count > 0 :
66+ detailview_path = reverse (detailview_name , args = [data [0 ]["id" ]])
67+
68+ with self .subTest ("Retrieve shared object" ):
69+ response = self .client .get (detailview_path , ** auth )
70+ self .assertEqual (
71+ response .status_code , expected_status_codes ["retrieve" ]
72+ )
73+
74+ with self .subTest ("Update shared object" ):
75+ response = self .client .put (
76+ detailview_path ,
77+ data = update_payload ,
78+ content_type = "application/json" ,
79+ ** auth ,
80+ )
81+ self .assertEqual (response .status_code , expected_status_codes ["update" ])
82+
83+ with self .subTest ("Delete shared object" ):
84+ response = self .client .delete (detailview_path , ** auth )
85+ self .assertEqual (response .status_code , expected_status_codes ["delete" ])
86+
87+ def _test_org_user_access_shared_object (
88+ self ,
89+ listview_name = None ,
90+ listview_path = None ,
91+ detailview_name = None ,
92+ detailview_path = None ,
93+ create_payload = None ,
94+ update_payload = None ,
95+ expected_count = 0 ,
96+ expected_status_codes = None ,
97+ token = None ,
98+ ):
99+ """
100+ Non-superusers can only view shared objects.
101+ They cannot create, update, or delete them.
102+ """
103+ if not token :
104+ user = self ._create_administrator (organizations = [self ._get_org ()])
105+ token = self ._obtain_auth_token (user .username , "tester" )
106+ if not expected_status_codes :
107+ expected_status_codes = {
108+ "create" : 400 ,
109+ "list" : 200 ,
110+ "retrieve" : 200 ,
111+ "update" : 403 ,
112+ "delete" : 403 ,
113+ "head" : 200 ,
114+ "option" : 200 ,
115+ }
116+ self ._test_access_shared_object (
117+ token = token ,
118+ listview_name = listview_name ,
119+ listview_path = listview_path ,
120+ detailview_name = detailview_name ,
121+ detailview_path = detailview_path ,
122+ create_payload = create_payload ,
123+ update_payload = update_payload ,
124+ expected_count = expected_count ,
125+ expected_status_codes = expected_status_codes ,
126+ )
127+
128+ def _test_superuser_access_shared_object (
129+ self ,
130+ token ,
131+ listview_path = None ,
132+ listview_name = None ,
133+ detailview_path = None ,
134+ detailview_name = None ,
135+ create_payload = None ,
136+ update_payload = None ,
137+ expected_count = 1 ,
138+ expected_status_codes = None ,
139+ ):
140+ """
141+ Superusers can perform all operations on shared objects.
142+ """
143+ if not token :
144+ user = self ._create_admin ()
145+ token = self ._obtain_auth_token (user .username , "tester" )
146+ if not expected_status_codes :
147+ expected_status_codes = {
148+ "create" : 201 ,
149+ "list" : 200 ,
150+ "retrieve" : 200 ,
151+ "update" : 200 ,
152+ "delete" : 204 ,
153+ "head" : 200 ,
154+ "option" : 200 ,
155+ }
156+ self ._test_access_shared_object (
157+ token = token ,
158+ listview_name = listview_name ,
159+ listview_path = listview_path ,
160+ detailview_name = detailview_name ,
161+ detailview_path = detailview_path ,
162+ create_payload = create_payload ,
163+ update_payload = update_payload ,
164+ expected_count = expected_count ,
165+ expected_status_codes = expected_status_codes ,
166+ )
167+
168+
169+ class APITestCase (TestMultitenantApiMixin , AuthenticationMixin , TestCase ):
16170 pass
0 commit comments