mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 16:23:04 +02:00
- Added module docstrings to 19 Python files - Added class docstrings to 5 classes (ScreenLocker, PokerModifierApp, etc.) - Added method docstrings to 22 methods - Added function docstrings to 25 functions - Added __init__ docstrings to 5 classes - Removed D100-D107 from ruff ignore list (docstrings now enforced) - Removed deprecated ANN101, ANN102, UP038 rules from ignore list - Fixed UP038: use union types in isinstance() calls - All ruff checks now pass with full docstring enforcement
107 lines
3.0 KiB
Python
107 lines
3.0 KiB
Python
"""Integration tests for the articles C server API."""
|
|
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import socket
|
|
import subprocess
|
|
import time
|
|
import urllib.error
|
|
import urllib.request
|
|
|
|
|
|
def _req(url, method="GET", data=None):
|
|
"""Send an HTTP request and return status code and body."""
|
|
if data is not None and not isinstance(data, bytes | bytearray):
|
|
data = json.dumps(data).encode("utf-8")
|
|
req = urllib.request.Request(url, data=data, method=method)
|
|
req.add_header("Content-Type", "application/json")
|
|
with urllib.request.urlopen(req, timeout=5) as resp:
|
|
body = resp.read()
|
|
return resp.getcode(), body
|
|
|
|
|
|
def test_crud_roundtrip(tmp_path):
|
|
"""Test full CRUD lifecycle for articles API."""
|
|
# Build C server
|
|
here = Path(__file__).resolve().parent
|
|
subprocess.run(["make", "-s", "server_c"], check=True, cwd=str(here))
|
|
|
|
# Find a free port
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
s.bind(("127.0.0.1", 0))
|
|
_, port = s.getsockname()
|
|
host = "127.0.0.1"
|
|
base = f"http://{host}:{port}"
|
|
|
|
# Isolate storage and start server
|
|
env = os.environ.copy()
|
|
env["ARTICLES_DATA_DIR"] = str(tmp_path)
|
|
env["HOST"] = host
|
|
env["PORT"] = str(port)
|
|
srv = subprocess.Popen(["./server_c"], cwd=str(here), env=env)
|
|
try:
|
|
# wait briefly for server to be ready
|
|
for _ in range(30):
|
|
try:
|
|
with urllib.request.urlopen(
|
|
base + "/api/articles", timeout=0.2
|
|
) as resp:
|
|
resp.read()
|
|
break
|
|
except Exception:
|
|
time.sleep(0.05)
|
|
|
|
# Create
|
|
code, body = _req(
|
|
base + "/api/articles",
|
|
method="POST",
|
|
data={
|
|
"title": "T1",
|
|
"body": "<p>Hello</p>",
|
|
"thumb": "data:image/png;base64,xyz",
|
|
},
|
|
)
|
|
assert code == 201
|
|
created = json.loads(body)
|
|
art_id = created["id"]
|
|
|
|
# List
|
|
code, body = _req(base + "/api/articles")
|
|
assert code == 200
|
|
items = json.loads(body)
|
|
assert any(a["id"] == art_id for a in items)
|
|
|
|
# Get one
|
|
code, body = _req(base + f"/api/articles/{art_id}")
|
|
assert code == 200
|
|
got = json.loads(body)
|
|
assert got["title"] == "T1"
|
|
|
|
# Update
|
|
code, body = _req(
|
|
base + f"/api/articles/{art_id}", method="PUT", data={"title": "T2"}
|
|
)
|
|
assert code == 200
|
|
updated = json.loads(body)
|
|
assert updated["title"] == "T2"
|
|
|
|
# Delete
|
|
code, _ = _req(base + f"/api/articles/{art_id}", method="DELETE")
|
|
assert code == 204
|
|
|
|
# Ensure gone
|
|
try:
|
|
_req(base + f"/api/articles/{art_id}")
|
|
msg = "Expected 404"
|
|
raise AssertionError(msg)
|
|
except urllib.error.HTTPError as e:
|
|
assert e.code == 404
|
|
|
|
finally:
|
|
srv.terminate()
|
|
try:
|
|
srv.wait(timeout=2)
|
|
except Exception:
|
|
srv.kill()
|