Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2This file (test_auth_functional.py) contains the functional tests for 

3the `auth` blueprint. 

4 

5These tests use GETs and POSTs to different endpoints to check 

6for the proper behavior of the `auth` module 

7""" 

8import json 

9import os 

10import threading 

11 

12import pytest 

13from flask import request 

14from flask import url_for 

15from flask_login import current_user 

16from modules.box__default.auth.models import User 

17 

18dirpath = os.path.dirname(os.path.abspath(__file__)) 

19module_path = os.path.dirname(dirpath) 

20 

21module_info = None 

22 

23with open(os.path.join(module_path, "info.json")) as f: 

24 module_info = json.load(f) 

25 

26 

27class TestAuthInvalidAccess: 

28 """ 

29 Test all auth routes for correct user authentication 

30 """ 

31 

32 routes_get = [ 

33 "/confirm/<token>", 

34 "/resend", 

35 "/unconfirmed", 

36 ] 

37 

38 @pytest.mark.parametrize("route", routes_get) 

39 def test_redirect_if_not_logged_in_get(self, test_client, route, auth): 

40 auth.logout() 

41 response = test_client.get( 

42 f"{module_info['url_prefix']}{route}", follow_redirects=True 

43 ) 

44 

45 assert response.status_code == 200 

46 assert request.path == url_for("auth.login") 

47 

48 

49class TestAuthEndpoints: 

50 """ 

51 Test all auth routes' functionalities 

