Coverage for tests/test_custom_admin_pages.py: 99%

1 import sys

2 from importlib import reload

3

4 from django.conf import settings

5 from django.contrib import admin

6 from django.contrib.auth import get_user_model

7 from django.contrib.auth.models import AbstractUser, Permission

8 from django.contrib.contenttypes.models import ContentType

9 from django.core.exceptions import ImproperlyConfigured

10 from django.shortcuts import render

11 from django.test import RequestFactory

12 from django.urls import clear_url_caches, reverse

13 from django.utils.text import get_valid_filename, slugify

14 from django.views.generic import TemplateView

15

16 import pytest

17

18 from ..views.admin_base_view import AdminBaseView

19

20 User: AbstractUser = get_user_model()

21

22 ADMIN_BASE_URL = reverse("admin:index")

23 django_custom_admin_pages_URL = (

24 f"{ADMIN_BASE_URL}{settings.CUSTOM_ADMIN_DEFAULT_APP_LABEL}/"

25)

26

27

28 def reload_urlconf(urlconf=None):

29 """

30 reloads urlconf, or sepecific urls.py passed in via urlconf arg.

31 """

32 urlconf = settings.ROOT_URLCONF

33 if urlconf in sys.modules:

34 clear_url_caches()

35 reload(sys.modules[urlconf])

36

37

38 class AnExampleView(AdminBaseView, TemplateView):

39 view_name = "Test Name"

40 route_name = "test_route"

41 template_name = "base_custom_admin.html"

42

43

44 class AnExampleAppView(AdminBaseView, TemplateView):

45 view_name = "Test App View"

46 app_label = "test_app"

47 route_name = "test_app_route"

48 template_name = "base_custom_admin.html"

49 permission_required = "test_app.test_perm"

50

51

52 class AnotherExampleView(AdminBaseView, TemplateView):

53 view_name = "Test Name"

54 route_name = "test_route1"

55 template_name = "base_custom_admin.html"

56

57

58 class NotInheretedView(TemplateView):

59 view_name = "Test Name"

60 route_name = "test_route"

61 template_name = "base_custom_admin.html"

62

63

64 def not_a_class_based_view(request):

65 return render(request, "base_custom_admin.html", context=dict())

66

67

68 class NoViewName(AdminBaseView, TemplateView):

69 route_name = "test_route2"

70 template_name = "base_custom_admin.html"

71

72

73 class NoRouteName(AdminBaseView, TemplateView):

74 view_name = "Test Name"

75 template_name = "base_custom_admin.html"

76

77

78@pytest.fixture

79 def superuser():

80 return User.objects.create(

81 username="Julian",

82 password="JulianTheWizard",

83 is_staff=True,

84 is_active=True,

85 is_superuser=True,

86 )

87

88

89 class TestRegistration:

90 """

91 Test registering a view

92 """

93

94 def it_raises_when_not_class_based(self):

95 with pytest.raises(ImproperlyConfigured):

96 admin.site.register_view(not_a_class_based_view)

97

98 def it_raises_when_no_view_name(self):

99 with pytest.raises(ImproperlyConfigured):

100 admin.site.register_view(NoViewName)

101

102 def it_doesnt_raise_when_no_route_name(self):

103 admin.site.register_view(NoRouteName)

104 assert (

105 NoRouteName.route_name == get_valid_filename(NoRouteName.view_name).lower()

106 )

107 assert NoRouteName.route_path == slugify(NoRouteName.view_name).lower()

108

109 def it_raises_when_not_subclassed(self):

110 with pytest.raises(ImproperlyConfigured):

111 admin.site.register_view(NotInheretedView)

112

113 def test_register_twice(self):

114 with pytest.raises(admin.sites.AlreadyRegistered):

115 admin.site.register_view([AnExampleView, AnExampleView])

116 admin.site.unregister_view(AnExampleView)

117

118 def test_unregister_unregistered_raises_error(self):

119 with pytest.raises(admin.sites.NotRegistered):

120 admin.site.unregister_view(AnExampleView)

121

122 def test_register_multiple(self):

123 admin.site.register_view([AnExampleView, AnotherExampleView])

124 admin.site.unregister_view([AnExampleView, AnotherExampleView])

125

126

127@pytest.fixture

