1import importlib
2from pathlib import Path
3
4import pytest
5from fastapi.testclient import TestClient
6
7openapi_schema = {
8    "openapi": "3.0.2",
9    "info": {"title": "FastAPI", "version": "0.1.0"},
10    "paths": {
11        "/users/": {
12            "get": {
13                "responses": {
14                    "200": {
15                        "description": "Successful Response",
16                        "content": {
17                            "application/json": {
18                                "schema": {
19                                    "title": "Response Read Users Users  Get",
20                                    "type": "array",
21                                    "items": {"$ref": "#/components/schemas/User"},
22                                }
23                            }
24                        },
25                    },
26                    "422": {
27                        "description": "Validation Error",
28                        "content": {
29                            "application/json": {
30                                "schema": {
31                                    "$ref": "#/components/schemas/HTTPValidationError"
32                                }
33                            }
34                        },
35                    },
36                },
37                "summary": "Read Users",
38                "operationId": "read_users_users__get",
39                "parameters": [
40                    {
41                        "required": False,
42                        "schema": {"title": "Skip", "type": "integer", "default": 0},
43                        "name": "skip",
44                        "in": "query",
45                    },
46                    {
47                        "required": False,
48                        "schema": {"title": "Limit", "type": "integer", "default": 100},
49                        "name": "limit",
50                        "in": "query",
51                    },
52                ],
53            },
54            "post": {
55                "responses": {
56                    "200": {
57                        "description": "Successful Response",
58                        "content": {
59                            "application/json": {
60                                "schema": {"$ref": "#/components/schemas/User"}
61                            }
62                        },
63                    },
64                    "422": {
65                        "description": "Validation Error",
66                        "content": {
67                            "application/json": {
68                                "schema": {
69                                    "$ref": "#/components/schemas/HTTPValidationError"
70                                }
71                            }
72                        },
73                    },
74                },
75                "summary": "Create User",
76                "operationId": "create_user_users__post",
77                "requestBody": {
78                    "content": {
79                        "application/json": {
80                            "schema": {"$ref": "#/components/schemas/UserCreate"}
81                        }
82                    },
83                    "required": True,
84                },
85            },
86        },
87        "/users/{user_id}": {
88            "get": {
89                "responses": {
90                    "200": {
91                        "description": "Successful Response",
92                        "content": {
93                            "application/json": {
94                                "schema": {"$ref": "#/components/schemas/User"}
95                            }
96                        },
97                    },
98                    "422": {
99                        "description": "Validation Error",
100                        "content": {
101                            "application/json": {
102                                "schema": {
103                                    "$ref": "#/components/schemas/HTTPValidationError"
104                                }
105                            }
106                        },
107                    },
108                },
109                "summary": "Read User",
110                "operationId": "read_user_users__user_id__get",
111                "parameters": [
112                    {
113                        "required": True,
114                        "schema": {"title": "User Id", "type": "integer"},
115                        "name": "user_id",
116                        "in": "path",
117                    }
118                ],
119            }
120        },
121        "/users/{user_id}/items/": {
122            "post": {
123                "responses": {
124                    "200": {
125                        "description": "Successful Response",
126                        "content": {
127                            "application/json": {
128                                "schema": {"$ref": "#/components/schemas/Item"}
129                            }
130                        },
131                    },
132                    "422": {
133                        "description": "Validation Error",
134                        "content": {
135                            "application/json": {
136                                "schema": {
137                                    "$ref": "#/components/schemas/HTTPValidationError"
138                                }
139                            }
140                        },
141                    },
142                },
143                "summary": "Create Item For User",
144                "operationId": "create_item_for_user_users__user_id__items__post",
145                "parameters": [
146                    {
147                        "required": True,
148                        "schema": {"title": "User Id", "type": "integer"},
149                        "name": "user_id",
150                        "in": "path",
151                    }
152                ],
153                "requestBody": {
154                    "content": {
155                        "application/json": {
156                            "schema": {"$ref": "#/components/schemas/ItemCreate"}
157                        }
158                    },
159                    "required": True,
160                },
161            }
162        },
163        "/items/": {
164            "get": {
165                "responses": {
166                    "200": {
167                        "description": "Successful Response",
168                        "content": {
169                            "application/json": {
170                                "schema": {
171                                    "title": "Response Read Items Items  Get",
172                                    "type": "array",
173                                    "items": {"$ref": "#/components/schemas/Item"},
174                                }
175                            }
176                        },
177                    },
178                    "422": {
179                        "description": "Validation Error",
180                        "content": {
181                            "application/json": {
182                                "schema": {
183                                    "$ref": "#/components/schemas/HTTPValidationError"
184                                }
185                            }
186                        },
187                    },
188                },
189                "summary": "Read Items",
190                "operationId": "read_items_items__get",
191                "parameters": [
192                    {
193                        "required": False,
194                        "schema": {"title": "Skip", "type": "integer", "default": 0},
195                        "name": "skip",
196                        "in": "query",
197                    },
198                    {
199                        "required": False,
200                        "schema": {"title": "Limit", "type": "integer", "default": 100},
201                        "name": "limit",
202                        "in": "query",
203                    },
204                ],
205            }
206        },
207    },
208    "components": {
209        "schemas": {
210            "ItemCreate": {
211                "title": "ItemCreate",
212                "required": ["title"],
213                "type": "object",
214                "properties": {
215                    "title": {"title": "Title", "type": "string"},
216                    "description": {"title": "Description", "type": "string"},
217                },
218            },
219            "Item": {
220                "title": "Item",
221                "required": ["title", "id", "owner_id"],
222                "type": "object",
223                "properties": {
224                    "title": {"title": "Title", "type": "string"},
225                    "description": {"title": "Description", "type": "string"},
226                    "id": {"title": "Id", "type": "integer"},
227                    "owner_id": {"title": "Owner Id", "type": "integer"},
228                },
229            },
230            "User": {
231                "title": "User",
232                "required": ["email", "id", "is_active"],
233                "type": "object",
234                "properties": {
235                    "email": {"title": "Email", "type": "string"},
236                    "id": {"title": "Id", "type": "integer"},
237                    "is_active": {"title": "Is Active", "type": "boolean"},
238                    "items": {
239                        "title": "Items",
240                        "type": "array",
241                        "items": {"$ref": "#/components/schemas/Item"},
242                        "default": [],
243                    },
244                },
245            },
246            "UserCreate": {
247                "title": "UserCreate",
248                "required": ["email", "password"],
249                "type": "object",
250                "properties": {
251                    "email": {"title": "Email", "type": "string"},
252                    "password": {"title": "Password", "type": "string"},
253                },
254            },
255            "ValidationError": {
256                "title": "ValidationError",
257                "required": ["loc", "msg", "type"],
258                "type": "object",
259                "properties": {
260                    "loc": {
261                        "title": "Location",
262                        "type": "array",
263                        "items": {"type": "string"},
264                    },
265                    "msg": {"title": "Message", "type": "string"},
266                    "type": {"title": "Error Type", "type": "string"},
267                },
268            },
269            "HTTPValidationError": {
270                "title": "HTTPValidationError",
271                "type": "object",
272                "properties": {
273                    "detail": {
274                        "title": "Detail",
275                        "type": "array",
276                        "items": {"$ref": "#/components/schemas/ValidationError"},
277                    }
278                },
279            },
280        }
281    },
282}
283
284
285@pytest.fixture(scope="module")
286def client():
287    test_db = Path("./sql_app.db")
288    if test_db.is_file():  # pragma: nocover
289        test_db.unlink()
290    # Import while creating the client to create the DB after starting the test session
291    from docs_src.sql_databases.sql_app import alt_main
292
293    # Ensure import side effects are re-executed
294    importlib.reload(alt_main)
295
296    with TestClient(alt_main.app) as c:
297        yield c
298    if test_db.is_file():  # pragma: nocover
299        test_db.unlink()
300
301
302def test_openapi_schema(client):
303    response = client.get("/openapi.json")
304    assert response.status_code == 200, response.text
305    assert response.json() == openapi_schema
306
307
308def test_create_user(client):
309    test_user = {"email": "johndoe@example.com", "password": "secret"}
310    response = client.post("/users/", json=test_user)
311    assert response.status_code == 200, response.text
312    data = response.json()
313    assert test_user["email"] == data["email"]
314    assert "id" in data
315    response = client.post("/users/", json=test_user)
316    assert response.status_code == 400, response.text
317
318
319def test_get_user(client):
320    response = client.get("/users/1")
321    assert response.status_code == 200, response.text
322    data = response.json()
323    assert "email" in data
324    assert "id" in data
325
326
327def test_inexistent_user(client):
328    response = client.get("/users/999")
329    assert response.status_code == 404, response.text
330
331
332def test_get_users(client):
333    response = client.get("/users/")
334    assert response.status_code == 200, response.text
335    data = response.json()
336    assert "email" in data[0]
337    assert "id" in data[0]
338
339
340def test_create_item(client):
341    item = {"title": "Foo", "description": "Something that fights"}
342    response = client.post("/users/1/items/", json=item)
343    assert response.status_code == 200, response.text
344    item_data = response.json()
345    assert item["title"] == item_data["title"]
346    assert item["description"] == item_data["description"]
347    assert "id" in item_data
348    assert "owner_id" in item_data
349    response = client.get("/users/1")
350    assert response.status_code == 200, response.text
351    user_data = response.json()
352    item_to_check = [it for it in user_data["items"] if it["id"] == item_data["id"]][0]
353    assert item_to_check["title"] == item["title"]
354    assert item_to_check["description"] == item["description"]
355    response = client.get("/users/1")
356    assert response.status_code == 200, response.text
357    user_data = response.json()
358    item_to_check = [it for it in user_data["items"] if it["id"] == item_data["id"]][0]
359    assert item_to_check["title"] == item["title"]
360    assert item_to_check["description"] == item["description"]
361
362
363def test_read_items(client):
364    response = client.get("/items/")
365    assert response.status_code == 200, response.text
366    data = response.json()
367    assert data
368    first_item = data[0]
369    assert "title" in first_item
370    assert "description" in first_item
371