"""Chrome tests — language selector, hide_streamlit_chrome, quit flow. These verify the GUI plumbing that every page depends on. Failures here cascade into every other page, so they run cheap and run first (alphabetical name ordering after smoke). """ from __future__ import annotations import pytest from .conftest import collected_text, with_language # --------------------------------------------------------------------------- # hide_streamlit_chrome mounts the selector # --------------------------------------------------------------------------- class TestHideChromeMountsSelector: """``hide_streamlit_chrome()`` is the one place the language selector is mounted. Every page that hides chrome (= every page) must get exactly one sidebar selectbox with the i18n label.""" def test_home_has_one_sidebar_selectbox(self, home_app): home_app.run() # Only one selectbox in the sidebar today; if a page adds # another, this becomes a weaker bound. assert len(home_app.sidebar.selectbox) == 1, ( "expected exactly one sidebar selectbox (the language picker); " f"got {len(home_app.sidebar.selectbox)}" ) def test_selector_label_is_localized(self, home_app): with_language(home_app, "es") home_app.run() labels = [sb.label for sb in home_app.sidebar.selectbox] assert "Idioma" in labels, ( f"Spanish selector should be labelled 'Idioma'; got {labels}" ) def test_selector_label_english_default(self, home_app): home_app.run() # no with_language → default = en labels = [sb.label for sb in home_app.sidebar.selectbox] assert "Language" in labels # --------------------------------------------------------------------------- # Language selector switches session state # --------------------------------------------------------------------------- class TestLanguageSwitch: """Picking 'es' in the selector flips ``st.session_state['ui_lang']`` and re-renders the page with Spanish strings on the next run.""" def test_default_language_is_english(self, home_app): home_app.run() # AppTest's session_state proxy doesn't implement .get(); use # membership check + attribute access. Absence == default ("en"). lang = home_app.session_state["ui_lang"] if "ui_lang" in home_app.session_state else "en" assert lang == "en" text = collected_text(home_app) assert "Clean. Normalize. Transform." in text def test_selecting_spanish_persists_in_session(self, home_app): home_app.run() selector = home_app.sidebar.selectbox[0] selector.select("es").run() assert home_app.session_state["ui_lang"] == "es" def test_selecting_spanish_re_renders_in_spanish(self, home_app): home_app.run() selector = home_app.sidebar.selectbox[0] selector.select("es").run() text = collected_text(home_app) assert "Limpia. Normaliza. Transforma." in text, ( "after selecting Spanish, the home tagline should switch to " f"'Limpia. Normaliza. Transforma.'; got:\n{text[:300]}" ) def test_selecting_back_to_english_reverts(self, home_app): # Start in Spanish, then flip back. with_language(home_app, "es") home_app.run() assert "Limpia. Normaliza. Transforma." in collected_text(home_app) selector = home_app.sidebar.selectbox[0] selector.select("en").run() text = collected_text(home_app) assert "Clean. Normalize. Transform." in text assert "Limpia. Normaliza. Transforma." not in text # --------------------------------------------------------------------------- # Footer + page_title localization # --------------------------------------------------------------------------- class TestLocalizedChrome: """A spot-check on the parts of the chrome that aren't the selector: the home-page privacy pill (visible to AppTest) and the upload section heading. The sticky footer caption is rendered via a component-iframe and isn't visible through ``collected_text``.""" def test_privacy_pill_english(self, home_app): home_app.run() text = collected_text(home_app) assert "Runs 100% locally" in text def test_privacy_pill_spanish(self, home_app): with_language(home_app, "es") home_app.run() text = collected_text(home_app) assert "Se ejecuta 100% en local" in text def test_upload_section_heading_localizes(self, home_app): with_language(home_app, "es") home_app.run() # The visible "Files" section heading is hard-coded English # in the redesigned home page; what's still localized is the # file_uploader widget's label (``upload.uploader_label_multi``). # AppTest exposes uploaders separately from the text-bearing # widget collections, so we check the uploader's label # attribute directly. labels = [u.label for u in home_app.file_uploader] assert any("Importa archivos" in lbl for lbl in labels), ( f"Spanish uploader label missing; got: {labels}" ) # --------------------------------------------------------------------------- # Quit / Close page # --------------------------------------------------------------------------- class TestClosePageShutsDownImmediately: """The Close page no longer renders a confirm button — visiting the page IS the close action. Under pytest the ``os._exit`` thread is skipped (so the test runner doesn't suicide), but the farewell success caption still renders and we assert against it.""" def test_english_close_renders_shutdown_message(self, app_factory): app = app_factory("99_Close") app.run() text = collected_text(app) assert "Shutting down" in text or "Goodbye" in text, ( f"Close page missing shutdown caption; got:\n{text[:300]}" ) # No confirm button — the page is the action. labels = [b.label for b in app.button] assert not any("Close the app" in lbl for lbl in labels), ( f"Close page should not render a confirm button; got: {labels}" ) def test_spanish_close_renders_localized_shutdown_message(self, app_factory): app = app_factory("99_Close") with_language(app, "es") app.run() text = collected_text(app) # ``quit.shutting_down`` in the es pack. assert "Cerrando" in text or "Apagando" in text or "Adiós" in text, ( f"Spanish Close page missing localized shutdown caption; got:\n{text[:300]}" )