Coverage for tests / test_tutorial / test_security / test_tutorial003.py: 100%
49 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
1import importlib 1abcd
3import pytest 1abcd
4from fastapi.testclient import TestClient 1abcd
5from inline_snapshot import snapshot 1abcd
7from ...utils import needs_py310 1abcd
10@pytest.fixture( 1abcd
11 name="client",
12 params=[
13 pytest.param("tutorial003_py310", marks=needs_py310),
14 pytest.param("tutorial003_an_py310", marks=needs_py310),
15 ],
16)
17def get_client(request: pytest.FixtureRequest): 1abcd
18 mod = importlib.import_module(f"docs_src.security.{request.param}") 1CDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?@[]^_
20 client = TestClient(mod.app) 1CDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?@[]^_
21 return client 1CDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?@[]^_
24def test_login(client: TestClient): 1abcd
25 response = client.post("/token", data={"username": "johndoe", "password": "secret"}) 2` { | } ~ abbbcb
26 assert response.status_code == 200, response.text 2` { | } ~ abbbcb
27 assert response.json() == {"access_token": "johndoe", "token_type": "bearer"} 2` { | } ~ abbbcb
30def test_login_incorrect_password(client: TestClient): 1abcd
31 response = client.post( 2dbebfbgbhbibjb
32 "/token", data={"username": "johndoe", "password": "incorrect"}
33 )
34 assert response.status_code == 400, response.text 2dbebfbgbhbibjb
35 assert response.json() == {"detail": "Incorrect username or password"} 2dbebfbgbhbibjb
38def test_login_incorrect_username(client: TestClient): 1abcd
39 response = client.post("/token", data={"username": "foo", "password": "secret"}) 2kblbmbnbobpbqbrb
40 assert response.status_code == 400, response.text 2kblbmbnbobpbqbrb
41 assert response.json() == {"detail": "Incorrect username or password"} 2kblbmbnbobpbqbrb
44def test_no_token(client: TestClient): 1abcd
45 response = client.get("/users/me") 1efghijkl
46 assert response.status_code == 401, response.text 1efghijkl
47 assert response.json() == {"detail": "Not authenticated"} 1efghijkl
48 assert response.headers["WWW-Authenticate"] == "Bearer" 1efghijkl
51def test_token(client: TestClient): 1abcd
52 response = client.get("/users/me", headers={"Authorization": "Bearer johndoe"}) 2sbtbubvbwbxbybzb
53 assert response.status_code == 200, response.text 2sbtbubvbwbxbybzb
54 assert response.json() == { 2sbtbubvbwbxbybzb
55 "username": "johndoe",
56 "full_name": "John Doe",
57 "email": "[email protected]",
58 "hashed_password": "fakehashedsecret",
59 "disabled": False,
60 }
63def test_incorrect_token(client: TestClient): 1abcd
64 response = client.get("/users/me", headers={"Authorization": "Bearer nonexistent"}) 1mnopqrst
65 assert response.status_code == 401, response.text 1mnopqrst
66 assert response.json() == {"detail": "Not authenticated"} 1mnopqrst
67 assert response.headers["WWW-Authenticate"] == "Bearer" 1mnopqrst
70def test_incorrect_token_type(client: TestClient): 1abcd
71 response = client.get( 1uvwxyzAB
72 "/users/me", headers={"Authorization": "Notexistent testtoken"}
73 )
74 assert response.status_code == 401, response.text 1uvwxyzAB
75 assert response.json() == {"detail": "Not authenticated"} 1uvwxyzAB
76 assert response.headers["WWW-Authenticate"] == "Bearer" 1uvwxyzAB
79def test_inactive_user(client: TestClient): 1abcd
80 response = client.get("/users/me", headers={"Authorization": "Bearer alice"}) 2AbBbCbDbEbFbGbHb
81 assert response.status_code == 400, response.text 2AbBbCbDbEbFbGbHb
82 assert response.json() == {"detail": "Inactive user"} 2AbBbCbDbEbFbGbHb
85def test_openapi_schema(client: TestClient): 1abcd
86 response = client.get("/openapi.json") 2IbJbKbLbMbNbObPb
87 assert response.status_code == 200, response.text 2IbJbKbLbMbNbObPb
88 assert response.json() == snapshot( 2IbJbKbLbMbNbObPb
89 {
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": {
147 "title": "Grant Type",
148 "anyOf": [
149 {"pattern": "^password$", "type": "string"},
150 {"type": "null"},
151 ],
152 },
153 "username": {"title": "Username", "type": "string"},
154 "password": {
155 "title": "Password",
156 "type": "string",
157 "format": "password",
158 },
159 "scope": {
160 "title": "Scope",
161 "type": "string",
162 "default": "",
163 },
164 "client_id": {
165 "title": "Client Id",
166 "anyOf": [{"type": "string"}, {"type": "null"}],
167 },
168 "client_secret": {
169 "title": "Client Secret",
170 "anyOf": [{"type": "string"}, {"type": "null"}],
171 "format": "password",
172 },
173 },
174 },
175 "ValidationError": {
176 "title": "ValidationError",
177 "required": ["loc", "msg", "type"],
178 "type": "object",
179 "properties": {
180 "loc": {
181 "title": "Location",
182 "type": "array",
183 "items": {
184 "anyOf": [{"type": "string"}, {"type": "integer"}]
185 },
186 },
187 "msg": {"title": "Message", "type": "string"},
188 "type": {"title": "Error Type", "type": "string"},
189 "input": {"title": "Input"},
190 "ctx": {"title": "Context", "type": "object"},
191 },
192 },
193 "HTTPValidationError": {
194 "title": "HTTPValidationError",
195 "type": "object",
196 "properties": {
197 "detail": {
198 "title": "Detail",
199 "type": "array",
200 "items": {
201 "$ref": "#/components/schemas/ValidationError"
202 },
203 }
204 },
205 },
206 },
207 "securitySchemes": {
208 "OAuth2PasswordBearer": {
209 "type": "oauth2",
210 "flows": {"password": {"scopes": {}, "tokenUrl": "token"}},
211 }
212 },
213 },
214 }
215 )