"""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 "Data Cleaning Mastery" 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 "Maestría" in text, ( "after selecting Spanish, the home title should switch to " f"'🧹 DataTools — Maestría…'; 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 "Maestría" in collected_text(home_app) selector = home_app.sidebar.selectbox[0] selector.select("en").run() text = collected_text(home_app) assert "Data Cleaning Mastery" in text assert "Maestría" not in text # --------------------------------------------------------------------------- # Footer + page_title localization # --------------------------------------------------------------------------- class TestLocalizedChrome: """A spot-check on the parts of the chrome that aren't the selector: the bottom footer caption and the home-page hero text. Other strings are pinned indirectly by ``TestEveryPageRenders.test_expected_*``.""" def test_footer_english(self, home_app): home_app.run() text = collected_text(home_app) assert "Your data never leaves" in text def test_footer_spanish(self, home_app): with_language(home_app, "es") home_app.run() text = collected_text(home_app) assert "Tus datos nunca salen" in text def test_upload_section_heading_localizes(self, home_app): with_language(home_app, "es") home_app.run() text = collected_text(home_app) # ``📤 Sube uno o más archivos para empezar`` from the es pack. assert "Sube uno o más archivos" in text # --------------------------------------------------------------------------- # 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]}" )