Coverage for tests/publisher/test_publisher_views.py: 100%

180 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-27 22:07 +0000

1import unittest 

2from webapp.app import app 

3from tests.mock_data.mock_store_logic import sample_charm 

4from unittest.mock import patch 

5 

6from canonicalwebteam.exceptions import StoreApiResponseErrorList 

7 

8 

9class TestPublisherViews(unittest.TestCase): 

10 @patch( 

11 "webapp.decorators.login_required", 

12 ) 

13 def setUp(self, mock_login_required): 

14 mock_login_required.return_value = lambda: True 

15 self.app = app 

16 self.app.config["TESTING"] = True 

17 self.app.config["WTF_CSRF_ENABLED"] = [] 

18 self.client = self.app.test_client() 

19 self.set_session() 

20 

21 def set_session(self): 

22 with self.client.session_transaction() as session: 

23 session["account"] = { 

24 "display-name": "test-display-name", 

25 "email": "test-email", 

26 "username": "test-username", 

27 } 

28 session["account-auth"] = "test-auth" 

29 

30 def test_get_account_details_no_login(self): 

31 with self.client.session_transaction() as session: 

32 del session["account-auth"] 

33 del session["account"] 

34 res = self.client.get("/account/details") 

35 self.assertEqual(res.status_code, 302) 

36 

37 @patch( 

38 "webapp.authentication.is_authenticated", 

39 return_value=True, 

40 ) 

41 def test_get_account_details(self, mock_is_authenticated): 

42 res = self.client.get("/account/details") 

43 self.assertEqual(res.status_code, 200) 

44 self.assertIn(b"test-display-name", res.data) 

45 self.assertIn(b"test-email", res.data) 

46 self.assertIn(b"test-username", res.data) 

47 

48 @patch("webapp.store_api.publisher_gateway.get_package_metadata") 

49 def test_get_publisher(self, mock_get_package_metadata): 

50 mock_get_package_metadata.return_value = sample_charm 

51 for endpoint in [ 

52 "listing", 

53 "releases", 

54 "publicise", 

55 "collaboration", 

56 "settings", 

57 ]: 

58 res = self.client.get(f"/test-entity/{endpoint}") 

59 self.assertEqual(res.status_code, 200) 

60 

61 @patch("webapp.store_api.publisher_gateway.get_package_metadata") 

62 def test_get_package(self, mock_get_package_metadata): 

63 mock_get_package_metadata.return_value = {"name": "test-package"} 

64 res = self.client.get("/api/packages/test-entity") 

65 self.assertEqual(res.status_code, 200) 

66 self.assertEqual( 

67 res.json, 

68 {"success": True, "data": mock_get_package_metadata.return_value}, 

69 ) 

70 

71 @patch("webapp.store_api.publisher_gateway.update_package_metadata") 

72 def test_update_package(self, mock_update_package_metadata): 

73 mock_update_package_metadata.return_value = {"name": "test-package"} 

74 res = self.client.patch( 

75 "/api/packages/test-entity", json={"key": "value"} 

76 ) 

77 self.assertEqual(res.status_code, 200) 

78 

79 @patch("webapp.store_api.publisher_gateway.update_package_metadata") 

80 def test_update_package_failure(self, mock_update_package_metadata): 

81 mock_update_package_metadata.side_effect = StoreApiResponseErrorList( 

82 "test-error", 500, [] 

83 ) 

84 res = self.client.patch( 

85 "/api/packages/test-entity", json={"key": "value"} 

86 ) 

87 self.assertEqual(res.status_code, 500) 

88 self.assertEqual(res.json["success"], False) 

89 

90 @patch("webapp.store_api.publisher_gateway.update_package_metadata") 

91 def test_update_package_unauthorized(self, mock_update_package_metadata): 

92 mock_update_package_metadata.side_effect = StoreApiResponseErrorList( 

93 "test-error", 500, [{"message": "unauthorized"}] 

94 ) 

95 res = self.client.patch( 

96 "/api/packages/test-entity", json={"key": "value"} 

97 ) 

98 self.assertEqual(res.status_code, 500) 

99 self.assertEqual(res.json["success"], False) 

100 self.assertEqual(res.json["message"], "Package not found") 

101 

102 @patch("webapp.store_api.publisher_gateway.get_account_packages") 

103 def test_list_page(self, mock_get_account_packages): 

