SPB Git forge
28commits 1branches 0releases
7.7 MBsize
maindefault branch
10 days agolast push
Python 66.3% TypeScript 22.7% JavaScript 8.6% HTML 1.4% CSS 0.7%
11.3 KB · 199 lines python
Raw Blame History
1"""Public aggregates, live feed, search, rankings, industries/countries, signals, sitemap — shapes, caching and graceful degradation."""2from __future__ import annotations34import pytest5import test_api_support as support67client = support.client8fixture_data = support.fixture_data910pytestmark = pytest.mark.asyncio(loop_scope="session")11V = "/api/v1"121314async def test_health(client):  # type: ignore[no-untyped-def]15    r = await client.get("/health")16    assert r.status_code == 200 and r.json()["db"] is True17    assert (await client.get(f"{V}/health")).status_code == 200181920async def test_stats_shape_and_cache_headers(client):  # type: ignore[no-untyped-def]21    r = await client.get(f"{V}/stats")22    assert r.status_code == 20023    body = r.json()24    for key in ("companies", "companies_active", "sensors", "sensors_active", "observations", "snapshots", "changes", "meaningful_changes", "events", "jobs_open",25                "countries", "industries", "observations_today", "changes_today", "events_today", "dataset_started_at", "dataset_age_days", "oldest_history_days",26                "last_observation_at", "archive"):27        assert key in body, key28    assert body["companies"] >= 2 and body["events"] >= 429    assert set(body["archive"]) == {"objects", "bytes"}30    assert r.headers["cache-control"].startswith("public, max-age=60")31    assert r.headers["etag"].startswith('W/"')32    r2 = await client.get(f"{V}/stats", headers={"If-None-Match": r.headers["etag"]})33    assert r2.status_code == 304343536async def test_stats_history_and_index(client):  # type: ignore[no-untyped-def]37    r = await client.get(f"{V}/stats/history?days=30")38    assert r.status_code == 200 and isinstance(r.json()["items"], list)39    r = await client.get(f"{V}/index")40    body = r.json()41    assert r.status_code == 20042    for key in ("value", "baseline", "delta_7d", "delta_30d", "series", "by_type", "by_country", "by_industry", "formula_version"):43        assert key in body44    assert body["baseline"] == 100454647async def test_system(client):  # type: ignore[no-untyped-def]48    r = await client.get(f"{V}/system")49    assert r.status_code == 20050    body = r.json()51    for key in ("sensors_online", "sensors_failing", "observations_today", "events_today", "countries_covered", "queue_lag_s", "scheduler_last_tick_at", "fetch_per_min",52                "success_rate_24h"):53        assert key in body54    assert body["sensors_online"] >= 3555657async def test_pulse_full_shape(client, fixture_data):  # type: ignore[no-untyped-def]58    r = await client.get(f"{V}/pulse")59    assert r.status_code == 20060    body = r.json()61    for key in ("stats", "live", "movers", "hiring", "launches", "pricing", "ai", "industries", "countries", "trending", "activity_index", "map"):62        assert key in body, key63    assert any(e["id"] == fixture_data["ev_pricing"] for e in body["pricing"])64    assert any(c["slug"] == fixture_data["alpha_slug"] for c in body["movers"])65    mover = next(c for c in body["movers"] if c["slug"] == fixture_data["alpha_slug"])66    assert mover["rank"] >= 1 and mover["value"] == 72.3 and "sparkline" in mover67    assert set(body["activity_index"]) == {"value", "delta_7d", "series"}68    assert any(b["country"] == "ZZ" for b in body["map"])697071async def test_methodology(client):  # type: ignore[no-untyped-def]72    body = (await client.get(f"{V}/methodology")).json()73    assert {m["metric"] for m in body["metrics"]} >= {"activity_score", "hiring_momentum_30d", "ai_adoption", "corporate_change_index"}74    assert "PRICING" in body["event_types"] and "significance_bands" in body and body["confidence_labels"][0]["label"] == "VERIFIED"757677async def test_live_and_since(client, fixture_data):  # type: ignore[no-untyped-def]78    r = await client.get(f"{V}/live?limit=10&country=ZZ")79    assert r.status_code == 200 and r.headers["cache-control"] == "no-store"80    body = r.json()81    ids = [e["id"] for e in body["items"]]82    assert fixture_data["ev_pricing"] in ids and fixture_data["ev_retracted"] not in ids83    ev = body["items"][0]84    for key in ("id", "company", "event_type", "event_subtype", "importance", "confidence", "confidence_label", "title", "payload", "entities", "tags", "detected_at",85                "source_url", "origin", "status"):86        assert key in ev87    assert set(ev["company"]) == {"id", "slug", "display_name", "canonical_domain", "country", "logo_url"}88    assert ev["detected_at"].endswith("Z")89    r = await client.get(f"{V}/live", params={"since": body["cursor"], "country": "ZZ"})90    assert r.status_code == 200 and r.json()["items"] == []91    r = await client.get(f"{V}/live", params={"event_type": "PRICING", "min_importance": 0.7, "country": "ZZ"})92    assert all(e["event_type"] == "PRICING" for e in r.json()["items"]) and r.json()["items"]93    assert (await client.get(f"{V}/live?since=not-a-date")).status_code == 422949596async def test_live_stream_first_bytes(client):  # type: ignore[no-untyped-def]97    r = await client.get(f"{V}/live/stream?max_s=1")98    assert r.status_code == 20099    assert r.headers["content-type"].startswith("text/event-stream")100    assert r.headers.get("x-accel-buffering") == "no" and r.headers["cache-control"] == "no-store, no-transform"101    assert "event: heartbeat" in r.text and '"cursor"' in r.text and "event: end" in r.text102103104async def test_rankings(client, fixture_data):  # type: ignore[no-untyped-def]105    r = await client.get(f"{V}/rankings?kind=most_active&window=7d&country=ZZ")106    assert r.status_code == 200 and r.headers["cache-control"].startswith("public, max-age=120")107    body = r.json()108    assert body["kind"] == "most_active" and body["window"] == "7d"109    slugs = [i["slug"] for i in body["items"]]110    assert slugs[:2] == [fixture_data["alpha_slug"], fixture_data["beta_slug"]]111    top = body["items"][0]112    assert top["rank"] == 1 and top["value"] == 72.3 and "delta" in top113    r = await client.get(f"{V}/rankings?kind=hiring_decline&window=30d&country=ZZ")114    assert [i["slug"] for i in r.json()["items"]] == [fixture_data["beta_slug"]]115    r = await client.get(f"{V}/rankings?kind=pricing_changes&window=7d")116    assert any(i["slug"] == fixture_data["alpha_slug"] and i["value"] == 1 for i in r.json()["items"])117    assert (await client.get(f"{V}/rankings?kind=bogus")).status_code == 422118119120async def test_industries(client, fixture_data):  # type: ignore[no-untyped-def]121    r = await client.get(f"{V}/industries")122    assert r.status_code == 200123    row = next(i for i in r.json()["items"] if i["slug"] == fixture_data["industry"])124    for key in ("slug", "name", "parent_slug", "companies", "events_7d", "events_30d", "hiring_momentum_30d", "activity_score", "ai_adoption", "top_event_types"):125        assert key in row126    assert row["companies"] == 2 and row["events_30d"] == 4 and row["activity_score"] == 51.2 and "PRICING" in row["top_event_types"]127    r = await client.get(f"{V}/industries/{fixture_data['industry']}")128    body = r.json()129    assert r.status_code == 200130    for key in ("description", "companies", "events", "hiring", "series", "countries", "trending"):131        assert key in body132    assert body["hiring"]["open"] == 2 and body["countries"][0] == {"country": "ZZ", "companies": 2}133    assert len(body["series"]) == 10 and body["companies"][0]["slug"] == fixture_data["alpha_slug"]134    assert (await client.get(f"{V}/industries/does-not-exist")).status_code == 404135136137async def test_countries(client, fixture_data):  # type: ignore[no-untyped-def]138    r = await client.get(f"{V}/countries")139    row = next(c for c in r.json()["items"] if c["code"] == "ZZ")140    for key in ("code", "name", "region", "companies", "events_7d", "events_30d", "hiring_momentum_30d", "activity_score", "industry_mix", "lat", "lon"):141        assert key in row142    assert row["companies"] == 2 and row["industry_mix"][0]["industry"] == fixture_data["industry"] and row["slug"] == "ztestland"143    for key in ("ZZ", "zz", "ztestland"):144        r = await client.get(f"{V}/countries/{key}")145        assert r.status_code == 200, key146    body = r.json()147    for key in ("companies", "events", "movers", "new_entrants", "series", "industries"):148        assert key in body149    assert body["movers"][0]["slug"] == fixture_data["alpha_slug"] and len(body["new_entrants"]) == 2150    assert (await client.get(f"{V}/countries/atlantis")).status_code == 404151152153async def test_signals_trends_map(client, fixture_data):  # type: ignore[no-untyped-def]154    r = await client.get(f"{V}/signals?scope=company&company={fixture_data['alpha_slug']}")155    items = r.json()["items"]156    assert r.status_code == 200 and items[0]["kind"] == "hiring_surge" and items[0]["company"]["slug"] == fixture_data["alpha_slug"]157    r = await client.get(f"{V}/trends?window=30d")158    assert r.status_code == 200 and isinstance(r.json()["items"], list)159    r = await client.get(f"{V}/map?metric=companies")160    assert r.status_code == 200161    buckets = r.json()["buckets"]162    zz = [b for b in buckets if b["country"] == "ZZ"]163    assert zz and {"lat", "lon", "country", "city", "companies", "events_30d", "jobs_open", "top"} <= set(zz[0])164    assert any(b["city"] == "Testville" and b["jobs_open"] == 2 for b in zz)165166167async def test_search_suggest_ask(client, fixture_data):  # type: ignore[no-untyped-def]168    r = await client.get(f"{V}/search", params={"q": f"ztest alpha {fixture_data['suffix']}"})169    body = r.json()170    assert r.status_code == 200 and body["companies"][0]["slug"] == fixture_data["alpha_slug"] and "took_ms" in body171    assert any(e["id"] == fixture_data["ev_pricing"] for e in (await client.get(f"{V}/search", params={"q": "starter price increased", "types": "events"})).json()["events"])172    people = (await client.get(f"{V}/search", params={"q": "jane ztest", "types": "people"})).json()["people"]173    assert people and people[0]["company"]["slug"] == fixture_data["alpha_slug"]174    r = await client.get(f"{V}/search", params={"q": f"alphaz {fixture_data['suffix']}"})     # alias175    assert r.json()["companies"][0]["slug"] == fixture_data["alpha_slug"]176    assert (await client.get(f"{V}/search", params={"q": "zt"})).status_code == 200177    r = await client.get(f"{V}/search/suggest", params={"q": "ztest al"})178    items = r.json()["items"]179    assert r.status_code == 200 and len(items) <= 10 and items[0]["kind"] == "company" and items[0]["href"].startswith("/company/")180    assert any(i["kind"] == "event_type" for i in (await client.get(f"{V}/search/suggest", params={"q": "pric"})).json()["items"])181    r = await client.get(f"{V}/ask", params={"q": "pricing changes in Ztestland this week"})182    body = r.json()183    assert r.status_code == 200184    for key in ("interpretation", "answer", "companies", "events", "sources"):185        assert key in body186    assert any(e["id"] == fixture_data["ev_pricing"] for e in body["events"]) and body["sources"]187    assert "fired" not in body["answer"].lower()188189190async def test_sitemap(client, fixture_data):  # type: ignore[no-untyped-def]191    r = await client.get(f"{V}/sitemap?kind=companies")192    body = r.json()193    assert r.status_code == 200 and body["pages"] >= 1194    slugs = {i["slug"] for i in body["items"]}195    assert fixture_data["alpha_slug"] in slugs          # indexed = true196    assert fixture_data["beta_slug"] not in slugs       # 1 sensor < seo_min_sensors197    assert fixture_data["industry"] in {i["slug"] for i in (await client.get(f"{V}/sitemap?kind=industries")).json()["items"]}198    assert "ztestland" in {i["slug"] for i in (await client.get(f"{V}/sitemap?kind=countries")).json()["items"]}199