"""POST /api/internal/insta/update — Windows worker webhook.""" import os import pytest from fastapi import FastAPI from fastapi.testclient import TestClient from app.internal_router import router from app import db @pytest.fixture(autouse=True) def _set_key(monkeypatch): monkeypatch.setenv("INTERNAL_API_KEY", "test-secret") @pytest.fixture def client(tmp_path, monkeypatch): # SQLite in-memory test monkeypatch.setenv("INSTA_DATA_PATH", str(tmp_path)) db.init_db() app = FastAPI() app.include_router(router) return TestClient(app) def _make_task(): return db.create_task("slate_render", {"slate_id": 42}) def test_update_with_valid_key_updates_db(client): tid = _make_task() r = client.post( "/api/internal/insta/update", headers={"X-Internal-Key": "test-secret"}, json={"task_id": tid, "status": "processing", "progress": 30}, ) assert r.status_code == 200 task = db.get_task(tid) assert task["status"] == "processing" assert task["progress"] == 30 def test_update_with_invalid_key_returns_401(client): tid = _make_task() r = client.post( "/api/internal/insta/update", headers={"X-Internal-Key": "wrong"}, json={"task_id": tid, "status": "processing", "progress": 30}, ) assert r.status_code == 401 def test_update_succeeded_sets_result_path(client): tid = _make_task() r = client.post( "/api/internal/insta/update", headers={"X-Internal-Key": "test-secret"}, json={ "task_id": tid, "status": "succeeded", "progress": 100, "result_path": "/media/insta/42/01.png", }, ) assert r.status_code == 200 task = db.get_task(tid) assert task["status"] == "succeeded" assert task["result_id"] is not None # slate_id from input_data def test_update_failed_records_error(client): tid = _make_task() r = client.post( "/api/internal/insta/update", headers={"X-Internal-Key": "test-secret"}, json={"task_id": tid, "status": "failed", "progress": 0, "error": "Chromium crashed"}, ) assert r.status_code == 200 task = db.get_task(tid) assert task["status"] == "failed" assert "Chromium" in (task.get("error") or "") def test_succeeded_registers_card_assets(client, tmp_path, monkeypatch): """succeeded 시 워커가 쓴 PNG들을 card_assets로 등록 (cutover 후 누락된 단계).""" from app import config # FK 충족용 실제 슬레이트 sid = db.add_card_slate({"keyword": "금리", "category": "economy"}) # 워커가 PNG 10장을 쓴 디렉토리 시뮬 (CARDS_DIR/{sid}) cards_root = tmp_path / "insta_cards" sdir = cards_root / str(sid) sdir.mkdir(parents=True) for p in range(1, 11): (sdir / f"{p:02d}.png").write_bytes(b"\x89PNG\r\n\x1a\n" + b"x" * 100) monkeypatch.setattr(config, "CARDS_DIR", str(cards_root)) monkeypatch.setattr(config, "INSTA_DATA_PATH", str(tmp_path)) tid = db.create_task("slate_render", {"slate_id": sid}) r = client.post( "/api/internal/insta/update", headers={"X-Internal-Key": "test-secret"}, json={ "task_id": tid, "status": "succeeded", "progress": 100, "result_path": f"/media/insta/{sid}/01.png", }, ) assert r.status_code == 200 assets = db.list_card_assets(sid) assert len(assets) == 10 assert assets[0]["page_index"] == 1 assert assets[0]["file_path"].endswith("01.png") assert db.get_card_slate(sid)["status"] == "rendered" def test_succeeded_no_files_registers_nothing(client, tmp_path, monkeypatch): """워커 출력이 없으면(파일 미존재) 잘못된 asset 등록 금지 — 200은 유지.""" from app import config sid = db.add_card_slate({"keyword": "환율", "category": "economy"}) monkeypatch.setattr(config, "CARDS_DIR", str(tmp_path / "insta_cards")) monkeypatch.setattr(config, "INSTA_DATA_PATH", str(tmp_path)) tid = db.create_task("slate_render", {"slate_id": sid}) r = client.post( "/api/internal/insta/update", headers={"X-Internal-Key": "test-secret"}, json={"task_id": tid, "status": "succeeded", "progress": 100}, ) assert r.status_code == 200 assert db.list_card_assets(sid) == []