Coverage for tests/test_tutorial/test_security/test_tutorial003_an_py310.py: 100%

57 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-08-08 03:53 +0000

1import pytest 1deabc

2from dirty_equals import IsDict 1deabc

3from fastapi.testclient import TestClient 1deabc

4 

5from ...utils import needs_py310 1deabc

6 

7 

8@pytest.fixture(name="client") 1deabc

9def get_client(): 1deabc

10 from docs_src.security.tutorial003_an_py310 import app 1abc

11 

12 client = TestClient(app) 1abc

13 return client 1abc

14 

15 

16@needs_py310 1deabc

17def test_login(client: TestClient): 1deabc

18 response = client.post("/token", data={"username": "johndoe", "password": "secret"}) 1abc

19 assert response.status_code == 200, response.text 1abc

20 assert response.json() == {"access_token": "johndoe", "token_type": "bearer"} 1abc

21 

22 

23@needs_py310 1deabc

24def test_login_incorrect_password(client: TestClient): 1deabc

25 response = client.post( 1abc

26 "/token", data={"username": "johndoe", "password": "incorrect"} 

27 ) 

28 assert response.status_code == 400, response.text 1abc

29 assert response.json() == {"detail": "Incorrect username or password"} 1abc

30 

31 

32@needs_py310 1deabc

33def test_login_incorrect_username(client: TestClient): 1deabc

34 response = client.post("/token", data={"username": "foo", "password": "secret"}) 1abc

35 assert response.status_code == 400, response.text 1abc

36 assert response.json() == {"detail": "Incorrect username or password"} 1abc

37 

38 

39@needs_py310 1deabc

40def test_no_token(client: TestClient): 1deabc

41 response = client.get("/users/me") 1abc

42 assert response.status_code == 401, response.text 1abc

43 assert response.json() == {"detail": "Not authenticated"} 1abc

44 assert response.headers["WWW-Authenticate"] == "Bearer" 1abc

45 

46 

47@needs_py310 1deabc

48def test_token(client: TestClient): 1deabc

49 response = client.get("/users/me", headers={"Authorization": "Bearer johndoe"}) 1abc

50 assert response.status_code == 200, response.text 1abc

51 assert response.json() == { 1abc

52 "username": "johndoe", 

53 "full_name": "John Doe", 

54 "email": "johndoe@example.com", 

55 "hashed_password": "fakehashedsecret", 

56 "disabled": False, 

57 } 

58 

59 

60@needs_py310 1deabc

61def test_incorrect_token(client: TestClient): 1deabc

62 response = client.get("/users/me", headers={"Authorization": "Bearer nonexistent"}) 1abc

63 assert response.status_code == 401, response.text 1abc

64 assert response.json() == {"detail": "Invalid authentication credentials"} 1abc

65 assert response.headers["WWW-Authenticate"] == "Bearer" 1abc

66 

67 

68@needs_py310 1deabc

69def test_incorrect_token_type(client: TestClient): 1deabc

70 response = client.get( 1abc

71 "/users/me", headers={"Authorization": "Notexistent testtoken"} 

72 ) 

73 assert response.status_code == 401, response.text 1abc

74 assert response.json() == {"detail": "Not authenticated"} 1abc

75 assert response.headers["WWW-Authenticate"] == "Bearer" 1abc

76 

77 

78@needs_py310 1deabc

79def test_inactive_user(client: TestClient): 1deabc

80 response = client.get("/users/me", headers={"Authorization": "Bearer alice"}) 1abc

81 assert response.status_code == 400, response.text 1abc

82 assert response.json() == {"detail": "Inactive user"} 1abc

83 

84 

85@needs_py310 1deabc

86def test_openapi_schema(client: TestClient): 1deabc

87 response = client.get("/openapi.json") 1abc

88 assert response.status_code == 200, response.text 1abc

