"""Smoke test for the Tribal Health job board adapter. Verifies that: 1. The manifest parses and exposes required fields 2. The adapter is registered 3. (network) The board opens and either dental/ortho cards are detected OR a zero-result state is handled cleanly; any returned card matches the keyword filter NOTE: The network test requires a connection and the Chrome browser. Mark with @pytest.mark.network to allow skipping in CI. """ import pytest @pytest.fixture def tribalhealth_manifest(): from gimme_job.config import load_site_manifest try: return load_site_manifest("tribalhealth") except FileNotFoundError: pytest.skip("tribalhealth.yaml not found") def test_tribalhealth_manifest_valid(tribalhealth_manifest): """Manifest parses and has required fields.""" assert tribalhealth_manifest.site_id == "tribalhealth" assert tribalhealth_manifest.identity.base_url assert tribalhealth_manifest.identity.start_url_template assert tribalhealth_manifest.extract.container_selectors # Keyword filter must be present — the board is not keyword-searchable. assert tribalhealth_manifest.post_filters.include_title_keywords def test_tribalhealth_adapter_registered(): """TribalHealthAdapter is registered in the registry.""" from gimme_job.adapters.registry import _load_all_adapters, _REGISTRY _load_all_adapters() assert "tribalhealth" in _REGISTRY def test_tribalhealth_start_url(tribalhealth_manifest): """Start URL points at the job board.""" from gimme_job.models.dto import SearchQuery url = tribalhealth_manifest.build_start_url(SearchQuery()) assert "tribalhealth.com/job-board" in url @pytest.mark.network def test_tribalhealth_smoke(tribalhealth_manifest): """Open the board and verify cards (keyword-matched) or a clean zero-result.""" from gimme_job.adapters.tribalhealth import TribalHealthAdapter from gimme_job.runtime.browser import BrowserManager adapter = TribalHealthAdapter(tribalhealth_manifest) bm = BrowserManager(headless=True) try: bm.open_context(headless=True) page = bm.new_page() page.set_default_timeout(20000) url = tribalhealth_manifest.build_start_url( __import__("gimme_job.models.dto", fromlist=["SearchQuery"]).SearchQuery() ) page.goto(url, timeout=45000, wait_until="domcontentloaded") cards = adapter.collect_cards(page, tribalhealth_manifest) assert isinstance(cards, list), "collect_cards must return a list" keywords = [k.lower() for k in tribalhealth_manifest.post_filters.include_title_keywords] for card in cards: assert card.title and card.title.strip(), "Card must have a title" # Every returned card must satisfy the keyword filter. assert any(kw in card.title.lower() for kw in keywords), ( f"Card slipped the keyword filter: {card.title!r}" ) # At least one field beyond title. assert any([card.location, card.url, card.company]), "Card needs a second field" finally: bm.close()