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

182 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2025-08-08 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.utils.emailer.Emailer.send_email_template") 

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

193 def test_invite_collaborators( 

194 self, mock_invite_collaborators, mock_send_email_template 

195 ): 

196 mock_send_email_template.return_value = None 

197 mock_invite_collaborators.return_value = { 

198 "tokens": [{"token": "test-token"}] 

199 } 

200 res = self.client.post( 

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

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

203 ) 

204 self.assertEqual(res.status_code, 200) 

205 

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

207 def test_revoke_invite(self, mock_revoke_invites): 

208 mock_revoke_invites.return_value.status_code = 204 

209 res = self.client.delete( 

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

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

212 ) 

213 self.assertEqual(res.status_code, 200) 

214 

215 def test_register_name(self): 

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

217 self.assertEqual(res.status_code, 200) 

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

219 

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

221 def test_post_register_name(self, mock_register_package_name): 

222 mock_register_package_name.return_value = True 

223 res = self.client.post( 

224 "/register-name", 

225 data={ 

226 "name": "test-name", 

227 "type": "charm", 

228 "private": "private", 

229 }, 

230 ) 

231 self.assertEqual(res.status_code, 302) 

232 

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

234 def test_post_register_name_already_owned( 

235 self, mock_register_package_name 

236 ): 

237 mock_register_package_name.side_effect = StoreApiResponseErrorList( 

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

239 ) 

240 res = self.client.post( 

241 "/register-name", 

242 data={ 

243 "name": "test-name", 

244 "type": "charm", 

245 "private": "private", 

246 }, 

247 ) 

248 self.assertEqual(res.status_code, 302) 

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

250 

251 def test_register_name_dispute(self): 

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

253 self.assertEqual(res.status_code, 200) 

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

255 

256 def test_register_name_dispute_redirect(self): 

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

258 self.assertEqual(res.status_code, 302) 

259 

260 def test_register_name_dispute_thank_you_redirect(self): 

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

262 self.assertEqual(res.status_code, 302) 

263 

264 def test_register_name_dispute_thank_you(self): 

265 res = self.client.get( 

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

267 ) 

268 self.assertEqual(res.status_code, 200) 

269 self.assertIn( 

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

271 res.data, 

272 ) 

273 

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

275 def test_delete_package(self, mock_unregister_package_name): 

276 mock_unregister_package_name.return_value.status_code = 200 

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

278 self.assertEqual(res.status_code, 200) 

279 

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

281 def test_delete_package_failed(self, mock_unregister_package_name): 

282 mock_unregister_package_name.return_value.status_code = 500 

283 mock_unregister_package_name.return_value.json = { 

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

285 } 

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

287 self.assertEqual(res.status_code, 500) 

288 

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

290 def test_post_create_track(self, mock_create_track): 

291 mock_create_track.return_value.status_code = 201 

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

293 res = self.client.post( 

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

295 data={ 

296 "track-name": "test-track", 

297 "version-pattern": "v1", 

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

299 }, 

300 ) 

301 self.assertEqual(res.status_code, 201) 

302 

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

304 def test_post_create_track_already_exists(self, mock_create_track): 

305 mock_create_track.return_value.status_code = 409 

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

307 res = self.client.post( 

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

309 data={ 

310 "track-name": "test-track", 

311 "version-pattern": "v1", 

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

313 }, 

314 ) 

315 self.assertEqual(res.status_code, 409) 

316 

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

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

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

320 def test_get_releases( 

321 self, 

322 mock_get_all_architectures, 

323 mock_process_releases, 

324 mock_get_releases, 

325 ): 

326 mock_get_releases.return_value = { 

327 "channel-map": [], 

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

329 "revisions": [], 

330 } 

331 mock_process_releases.return_value = [] 

332 mock_get_all_architectures.return_value = [] 

333 self.set_session() 

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

335 self.assertEqual(res.status_code, 200)