Coverage for apis_core/generic/tests/test_generic.py: 36%

101 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2025-09-03 06:15 +0000

1import pytest 

2from django.contrib.auth.models import Permission, User 

3from django.contrib.contenttypes.models import ContentType 

4from faker import Faker 

5 

6from apis_core.generic.tests.models import Dummy, Person 

7from apis_core.generic.tests.tables import DummyTable 

8from apis_core.generic.views import List 

9 

10fake = Faker() 

11 

12# tuple of route, permission, and expected status_code 

13routes = [ 

14 ("/generic_tests.person/", "view_person", 200), 

15 ("/generic_tests.person/1", "view_person", 200), 

16 ("/generic_tests.person/create", "add_person", 200), 

17 ("/generic_tests.person/delete/1", "delete_person", 200), 

18 ("/generic_tests.person/update/1", "change_person", 200), 

19 ("/generic_tests.person/duplicate/1", "add_person", 302), 

20 ("/generic_tests.person/autocomplete", "view_person", 200), 

21 ("/generic_tests.person/import", "add_person", 200), 

22 ("/generic_tests.person/selectmergeorenrich/1", "add_person", 200), 

23 ("/generic_tests.person/merge/1/2", "change_person", 200), 

24 ( 

25 "/generic_tests.person/enrich/1?uri=https://d-nb.info/gnd/119252880", 

26 "change_person", 

27 200, 

28 ), 

29] 

30route_parameters = "route,permission,status_code" 

31 

32unique_first_name = "SomeUniqueFirstName" 

33unique_last_name = "SomeUniqueLastName" 

34 

35 

36@pytest.mark.django_db 

37class TestGeneric(object): 

38 @pytest.fixture 

39 def setup(self): 

40 # Create an admin user 

41 self.admin = User.objects.create_superuser( 

42 "admin", fake.email(), fake.password() 

43 ) 

44 # Create a normal user 

45 self.user = User.objects.create_user( 

46 fake.user_name(), fake.email(), fake.password() 

47 ) 

48 # Create a couple of person objects 

49 for _ in range(0, fake.random_int(5, 20)): 

50 Person.objects.create( 

51 first_name=fake.first_name(), last_name=fake.last_name() 

52 ) 

53 self.unique = Person.objects.create( 

54 first_name=unique_first_name, last_name=unique_last_name 

55 ) 

56 self.person_count = Person.objects.count() 

57 

58 def test_person_count(self, setup): 

59 """Check if the correct number of persons was created""" 

60 assert Person.objects.count() == self.person_count 

61 

62 # Initial tests for checking the permissions of the views 

63 

64 @pytest.mark.parametrize(route_parameters, routes) 

65 def test_anon_person_views(self, setup, route, permission, status_code, client): 

66 """Anon user should not be able to access the person views""" 

67 response = client.get(route) 

68 assert response.status_code == 302 

69 

70 @pytest.mark.parametrize(route_parameters, routes) 

71 def test_admin_person_views( 

72 self, setup, route, permission, status_code, admin_client 

73 ): 

74 """Admin user should be able to access the person list""" 

75 response = admin_client.get(route) 

76 assert response.status_code == status_code 

77 

78 @pytest.mark.parametrize(route_parameters, routes) 

79 def test_person_user_views(self, setup, route, permission, status_code, client): 

80 """Normal user should not be able to access the person list""" 

81 client.force_login(self.user) 

82 response = client.get(route) 

83 assert response.status_code == 403 

84 

85 @pytest.mark.parametrize(route_parameters, routes) 

86 def test_person_user_with_access( 

87 self, setup, route, permission, status_code, client 

88 ): 

89 """Normal user should be able to access the person views after bein granted permission""" 

90 content_type = ContentType.objects.get_for_model(Person) 

91 p = Permission.objects.get(codename=permission, content_type=content_type) 

92 self.user.user_permissions.add(p) 

93 client.force_login(self.user) 

94 response = client.get(route) 

95 assert response.status_code == status_code 

96 

97 # More detailed tests checking the content of the responses and sending actual data 

98 

99 def test_person_list(self, setup, admin_client): 