104 mock_get_account_packages.return_value = [ 

105 { 

106 "contact": "email", 

107 "id": "ChgcZB3RhaDOnhkAv9cgRg52LhjBbDt8", 

108 "media": [ 

109 { 

110 "type": "icon", 

111 "url": "https://example.com/icon.svg", 

112 } 

113 ], 

114 "name": "postgresql", 

115 "private": False, 

116 "publisher": { 

117 "id": "test-id", 

118 "display-name": "Canonical Data Platform", 

119 }, 

120 "status": "published", 

121 "type": "charm", 

122 }, 

123 ] 

124 

125 with self.client.session_transaction() as session: 

126 session["account"] = {"id": "test-id"} 

127 

128 res = self.client.get("/charms") 

129 self.assertEqual(res.status_code, 200) 

130 self.assertIn(b"postgresql", res.data) 

131 self.assertIn(b"Published charms", res.data) 

132 res = self.client.get("/bundles") 

133 self.assertEqual(res.status_code, 200) 

134 self.assertNotIn(b"postgresql", res.data) 

135 

136 def test_accept_invite(self): 

137 res = self.client.get("/accept-invite") 

138 self.assertIn(b"Success", res.data) 

139 self.assertEqual(res.status_code, 200) 

140 

141 @patch("webapp.store_api.publisher_gateway.accept_invite") 

142 def test_accept_post_invite(self, mock_accept_invite): 

143 mock_accept_invite.return_value.status_code = 204 

144 res = self.client.post( 

145 "/accept-invite", 

146 data={"token": "test-token", "package": "test-package"}, 

147 ) 

148 self.assertEqual(res.status_code, 200) 

149 

150 @patch("webapp.store_api.publisher_gateway.accept_invite") 

151 def test_accept_post_invite_failed(self, mock_accept_invite): 

152 mock_accept_invite.return_value.status_code = 401 

153 res = self.client.post( 

154 "/accept-invite", 

155 data={"token": "test-token", "package": "test-package"}, 

156 ) 

157 self.assertEqual(res.status_code, 500) 

158 self.assertEqual(res.json["message"], "An error occured") 

159 

160 @patch("webapp.store_api.publisher_gateway.reject_invite") 

161 def test_reject_post_invite(self, mock_reject_invite): 

162 mock_reject_invite.return_value.status_code = 204 

163 res = self.client.post( 

164 "/reject-invite", 

165 data={"token": "test-token", "package": "test-package"}, 

166 ) 

167 self.assertEqual(res.status_code, 200) 

168 

169 @patch("webapp.store_api.publisher_gateway.get_collaborators") 

170 def test_get_collaborators(self, mock_get_collaborators): 

171 mock_get_collaborators.return_value = [{"name": "collaborator"}] 

172 res = self.client.get("/api/packages/test-entity/collaborators") 

173 self.assertEqual(res.status_code, 200) 

174 

175 @patch("webapp.store_api.publisher_gateway.get_collaborators") 

176 def test_get_collaborators_failed(self, mock_get_collaborators): 

177 mock_get_collaborators.side_effect = StoreApiResponseErrorList( 

178 "test-error", 500, [] 

179 ) 

180 res = self.client.get("/api/packages/test-entity/collaborators") 

181 self.assertEqual(res.status_code, 500) 

182 

183 @patch("webapp.store_api.publisher_gateway.get_pending_invites") 

184 def test_get_pending_invites(self, mock_get_pending_invites): 

185 mock_get_pending_invites.return_value = { 

186 "invites": [{"name": "invite"}] 

187 } 

188 res = self.client.get("/api/packages/test-entity/invites") 

189 self.assertEqual(res.status_code, 200) 

190 

191 @patch("webapp.store_api.publisher_gateway.invite_collaborators") 

192 def test_invite_collaborators(self, mock_invite_collaborators): 

193 mock_invite_collaborators.return_value = {"tokens": ["token"]} 

194 res = self.client.post( 

195 "/api/packages/test-entity/invites", 

196 data={"collaborators": "collaborator"}, 

197 ) 

198 self.assertEqual(res.status_code, 200) 

199 

200 @patch("webapp.store_api.publisher_gateway.revoke_invites") 

201 def test_revoke_invite(self, mock_revoke_invites): 

202 mock_revoke_invites.return_value.status_code = 204 

203 res = self.client.delete( 

204 "/api/packages/test-entity/invites", 

205 data={"collaborator": "collaborator"}, 

206 ) 

207 self.assertEqual(res.status_code, 200) 

208 

209 def test_register_name(self): 

210 res = self.client.get("/register-name") 

211 self.assertEqual(res.status_code, 200) 

212 self.assertIn(b"Register a new", res.data) 

213 

214 @patch("webapp.store_api.publisher_gateway.register_package_name") 

