File size: 4,632 Bytes
d27b187
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"""Headless render test for the Streamlit UI.

Uses streamlit.testing.v1.AppTest to actually EXECUTE ui/app.py (not just boot the
server), including the satellite panel and the weather block, and asserts no
exception is raised. This catches version-sensitive widget signatures (e.g.
st.image keyword args) that an HTTP-200 check on the static shell would miss.

Requires the network (NASA/Open-Meteo) for the satellite/weather paths; run when
online. The API server need not be running — the UI falls back to the in-process
engine.

Run:  python tests/test_ui_render.py
"""
from __future__ import annotations

import os
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
os.environ.setdefault("AGROSENSE_EMBEDDING_BACKEND", "hashing")

from streamlit.testing.v1 import AppTest

APP = str(Path(__file__).resolve().parent.parent / "ui" / "app.py")


def main() -> int:
    at = AppTest.from_file(APP, default_timeout=120).run()
    assert not at.exception, f"initial render raised: {at.exception}"
    # Top-bar tickers: news + the slow-scroll commodities ticker (Gold/Silver/etc.).
    md0 = " ".join((m.value or "") for m in at.markdown)
    assert "Commodities" in md0 and "Gold" in md0, "commodities ticker did not render"
    print("PASS initial render + commodities ticker")

    # Setting a location enables the satellite checkbox AND drives the top-bar
    # local-weather strip (rendered below the news ticker).
    at.text_input[0].set_value("Belagavi").run()
    assert not at.exception, f"after location: {at.exception}"
    assert at.checkbox, "expected a satellite checkbox"
    md = " ".join((m.value or "") for m in at.markdown)
    assert "🌤️" in md and "°C" in md, "local weather strip did not render"
    print("PASS location set + weather strip")

    # Ticking it executes get_satellite() + render_satellite() (st.image/metric/columns).
    at.checkbox[0].set_value(True).run()
    assert not at.exception, f"satellite panel raised: {at.exception}"
    print("PASS satellite panel rendered")

    # The decision-advisories checkbox executes get_advisories() + render_advisories()
    # (st.error/warning/info + st.image) over the fused weather+satellite signals.
    at.checkbox[1].set_value(True).run()
    assert not at.exception, f"advisories panel raised: {at.exception}"
    print("PASS advisories panel rendered")

    # The environment checkbox executes get_environment() + render_environment()
    # (st.metric, st.columns) over the live Open-Meteo profile.
    at.checkbox[2].set_value(True).run()
    assert not at.exception, f"environment panel raised: {at.exception}"
    print("PASS environment panel rendered")

    # The planetary checkbox executes get_planetary() + render_planetary()
    # (st.markdown + st.dataframe) over the locally-computed ephemeris.
    at.checkbox[3].set_value(True).run()
    assert not at.exception, f"planetary panel raised: {at.exception}"
    print("PASS planetary panel rendered")

    # The hazards checkbox executes get_hazards() + render_hazards() (NASA EONET/FIRMS).
    at.checkbox[4].set_value(True).run()
    assert not at.exception, f"hazards panel raised: {at.exception}"
    print("PASS hazards panel rendered")

    # A query exercises the answer + weather block render path.
    at.chat_input[0].set_value("paddy disease control").run()
    assert not at.exception, f"query render raised: {at.exception}"
    print("PASS query + weather render")

    # The NDVI-populated branch (st.line_chart) is credential-gated, so the run
    # above only hits the "not configured" caption. Verify that exact widget
    # signature works in this Streamlit version, with no creds needed.
    chart = AppTest.from_string(
        'import streamlit as st\n'
        'st.line_chart({"date": ["2026-05-01", "2026-05-20"], "NDVI": [0.52, 0.71]}, '
        'x="date", y="NDVI")\n',
        default_timeout=60,
    ).run()
    assert not chart.exception, f"st.line_chart signature failed: {chart.exception}"
    print("PASS NDVI line_chart signature")

    # The market-prices render path (st.dataframe) is key-gated; verify its
    # signature in this Streamlit version without a data.gov.in key.
    table = AppTest.from_string(
        'import streamlit as st\n'
        'st.dataframe([{"Market": "Hubli", "Modal": 1500}], hide_index=True)\n',
        default_timeout=60,
    ).run()
    assert not table.exception, f"st.dataframe signature failed: {table.exception}"
    print("PASS prices dataframe signature")

    print("\nUI RENDER OK")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())