52 """ 

53 

54 def test_user_registration_page_renders(self, test_client): 

55 response = test_client.get(f"{module_info['url_prefix']}/register") 

56 

57 assert response.status_code == 200 

58 assert b"Email" in response.data 

59 assert b"Password" in response.data 

60 assert b"Confirm Password" in response.data 

61 assert b"Register" in response.data 

62 

63 def test_user_not_registered_on_invalid_form_submit(self, test_client): 

64 User.create(email="test@gmail.com", password="pass") 

65 data = { 

66 "email": "test@gmail.com", 

67 "password": "password", 

68 "confirm": "password", 

69 } 

70 

71 response = test_client.post( 

72 f"{module_info['url_prefix']}/register", 

73 data=data, 

74 follow_redirects=True, 

75 ) 

76 

77 assert response.status_code == 200 

78 assert request.path == url_for("auth.register") 

79 

80 def test_user_registration_is_case_insensitive(self, test_client): 

81 User.create(email="foo@bar.com", password="pass") 

82 data = { 

83 "email": "Foo@Bar.com", 

84 "password": "password", 

85 "confirm": "password", 

86 } 

87 

88 response = test_client.post( 

89 f"{module_info['url_prefix']}/register", 

90 data=data, 

91 follow_redirects=True, 

92 ) 

93 

94 assert response.status_code == 200 

95 assert request.path == url_for("auth.register") 

96 

97 @pytest.mark.parametrize( 

98 "email_config", 

99 [ 

100 ("EMAIL_CONFIRMATION_DISABLED", True), 

101 ], 

102 indirect=True, 

103 ) 

104 def test_user_confirmed_if_email_disabled(self, test_client, email_config): 

105 data = { 

106 "email": "test@gmail.com", 

107 "password": "password", 

108 "confirm": "password", 

109 } 

110 response = test_client.post( 

111 f"{module_info['url_prefix']}/register", 

112 data=data, 

113 follow_redirects=True, 

114 ) 

115 user = User.query.filter(User.email == "test@gmail.com").scalar() 

116 

117 assert response.status_code == 200 

118 assert request.path == url_for("dashboard.index") 

119 assert user.is_email_confirmed is True 

120 

121 @pytest.mark.parametrize( 

122 "email_config", 

123 [ 

124 ("EMAIL_CONFIRMATION_DISABLED", "remove"), 

125 ("EMAIL_CONFIRMATION_DISABLED", False), 

126 ("EMAIL_CONFIRMATION_DISABLED", None), 

127 ], 

128 indirect=True, 

129 ) 

130 def test_user_is_registered_on_valid_form_submit( 

131 self, test_client, capfd, email_config 

132 ): 

133 data = { 

134 "email": "test@gmail.com", 

135 "password": "password", 

136 "confirm": "password", 

137 } 

138 response = test_client.post( 

139 f"{module_info['url_prefix']}/register", 

140 data=data, 

141 follow_redirects=True, 

142 ) 

143 # Not very happy with this solution. Need a better 

144 # way to wait for the email thread to join with main 

145 # thread before reading the email written to stdout @rehmanis 

146 while threading.activeCount() > 1: 

147 pass 

148 else: 

149 captured = capfd.readouterr() 

150 

151 user = User.query.filter(User.email == "test@gmail.com").scalar() 

152 

153 assert response.status_code == 200 

154 assert request.path == url_for("auth.unconfirmed") 

155 assert b"A confirmation email has been sent via email" in response.data 

156 assert "test@gmail.com" in captured.out 

157 assert "Welcome to Shopyo" in captured.out 

158 assert user is not None 

159 assert user.is_email_confirmed is False 

160 

161 @pytest.mark.usefixtures("login_non_admin_user") 

162 def test_user_not_confirmed_for_already_confirmed_user(self, test_client): 

163 response = test_client.get( 

164 url_for("auth.confirm", token="sometoken"), follow_redirects=True 

165 ) 

166 

167 assert response.status_code == 200 

168 assert request.path == url_for("dashboard.index") 

169 assert b"Account already confirmed." in response.data 

170 

171 @pytest.mark.usefixtures("login_unconfirmed_user") 

172 def test_user_confirmed_on_valid_token(self, test_client): 

173 token = current_user.generate_confirmation_token() 

174 response = test_client.get( 

175 url_for("auth.confirm", token=token), follow_redirects=True 

176 ) 

177 

178 assert response.status_code == 200 

179 assert request.path == url_for("dashboard.index") 

180 assert b"You have confirmed your account. Thanks!" in response.data 

181 assert current_user.is_email_confirmed is True 

182 

183 @pytest.mark.usefixtures("login_unconfirmed_user") 

184 def test_no_confirm_sent_for_invalid_token(self, test_client): 

185 token = current_user.generate_confirmation_token() + "extra" 

186 response = test_client.get( 

187 url_for("auth.confirm", token=token), follow_redirects=True 

188 ) 

189 

190 assert response.status_code == 200 

191 assert request.path == url_for("auth.unconfirmed") 

192 assert b"The confirmation link is invalid/expired." in response.data 

193 

194 @pytest.mark.usefixtures("login_non_admin_user") 

195 def test_do_not_allow_email_resend_for_confirmed(self, test_client): 

196 response = test_client.get(url_for("auth.resend"), follow_redirects=True) 

197 

198 assert response.status_code == 200 

199 assert request.path == url_for("dashboard.index") 

200 

201 @pytest.mark.usefixtures("login_unconfirmed_user") 

202 def test_valid_resend_email_confirmation(self, test_client, capfd): 

203 response = test_client.get(url_for("auth.resend"), follow_redirects=True) 

204 

205 # Not very happy with this solution. Need a better 

206 # way to wait for the email thread to join with main 

207 # thread before reading the email written to stdout @rehmanis 

208 while threading.activeCount() > 1: 208 ↛ 209line 208 didn't jump to line 209, because the condition on line 208 was never true

209 pass 

210 else: 

211 captured = capfd.readouterr() 

212 

213 assert response.status_code == 200 

214 assert current_user.email in captured.out 

215 assert "Welcome to Shopyo" in captured.out 

216 assert request.path == url_for("auth.unconfirmed") 

217 assert b"A new confirmation email has been sent" in response.data 

218 

219 @pytest.mark.usefixtures("login_non_admin_user") 

220 def test_confirmed_user_is_redirected_to_dashboard(self, test_client): 

221 response = test_client.get(url_for("auth.unconfirmed"), follow_redirects=True) 

222 

223 assert response.status_code == 200 

224 assert request.path == url_for("dashboard.index") 

225 

226 @pytest.mark.usefixtures("login_unconfirmed_user") 

227 def test_unconfirmed_page_renders_correctly(self, test_client): 

228 response = test_client.get(url_for("auth.unconfirmed")) 

229 

230 assert response.status_code == 200 

231 assert request.path == url_for("auth.unconfirmed") 

232 assert b"You have not confirmed your account" in response.data 

233 assert b"Email confirmation link was sent to" in response.data 

234 assert current_user.email.encode() in response.data 

235 

236 def test_login_for_dashboard_renders(self, test_client): 

237 response = test_client.get(url_for("auth.login")) 

238 

239 assert response.status_code == 200 

240 assert b"Login" in response.data 

241 assert b"submit" in response.data 

242 

243 def test_invalid_dashboard_login(self, test_client): 

244 response = test_client.post( 

245 url_for("auth.login"), 

246 data=dict(email="admin1@domain.com", password="wrongpass"), 

247 follow_redirects=True, 

248 ) 

249 

250 assert response.status_code == 200 

251 assert request.path == url_for("auth.login") 

252 assert b"please check your user id and password" in response.data 

253 

254 def test_valid_dashboard_login(self, test_client, non_admin_user): 

255 response = test_client.post( 

256 url_for("auth.login"), 

257 data=dict(email=non_admin_user.email, password="pass"), 

258 follow_redirects=True, 

259 ) 

260 

261 assert response.status_code == 200 

262 assert current_user.email == non_admin_user.email 

263 assert request.path == url_for("dashboard.index") 

264 

265 def test_valid_dashboard_login_is_case_insensitive(self, test_client): 

266 User.create(email="foo@bar.com", password="pass") 

267 data = {"email": "Foo@Bar.com", "password": "pass"} 

268 response = test_client.post( 

269 url_for("auth.login"), 

270 data=data, 

271 follow_redirects=True, 

272 ) 

273 

274 assert response.status_code == 200 

275 assert current_user.email.lower() == data["email"].lower() 

276 assert request.path == url_for("auth.unconfirmed") 

277 

278 @pytest.mark.usefixtures("login_non_admin_user") 

279 def test_current_user_logout(self, test_client): 

280 response = test_client.get(url_for("auth.logout"), follow_redirects=True) 

281 

282 assert response.status_code == 200 

283 assert request.path == url_for("auth.login") 

284 assert b"Successfully logged out" in response.data 

285 assert current_user.is_authenticated is False