2309e9f43a
Five-service streaming platform: auth, catalogue, streaming, ingest, thumbnailer. Includes React frontend served by nginx, NATS JetStream event bus, aiobotocore async S3, PyAV video metadata + thumbnail extraction, service-to-service JWT auth, and a full unit + e2e test suite.
105 lines
3.1 KiB
Python
105 lines
3.1 KiB
Python
import os
|
|
import time
|
|
|
|
import boto3
|
|
import httpx
|
|
import pytest
|
|
|
|
GATEWAY_URL = os.environ.get("GATEWAY_URL", "http://localhost:8080")
|
|
S3_ENDPOINT = os.environ.get("S3_ENDPOINT_URL", "http://localhost:9000")
|
|
S3_ACCESS_KEY = os.environ.get("S3_ACCESS_KEY", "minioadmin")
|
|
S3_SECRET_KEY = os.environ.get("S3_SECRET_KEY", "minioadmin")
|
|
S3_BUCKET = os.environ.get("S3_BUCKET_MEDIA", "media")
|
|
|
|
TESTDATA = os.path.join(os.path.dirname(__file__), "..", "..", "testdata")
|
|
|
|
TEST_VIDEOS = [
|
|
{
|
|
"filename": "Big_Buck_Bunny_1080_10s_30MB.mp4",
|
|
"s3_key": "media/big_buck_bunny.mp4",
|
|
"media_type": "movie",
|
|
"title": "Big Buck Bunny",
|
|
"director": "Sacha Goedegebure",
|
|
"release_year": 2008,
|
|
"is_published": True,
|
|
},
|
|
{
|
|
"filename": "Jellyfish_1080_10s_30MB.mkv",
|
|
"s3_key": "media/jellyfish.mkv",
|
|
"media_type": "movie",
|
|
"title": "Jellyfish",
|
|
"director": "Blender Foundation",
|
|
"release_year": 2015,
|
|
"is_published": True,
|
|
},
|
|
]
|
|
|
|
ADMIN_EMAIL = "e2e-admin@streamstack.test"
|
|
ADMIN_PASSWORD = "e2etestpassword"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def s3():
|
|
return boto3.client(
|
|
"s3",
|
|
endpoint_url=S3_ENDPOINT,
|
|
aws_access_key_id=S3_ACCESS_KEY,
|
|
aws_secret_access_key=S3_SECRET_KEY,
|
|
region_name="us-east-1",
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def admin_token():
|
|
with httpx.Client(base_url=GATEWAY_URL) as client:
|
|
# Register; ignore 409 if already exists from a previous run
|
|
client.post(
|
|
"/api/v1/auth/users/",
|
|
json={"email": ADMIN_EMAIL, "password": ADMIN_PASSWORD, "roles": ["admin", "viewer"]},
|
|
)
|
|
resp = client.post(
|
|
"/api/v1/auth/token",
|
|
data={"username": ADMIN_EMAIL, "password": ADMIN_PASSWORD},
|
|
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
|
)
|
|
resp.raise_for_status()
|
|
return resp.json()["access_token"]
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def seeded_media(s3, admin_token):
|
|
items = []
|
|
with httpx.Client(base_url=GATEWAY_URL) as client:
|
|
for video in TEST_VIDEOS:
|
|
local_path = os.path.join(TESTDATA, video["filename"])
|
|
s3.upload_file(local_path, S3_BUCKET, video["s3_key"])
|
|
|
|
payload = {k: v for k, v in video.items() if k != "filename"}
|
|
resp = client.post(
|
|
"/api/v1/catalogue/",
|
|
json=payload,
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
resp.raise_for_status()
|
|
items.append(resp.json())
|
|
return items
|
|
|
|
|
|
def wait_for_service(url: str, timeout: int = 60) -> None:
|
|
deadline = time.time() + timeout
|
|
while time.time() < deadline:
|
|
try:
|
|
r = httpx.get(url, timeout=5)
|
|
if r.status_code < 500:
|
|
return
|
|
except Exception:
|
|
pass
|
|
time.sleep(2)
|
|
raise RuntimeError(f"Service not ready: {url}")
|
|
|
|
|
|
def pytest_configure(config):
|
|
wait_for_service(f"{GATEWAY_URL}/api/v1/auth/health")
|
|
wait_for_service(f"{GATEWAY_URL}/api/v1/catalogue/health")
|
|
wait_for_service(f"{GATEWAY_URL}/api/v1/stream/health")
|