128 def view():

129 admin.site.register_view(AnExampleView)

130 reload_urlconf()

131 yield

132 admin.site.unregister_view(AnExampleView)

133

134

135@pytest.fixture

136 def app_view():

137 admin.site.register_view(AnExampleAppView)

138 reload_urlconf()

139 yield

140 admin.site.unregister_view(AnExampleAppView)

141

142

143 class TestPageRendering:

144 @pytest.fixture

145 def super_client(self, client, superuser):

146 client.force_login(superuser)

147 assert superuser.is_staff

148 assert superuser.is_active

149 assert superuser.is_superuser

150 return client

151

152 @pytest.mark.django_db

153 def test_admin_index_newly_registered_view(self, view, super_client):

154 """

155 Verify that view is in admin custom views

156 """

157

158 # add route in runtime and reload urlconf

159

160 r = super_client.get(reverse("admin:test_route"))

161 assert r.status_code == 200

162

163 django_custom_admin_pages_dict: dict = list(

164 filter(

165 lambda x: x["app_label"] == "django_custom_admin_pages",

166 r.context["app_list"],

167 )

168 )[0]

169 test_view: dict = list(

170 filter(

171 lambda x: x["admin_url"] == f"{django_custom_admin_pages_URL}test-name",

172 django_custom_admin_pages_dict["models"],

173 )

174 )[0]

175

176 assert (

177 django_custom_admin_pages_dict["app_url"] == django_custom_admin_pages_URL

178 )

179 assert django_custom_admin_pages_dict["name"] == "Custom Admin Pages"

180 assert (

181 django_custom_admin_pages_dict["app_label"]

182 == settings.CUSTOM_ADMIN_DEFAULT_APP_LABEL

183 )

184 assert test_view["name"] == "Test Name" == test_view["object_name"]

185 assert test_view["view_only"]

186

187 @pytest.mark.django_db

188 def test_admin_index_newly_registered_app_view(self, app_view, super_client):

189 """

190 Verify that view is in admin custom views

191 """

192

193 # add route in runtime and reload urlconf

194

195 r = super_client.get(reverse("admin:test_app_route"))

196 assert r.status_code == 200

197

198 app_dict: dict = [

199 x for x in r.context["app_list"] if x["app_label"] == "test_app"

200 ][0]

201

202 test_view: dict = [

203 x

204 for x in app_dict["models"]

205 if x["admin_url"] == "/admin/test_app/test-app-view"

206 ][0]

207

208 assert app_dict["app_url"] == "/admin/test_app/"

209 assert app_dict["name"] == "Test_App"

210 assert app_dict["app_label"] == "test_app"

211 assert test_view["name"] == "Test App View" == test_view["object_name"]

212 assert test_view["view_only"]

213

214

215@pytest.mark.django_db

216 def test_get_app_list(superuser, app_view):

217 request_factory = RequestFactory()

218 request = request_factory.get(reverse("admin:index"))

219 request.user = superuser

220

221 app_list = admin.site.get_app_list(request)

222 test_app = [x for x in app_list if x["name"] == "Test_App"][0]

223 assert len([x for x in test_app["models"] if x["name"] == "Test App View"]) == 1

224

225

226 class TestPermissions:

227 @pytest.fixture

228 def test_app_ct(self):

229 return ContentType.objects.get(app_label="test_app", model="somemodel")

230

231 @pytest.fixture

232 def permission(self, test_app_ct):

233 return Permission.objects.create(

234 name="Test Perm", codename="test_perm", content_type=test_app_ct

235 )

236

237 @pytest.fixture

238 def user(self, permission):

239 u = User.objects.create(

240 username="Bill",

241 password="Billspw",

242 is_staff=True,

243 is_active=True,

244 )

245 u.user_permissions.add(permission)

246 return u

247

248 @pytest.mark.django_db

249 def it_shows_if_user_has_permission(sefl, user, app_view):

250 request_factory = RequestFactory()

251 request = request_factory.get(reverse("admin:index"))

252 request.user = user

253

254 app_list = admin.site.get_app_list(request)

255 test_app = [x for x in app_list if x["name"] == "Test_App"][0]

256 assert len([x for x in test_app["models"] if x["name"] == "Test App View"]) == 1