111 lines
3.8 KiB
Python
111 lines
3.8 KiB
Python
import unittest
|
|
from fastapi.testclient import TestClient
|
|
|
|
import main
|
|
from db import connect, create
|
|
|
|
|
|
SAMPLE_URL = "https://www.allrecipes.com/recipe/262696/cheese-omelette/"
|
|
with open("tests/sample_files/recipes/cheese-omelette.html", "r", encoding="utf-8") as f:
|
|
SAMPLE_HTML = f.read()
|
|
|
|
|
|
class TestRecipesParseFromUrlIntegrationV2(unittest.IsolatedAsyncioTestCase):
|
|
async def asyncSetUp(self):
|
|
self.conn = await connect(":memory:")
|
|
await create(self.conn)
|
|
|
|
async def override_get_db():
|
|
try:
|
|
yield self.conn
|
|
finally:
|
|
pass
|
|
|
|
main.app.dependency_overrides[main.get_db] = override_get_db
|
|
self.client = TestClient(main.app)
|
|
|
|
# Register user and create household
|
|
r = self.client.post(
|
|
"/api/v1/auth/register",
|
|
json={"email": "scrape@test.com", "password": "pw", "displayName": "Scrape"},
|
|
)
|
|
assert r.status_code == 200, r.text
|
|
token = r.json()["accessToken"]
|
|
self.headers = {"Authorization": f"Bearer {token}"}
|
|
r2 = self.client.post("/api/v1/households", headers=self.headers, json={"name": "H"})
|
|
assert r2.status_code == 200, r2.text
|
|
self.slug = r2.json()["slug"]
|
|
|
|
async def asyncTearDown(self):
|
|
await self.conn.close()
|
|
main.app.dependency_overrides.clear()
|
|
|
|
def test_parse_from_url_with_mocked_html(self):
|
|
# Monkeypatch httpx.AsyncClient.get used in scraper
|
|
import recipes.scraping as scraping
|
|
|
|
class DummyResp:
|
|
def __init__(self, status_code=200, text=""):
|
|
self.status_code = status_code
|
|
self.text = text
|
|
|
|
class DummyClient:
|
|
async def __aenter__(self):
|
|
return self
|
|
|
|
async def __aexit__(self, exc_type, exc, tb):
|
|
return False
|
|
|
|
async def get(self, url, headers=None, follow_redirects=False):
|
|
assert url == SAMPLE_URL
|
|
return DummyResp(200, SAMPLE_HTML)
|
|
|
|
orig_client = scraping.httpx.AsyncClient
|
|
scraping.httpx.AsyncClient = DummyClient
|
|
try:
|
|
r = self.client.post(
|
|
f"/api/v1/households/{self.slug}/recipes/parse-from-url",
|
|
headers=self.headers,
|
|
json={"url": SAMPLE_URL},
|
|
)
|
|
assert r.status_code == 200, r.text
|
|
data = r.json()
|
|
# Now returns RecipeCreate shape
|
|
assert "id" not in data
|
|
assert "name" in data and "omelette" in data["name"].lower()
|
|
assert isinstance(data.get("ingredients"), list)
|
|
assert isinstance(data.get("imageUrls"), list)
|
|
finally:
|
|
scraping.httpx.AsyncClient = orig_client
|
|
|
|
def test_parse_from_url_not_found(self):
|
|
import recipes.scraping as scraping
|
|
|
|
class DummyResp:
|
|
def __init__(self, status_code=404, text=""):
|
|
self.status_code = status_code
|
|
self.text = text
|
|
|
|
class DummyClient:
|
|
async def __aenter__(self):
|
|
return self
|
|
|
|
async def __aexit__(self, exc_type, exc, tb):
|
|
return False
|
|
|
|
async def get(self, url, headers=None, follow_redirects=False):
|
|
return DummyResp(404, "")
|
|
|
|
orig_client = scraping.httpx.AsyncClient
|
|
scraping.httpx.AsyncClient = DummyClient
|
|
try:
|
|
r = self.client.post(
|
|
f"/api/v1/households/{self.slug}/recipes/parse-from-url",
|
|
headers=self.headers,
|
|
json={"url": SAMPLE_URL},
|
|
)
|
|
assert r.status_code == 404, r.text
|
|
body = r.json()
|
|
assert body.get("status") == 404
|
|
finally:
|
|
scraping.httpx.AsyncClient = orig_client
|