215 def test_post_register_name(self, mock_register_package_name): 

216 mock_register_package_name.return_value = True 

217 res = self.client.post( 

218 "/register-name", 

219 data={ 

220 "name": "test-name", 

221 "type": "charm", 

222 "private": "private", 

223 }, 

224 ) 

225 self.assertEqual(res.status_code, 302) 

226 

227 @patch("webapp.store_api.publisher_gateway.register_package_name") 

228 def test_post_register_name_already_owned( 

229 self, mock_register_package_name 

230 ): 

231 mock_register_package_name.side_effect = StoreApiResponseErrorList( 

232 "test-error", 500, [{"code": "already-owned"}] 

233 ) 

234 res = self.client.post( 

235 "/register-name", 

236 data={ 

237 "name": "test-name", 

238 "type": "charm", 

239 "private": "private", 

240 }, 

241 ) 

242 self.assertEqual(res.status_code, 302) 

243 self.assertIn("already_owned=True", res.headers["Location"]) 

244 

245 def test_register_name_dispute(self): 

246 res = self.client.get("/register-name-dispute?entity-name=test-name") 

247 self.assertEqual(res.status_code, 200) 

248 self.assertIn(b"Claim the name", res.data) 

249 

250 def test_register_name_dispute_redirect(self): 

251 res = self.client.get("/register-name-dispute") 

252 self.assertEqual(res.status_code, 302) 

253 

254 def test_register_name_dispute_thank_you_redirect(self): 

255 res = self.client.get("/register-name-dispute/thank-you") 

256 self.assertEqual(res.status_code, 302) 

257 

258 def test_register_name_dispute_thank_you(self): 

259 res = self.client.get( 

260 "/register-name-dispute/thank-you?entity-name=test-name" 

261 ) 

262 self.assertEqual(res.status_code, 200) 

263 self.assertIn( 

264 b"We will process the details provided with the name dispute.", 

265 res.data, 

266 ) 

267 

268 @patch("webapp.store_api.publisher_gateway.unregister_package_name") 

269 def test_delete_package(self, mock_unregister_package_name): 

270 mock_unregister_package_name.return_value.status_code = 200 

271 res = self.client.delete("/packages/test-package") 

272 self.assertEqual(res.status_code, 200) 

273 

274 @patch("webapp.store_api.publisher_gateway.unregister_package_name") 

275 def test_delete_package_failed(self, mock_unregister_package_name): 

276 mock_unregister_package_name.return_value.status_code = 500 

277 mock_unregister_package_name.return_value.json = { 

278 "error-list": [{"message": "test-error"}] 

279 } 

280 res = self.client.delete("/packages/test-package") 

281 self.assertEqual(res.status_code, 500) 

282 

283 @patch("webapp.store_api.publisher_gateway.create_track") 

284 def test_post_create_track(self, mock_create_track): 

285 mock_create_track.return_value.status_code = 201 

286 mock_create_track.return_value.json = lambda: {"track": "test-track"} 

287 res = self.client.post( 

288 "/test-charm/create-track", 

289 data={ 

290 "track-name": "test-track", 

291 "version-pattern": "v1", 

292 "auto-phasing-percentage": "50", 

293 }, 

294 ) 

295 self.assertEqual(res.status_code, 201) 

296 

297 @patch("webapp.store_api.publisher_gateway.create_track") 

298 def test_post_create_track_already_exists(self, mock_create_track): 

299 mock_create_track.return_value.status_code = 409 

300 mock_create_track.return_value.json = lambda: {"track": "test-track"} 

301 res = self.client.post( 

302 "/test-charm/create-track", 

303 data={ 

304 "track-name": "test-track", 

305 "version-pattern": "v1", 

306 "auto-phasing-percentage": "50", 

307 }, 

308 ) 

309 self.assertEqual(res.status_code, 409) 

310 

311 @patch("webapp.store_api.publisher_gateway.get_releases") 

312 @patch("webapp.publisher.logic.process_releases") 

313 @patch("webapp.publisher.logic.get_all_architectures") 

314 def test_get_releases( 

315 self, 

316 mock_get_all_architectures, 

317 mock_process_releases, 

318 mock_get_releases, 

319 ): 

320 mock_get_releases.return_value = { 

321 "channel-map": [], 

322 "package": {"channels": []}, 

323 "revisions": [], 

324 } 

325 mock_process_releases.return_value = [] 

326 mock_get_all_architectures.return_value = [] 

327 self.set_session() 

328 res = self.client.get("/api/packages/test-entity/releases") 

329 self.assertEqual(res.status_code, 200)