100 """Check if the first_name of some person object is listed in the person list""" 

101 p = Person.objects.order_by("?").first() 

102 response = admin_client.get("/generic_tests.person/") 

103 assert p.first_name in response.content.decode() 

104 

105 def test_person_detail(self, setup, admin_client): 

106 """Check if the details page of a person lists its details""" 

107 p = Person.objects.order_by("?").first() 

108 response = admin_client.get(f"/generic_tests.person/{p.pk}") 

109 assert p.first_name in response.content.decode() 

110 assert p.last_name in response.content.decode() 

111 

112 def test_person_create(self, setup, admin_client): 

113 """Check if we can create a person using the create route""" 

114 data = { 

115 "first_name": fake.first_name(), 

116 "last_name": fake.last_name(), 

117 } 

118 response = admin_client.post("/generic_tests.person/create", data, follow=True) 

119 assert response.status_code == 200 

120 assert data["first_name"] in response.content.decode() 

121 assert data["last_name"] in response.content.decode() 

122 assert Person.objects.count() == self.person_count + 1 

123 

124 def test_person_delete(self, setup, admin_client): 

125 """Check if we can delete a person using the delete route""" 

126 p = Person.objects.order_by("?").first() 

127 response = admin_client.get(f"/generic_tests.person/delete/{p.pk}") 

128 assert response.status_code == 200 

129 assert "Confirm deletion of:" in response.content.decode() 

130 assert str(p) in response.content.decode() 

131 

132 def test_person_delete_confirmation(self, setup, admin_client): 

133 """Check if we can delete a person using the delete route""" 

134 p = self.unique 

135 response = admin_client.post( 

136 f"/generic_tests.person/delete/{p.pk}", follow=True 

137 ) 

138 assert response.status_code == 200 

139 assert p.first_name not in response.content.decode() 

140 assert p.last_name not in response.content.decode() 

141 assert Person.objects.count() == self.person_count - 1 

142 

143 def test_person_delete_redirect(self, setup, admin_client): 

144 """Check if we can delete a person using the delete route""" 

145 p = self.unique 

146 response = admin_client.post( 

147 f"/generic_tests.person/delete/{p.pk}?redirect=/generic_tests.person/create" 

148 ) 

149 assert response.status_code == 302 

150 assert response.headers["Location"] == "/generic_tests.person/create" 

151 

152 def test_person_update(self, setup, admin_client): 

153 """Check if we can update a person""" 

154 p = Person.objects.order_by("?").first() 

155 data = { 

156 "first_name": fake.first_name(), 

157 "last_name": fake.last_name(), 

158 } 

159 response = admin_client.post( 

160 f"/generic_tests.person/update/{p.pk}", data, follow=True 

161 ) 

162 assert response.status_code == 200 

163 assert Person.objects.get(pk=p.pk).last_name == data["last_name"] 

164 assert Person.objects.get(pk=p.pk).first_name == data["first_name"] 

165 

166 def test_person_autocomplete(self, setup, admin_client): 

167 """Check if we find a person using autocomplete""" 

168 p = self.unique 

169 response = admin_client.get( 

170 f"/generic_tests.person/autocomplete?q={p.first_name}" 

171 ) 

172 assert response.status_code == 200 

173 expected = { 

174 "results": [{"id": str(p.pk), "selected_text": str(p), "text": str(p)}], 

175 "pagination": {"more": False}, 

176 } 

177 assert response.json() == expected 

178 

179 def test_person_table_export_filename(self, rf, admin_user): 

180 """Check if the person table provides the correct export filename""" 

181 view = List(model=Person) 

182 assert view.get_export_filename("ext") == "table.ext" 

183 

184 def test_dummy_table_export_filename(self, rf, admin_user): 

185 """Check if the dummy table provides the correct export filename""" 

186 view = List(model=Dummy) 

187 assert view.get_export_filename("ext") == "dummytable.ext" 

188 

189 def test_dummy_table_class(self, admin_client): 

190 request = admin_client.get("/generic_tests.dummy/") 

191 assert isinstance(request.context["table"], DummyTable)