10k-viewer/tests/test_app.py
Jarian Cottingham fa7e3eb545
Some checks are pending
Test / test (push) Waiting to run
chore: polish for public release
- Real contact in SEC User-Agent (required by EDGAR)
- Fix Dockerfile cache dir (was missing, build would fail)
- Pin flask>=3.0,<4
- Harden clean_ereader to strip single-quoted attributes
- Remove unused templates (archive.html, more.html)
- Add pytest suite (10 tests) and CI workflow
2026-08-20 21:11:29 +00:00

110 lines
3.1 KiB
Python

"""Tests for the 10-K viewer Flask app."""
import sys
from pathlib import Path
import pytest
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
import app as viewer # noqa: E402
SAMPLE_SUBS = {
"filings": {
"recent": {
"form": ["10-K", "8-K", "10-Q", "10-K"],
"filingDate": ["2024-11-01", "2024-10-15", "2024-08-01", "2023-11-02"],
"primaryDocument": [
"aapl-20240928.htm",
"aapl-20241015.htm",
"aapl-20240628.htm",
"aapl-20230930.htm",
],
"accessionNumber": [
"0000320193-24-000123",
"0000320193-24-000100",
"0000320193-24-000090",
"0000320193-23-000050",
],
}
}
}
@pytest.fixture
def client():
viewer._filings_cache.clear()
viewer._tickers = None
viewer.app.config["TESTING"] = True
with viewer.app.test_client() as c:
yield c
def test_parse_filings_filters_forms():
r = viewer.parse_filings(SAMPLE_SUBS, "0000320193", {"10-K"})
assert len(r) == 2
assert all(f["form"] == "10-K" for f in r)
def test_parse_filings_builds_url_and_file():
r = viewer.parse_filings(SAMPLE_SUBS, "0000320193", {"10-K", "10-Q"})
first = r[0]
assert first["file"] == "2024-11-01_000032019324000123.html"
assert (
first["url"]
== "https://www.sec.gov/Archives/edgar/data/0000320193/000032019324000123/aapl-20240928.htm"
)
def test_parse_filings_no_matching_forms():
assert viewer.parse_filings(SAMPLE_SUBS, "0000320193", {"20-F"}) == []
def test_clean_ereader_strips_scripts_and_handlers():
html = b"<html><head><script>evil()</script></head><body><div onclick='x()' class='c' id='i'>hi</div></body></html>"
out = viewer.clean_ereader(html).decode("utf-8")
assert "<script>" not in out
assert "onclick" not in out
assert "class=" not in out
assert "id=" not in out
assert "Georgia" in out
def test_get_tickers_fallback():
viewer._tickers = None
t = viewer.get_tickers()
assert t["AAPL"]["cik"] == "0000320193"
def test_index_default_lists_companies(client):
resp = client.get("/")
assert resp.status_code == 200
assert "AAPL" in resp.get_data(as_text=True)
def test_index_search_filters(client):
resp = client.get("/?q=apple")
assert resp.status_code == 200
body = resp.get_data(as_text=True)
assert "AAPL" in body
assert "MSFT" not in body
def test_company_renders_filings(client, monkeypatch):
monkeypatch.setattr(viewer, "get_filings", lambda cik, forms: [
{"form": "10-K", "date": "2024-11-01", "file": "f1.html", "url": "https://x/f1.html"},
])
resp = client.get("/AAPL")
assert resp.status_code == 200
assert "Apple Inc." in resp.get_data(as_text=True)
assert "f1.html" in resp.get_data(as_text=True)
def test_company_unknown_ticker_404(client):
assert client.get("/NOPE").status_code == 404
def test_view_unknown_ticker_404(client):
assert client.get("/NOPE/view/f1.html").status_code == 404