Some checks are pending
Test / test (push) Waiting to run
- 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
110 lines
3.1 KiB
Python
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
|