89 assert response.json() == { 1abc

90 "openapi": "3.1.0", 

91 "info": {"title": "FastAPI", "version": "0.1.0"}, 

92 "paths": { 

93 "/token": { 

94 "post": { 

95 "responses": { 

96 "200": { 

97 "description": "Successful Response", 

98 "content": {"application/json": {"schema": {}}}, 

99 }, 

100 "422": { 

101 "description": "Validation Error", 

102 "content": { 

103 "application/json": { 

104 "schema": { 

105 "$ref": "#/components/schemas/HTTPValidationError" 

106 } 

107 } 

108 }, 

109 }, 

110 }, 

111 "summary": "Login", 

112 "operationId": "login_token_post", 

113 "requestBody": { 

114 "content": { 

115 "application/x-www-form-urlencoded": { 

116 "schema": { 

117 "$ref": "#/components/schemas/Body_login_token_post" 

118 } 

119 } 

120 }, 

121 "required": True, 

122 }, 

123 } 

124 }, 

125 "/users/me": { 

126 "get": { 

127 "responses": { 

128 "200": { 

129 "description": "Successful Response", 

130 "content": {"application/json": {"schema": {}}}, 

131 } 

132 }, 

133 "summary": "Read Users Me", 

134 "operationId": "read_users_me_users_me_get", 

135 "security": [{"OAuth2PasswordBearer": []}], 

136 } 

137 }, 

138 }, 

139 "components": { 

140 "schemas": { 

141 "Body_login_token_post": { 

142 "title": "Body_login_token_post", 

143 "required": ["username", "password"], 

144 "type": "object", 

145 "properties": { 

146 "grant_type": IsDict( 

147 { 

148 "title": "Grant Type", 

149 "anyOf": [ 

150 {"pattern": "password", "type": "string"}, 

151 {"type": "null"}, 

152 ], 

153 } 

154 ) 

155 | IsDict( 

156 # TODO: remove when deprecating Pydantic v1 

157 { 

158 "title": "Grant Type", 

159 "pattern": "password", 

160 "type": "string", 

161 } 

162 ), 

163 "username": {"title": "Username", "type": "string"}, 

164 "password": {"title": "Password", "type": "string"}, 

165 "scope": {"title": "Scope", "type": "string", "default": ""}, 

166 "client_id": IsDict( 

167 { 

168 "title": "Client Id", 

169 "anyOf": [{"type": "string"}, {"type": "null"}], 

170 } 

171 ) 

172 | IsDict( 

173 # TODO: remove when deprecating Pydantic v1 

174 {"title": "Client Id", "type": "string"} 

175 ), 

176 "client_secret": IsDict( 

177 { 

178 "title": "Client Secret", 

179 "anyOf": [{"type": "string"}, {"type": "null"}], 

180 } 

181 ) 

182 | IsDict( 

183 # TODO: remove when deprecating Pydantic v1 

184 {"title": "Client Secret", "type": "string"} 

185 ), 

186 }, 

187 }, 

188 "ValidationError": { 

189 "title": "ValidationError", 

190 "required": ["loc", "msg", "type"], 

191 "type": "object", 

192 "properties": { 

193 "loc": { 

194 "title": "Location", 

195 "type": "array", 

196 "items": { 

197 "anyOf": [{"type": "string"}, {"type": "integer"}] 

198 }, 

199 }, 

200 "msg": {"title": "Message", "type": "string"}, 

201 "type": {"title": "Error Type", "type": "string"}, 

202 }, 

203 }, 

204 "HTTPValidationError": { 

205 "title": "HTTPValidationError", 

206 "type": "object", 

207 "properties": { 

208 "detail": { 

209 "title": "Detail", 

210 "type": "array", 

211 "items": {"$ref": "#/components/schemas/ValidationError"}, 

212 } 

213 }, 

214 }, 

215 }, 

216 "securitySchemes": { 

217 "OAuth2PasswordBearer": { 

218 "type": "oauth2", 

219 "flows": {"password": {"scopes": {}, "tokenUrl": "token"}}, 

220 } 

221 }, 

222 }, 

223 }