chore: downgrade upload-artifact action from v4 to v3 in CI workflow
This commit is contained in:
+28
-1
@@ -1,4 +1,4 @@
|
||||
import os, sys, tempfile, subprocess, time
|
||||
import os, sys, tempfile, subprocess, time, asyncio, threading
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
|
||||
@@ -26,6 +26,33 @@ os.environ["DEVPLACE_DATABASE_URL"] = f"sqlite:///{_TEST_DB.name}"
|
||||
os.environ["SECRET_KEY"] = "test-secret-key"
|
||||
os.environ["DEVPLACE_DISABLE_SERVICES"] = "1"
|
||||
os.environ["DEVPLACE_RATE_LIMIT"] = "1000000"
|
||||
os.environ["DEVPLACE_SITEMAP_TTL"] = "0"
|
||||
|
||||
|
||||
def run_async(coro):
|
||||
box = {}
|
||||
|
||||
def runner():
|
||||
try:
|
||||
box["value"] = asyncio.run(coro)
|
||||
except BaseException as exc:
|
||||
box["error"] = exc
|
||||
|
||||
thread = threading.Thread(target=runner)
|
||||
thread.start()
|
||||
thread.join()
|
||||
from devplacepy.database import refresh_snapshot
|
||||
refresh_snapshot()
|
||||
if "error" in box:
|
||||
raise box["error"]
|
||||
return box["value"]
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _fresh_db_snapshot():
|
||||
from devplacepy.database import refresh_snapshot
|
||||
refresh_snapshot()
|
||||
yield
|
||||
|
||||
|
||||
def save_failure_screenshot(page, test_name):
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import asyncio
|
||||
|
||||
import httpx
|
||||
|
||||
from devplacepy.services import news as news_mod
|
||||
from devplacepy.services.news import NewsService, _extract_grade, _get_ai_key, _get_article_images
|
||||
from devplacepy.database import get_table
|
||||
from devplacepy.utils import generate_uid
|
||||
from tests.conftest import run_async
|
||||
|
||||
API_URL = "http://news.test/api"
|
||||
AI_URL = "http://ai.test/v1/chat"
|
||||
@@ -120,14 +119,14 @@ def test_get_ai_key_empty_when_unset(monkeypatch):
|
||||
|
||||
def test_grade_article_empty_content_returns_none(local_db, monkeypatch):
|
||||
monkeypatch.setattr(news_mod, "get_setting", _settings_stub())
|
||||
grade = asyncio.run(NewsService()._grade_article(
|
||||
grade = run_async(NewsService()._grade_article(
|
||||
{"title": "EmptyArticle", "description": "d", "content": "c"}, AI_URL, "m", FakeClient([])))
|
||||
assert grade is None
|
||||
|
||||
|
||||
def test_grade_article_unparseable_returns_none(local_db, monkeypatch):
|
||||
monkeypatch.setattr(news_mod, "get_setting", _settings_stub())
|
||||
grade = asyncio.run(NewsService()._grade_article(
|
||||
grade = run_async(NewsService()._grade_article(
|
||||
{"title": "BadArticle", "description": "d", "content": "c"}, AI_URL, "m", FakeClient([])))
|
||||
assert grade is None
|
||||
|
||||
@@ -135,7 +134,7 @@ def test_grade_article_unparseable_returns_none(local_db, monkeypatch):
|
||||
def test_run_once_handles_api_failure(local_db, monkeypatch):
|
||||
monkeypatch.setattr(news_mod, "get_setting", _settings_stub())
|
||||
monkeypatch.setattr(news_mod.httpx, "AsyncClient", lambda *a, **k: FailingApiClient([]))
|
||||
asyncio.run(NewsService().run_once())
|
||||
run_async(NewsService().run_once())
|
||||
|
||||
|
||||
def test_run_once_updates_existing_news_row(local_db, monkeypatch):
|
||||
@@ -150,7 +149,7 @@ def test_run_once_updates_existing_news_row(local_db, monkeypatch):
|
||||
monkeypatch.setattr(news_mod, "get_setting", _settings_stub(threshold="7"))
|
||||
monkeypatch.setattr(news_mod.httpx, "AsyncClient", lambda *a, **k: FakeClient(articles))
|
||||
|
||||
asyncio.run(NewsService().run_once())
|
||||
run_async(NewsService().run_once())
|
||||
|
||||
row = get_table("news").find_one(uid=existing_uid)
|
||||
assert row["title"] == "HighArticle"
|
||||
@@ -171,7 +170,7 @@ def test_get_article_images_filters_and_dedupes():
|
||||
return FakeResp(text=html)
|
||||
|
||||
client.get = fake_get
|
||||
images = asyncio.run(_get_article_images("http://news.test/page", client))
|
||||
images = run_async(_get_article_images("http://news.test/page", client))
|
||||
assert [img["url"] for img in images] == ["http://img.test/a.png"]
|
||||
|
||||
|
||||
@@ -182,7 +181,7 @@ def test_get_article_images_network_error_returns_empty():
|
||||
raise httpx.HTTPError("down")
|
||||
|
||||
client.get = failing_get
|
||||
assert asyncio.run(_get_article_images("http://news.test/page", client)) == []
|
||||
assert run_async(_get_article_images("http://news.test/page", client)) == []
|
||||
|
||||
|
||||
def test_run_once_publishes_grades_and_is_idempotent(local_db, monkeypatch):
|
||||
@@ -200,7 +199,7 @@ def test_run_once_publishes_grades_and_is_idempotent(local_db, monkeypatch):
|
||||
monkeypatch.setattr(news_mod, "get_setting", _settings_stub(threshold="7"))
|
||||
monkeypatch.setattr(news_mod.httpx, "AsyncClient", lambda *a, **k: FakeClient(articles))
|
||||
|
||||
asyncio.run(NewsService().run_once())
|
||||
run_async(NewsService().run_once())
|
||||
|
||||
news = get_table("news")
|
||||
sync = get_table("news_sync")
|
||||
@@ -214,6 +213,6 @@ def test_run_once_publishes_grades_and_is_idempotent(local_db, monkeypatch):
|
||||
assert sync.find_one(external_id=g_fail)["status"] == "grading_failed"
|
||||
assert sync.find_one(external_id=g_high)["status"] == "graded"
|
||||
|
||||
asyncio.run(NewsService().run_once())
|
||||
run_async(NewsService().run_once())
|
||||
assert news.count(external_id=g_high) == 1
|
||||
assert news.count(external_id=g_fail) == 1
|
||||
|
||||
+3
-2
@@ -152,11 +152,12 @@ def _seed_news():
|
||||
from devplacepy.database import get_table
|
||||
from devplacepy.utils import generate_uid, make_combined_slug
|
||||
uid = generate_uid()
|
||||
slug = make_combined_slug("SEO Test News Article", uid)
|
||||
title = f"SEO Test News Article {uid.split('-')[-1]}"
|
||||
slug = make_combined_slug(title, uid)
|
||||
get_table("news").insert({
|
||||
"uid": uid,
|
||||
"slug": slug,
|
||||
"title": "SEO Test News Article",
|
||||
"title": title,
|
||||
"description": "A seeded news article for SEO tests.",
|
||||
"content": "Body content for the seeded article.",
|
||||
"url": "https://example.com/article",
|
||||
|
||||
Reference in New Issue
Block a user