Spaces:
Running
Running
| import os | |
| import re | |
| import pytest | |
| from playwright.sync_api import sync_playwright | |
| # ββ State label β numeric ID (uppercase keys match site dropdown labels) ββββββ | |
| STATE_LABEL_TO_ID = { | |
| "ANDAMAN & NICOBAR ISLANDS": 135, | |
| "ANDHRA PRADESH": 128, | |
| "ARUNACHAL PRADESH": 112, | |
| "ASSAM": 118, | |
| "BIHAR": 110, | |
| "CHANDIGARH": 104, | |
| "CHHATTISGARH": 122, | |
| "DADRA & NAGAR HAVELI AND DAMAN & DIU": 138, | |
| "DELHI": 107, | |
| "GOA": 130, | |
| "GUJARAT": 124, | |
| "HARYANA": 106, | |
| "HIMACHAL PRADESH": 102, | |
| "IAF EC SOCIETY": 163, | |
| "JAMMU & KASHMIR": 101, | |
| "JHARKHAND": 120, | |
| "KARNATAKA": 129, | |
| "KENDRIYA VIDYALAYA SANGHATHAN": 192, | |
| "KERALA": 132, | |
| "LADAKH": 137, | |
| "LAKSHADWEEP": 131, | |
| "MADHYA PRADESH": 123, | |
| "MAHARASHTRA": 127, | |
| "MANIPUR": 114, | |
| "MEGHALAYA": 117, | |
| "MIZORAM": 115, | |
| "MSRVVP": 161, | |
| "NAGALAND": 113, | |
| "NAVODAYA VIDYALAYA SAMITI": 193, | |
| "NAVY EDUCATION SOCIETY": 162, | |
| "ODISHA": 121, | |
| "PUDUCHERRY": 134, | |
| "PUNJAB": 103, | |
| "RAJASTHAN": 108, | |
| "SIKKIM": 111, | |
| "TAMILNADU": 133, | |
| "TELANGANA": 136, | |
| "TEST STATE": 199, | |
| "TRIPURA": 116, | |
| "UTTARAKHAND": 105, | |
| "UTTAR PRADESH": 109, | |
| "WEST BENGAL": 119, | |
| } | |
| # ββ Early check for unquoted state names ββ | |
| import sys | |
| def _check_unquoted_state_args(): | |
| if "--state" in sys.argv: | |
| try: | |
| idx = sys.argv.index("--state") | |
| if idx + 1 < len(sys.argv): | |
| state_val = sys.argv[idx + 1] | |
| if idx + 2 < len(sys.argv): | |
| next_arg = sys.argv[idx + 2] | |
| # If the next argument isn't a flag, it might be an unquoted state part. | |
| if not next_arg.startswith("-"): | |
| combined = (state_val + " " + next_arg).upper() | |
| if any(combined in s for s in STATE_LABEL_TO_ID): | |
| print(f"\nERROR: It looks like you passed a multi-word state name without quotes.") | |
| print(f"Please use double quotes around the state name: --state \"{combined}\"") | |
| print(f"Valid state names are:\n " + "\n ".join(sorted(STATE_LABEL_TO_ID.keys())) + "\n") | |
| sys.exit(1) | |
| except ValueError: | |
| pass | |
| _check_unquoted_state_args() | |
| _OUTPUT_DIR = os.path.normpath( | |
| os.path.join(os.path.dirname(os.path.abspath(__file__)), "output") | |
| ) | |
| def _state_prefix(state_name: str) -> str: | |
| """'ANDAMAN & NICOBAR ISLANDS' β 'andaman_nicobar_islands'""" | |
| return re.sub(r"[^a-z0-9]+", "_", state_name.lower()).strip("_") | |
| # ββ CLI option ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def pytest_addoption(parser): | |
| parser.addoption( | |
| "--state", | |
| action="store", | |
| default="GOA", | |
| help=( | |
| "State name to scrape (case-insensitive). " | |
| "Examples: --state GOA or --state 'UTTAR PRADESH'. " | |
| "Default: GOA" | |
| ), | |
| ) | |
| # ββ State fixtures ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def state_name(request): | |
| """Validated, uppercased state name from --state CLI option.""" | |
| raw = request.config.getoption("--state").strip().upper() | |
| if raw not in STATE_LABEL_TO_ID: | |
| valid = "\n ".join(sorted(STATE_LABEL_TO_ID)) | |
| pytest.fail( | |
| f"Unknown state: '{raw}'.\n" | |
| f"Valid state names:\n {valid}" | |
| ) | |
| return raw | |
| def state_id(state_name): | |
| """Numeric state ID for the API (resolved from --state).""" | |
| return STATE_LABEL_TO_ID[state_name] | |
| def results_file(state_name): | |
| """Path to the state-specific school data JSON, e.g. output/goa_schools.json.""" | |
| os.makedirs(_OUTPUT_DIR, exist_ok=True) | |
| return os.path.join(_OUTPUT_DIR, f"{_state_prefix(state_name)}_schools.json") | |
| def id_map_file(state_name): | |
| """Path to the state-specific district/block ID map JSON.""" | |
| os.makedirs(_OUTPUT_DIR, exist_ok=True) | |
| return os.path.join(_OUTPUT_DIR, f"{_state_prefix(state_name)}_id_map.json") | |
| def district_cat_results_file(state_name): | |
| """Path to the districtΓcategory school data JSON. | |
| e.g. output/goa_schools_by_category.json | |
| """ | |
| os.makedirs(_OUTPUT_DIR, exist_ok=True) | |
| return os.path.join(_OUTPUT_DIR, f"{_state_prefix(state_name)}_schools_by_category.json") | |
| def district_id_map_file(state_name): | |
| """Path to the state-specific district-only ID map JSON (no blocks). | |
| e.g. output/goa_district_id_map.json | |
| """ | |
| os.makedirs(_OUTPUT_DIR, exist_ok=True) | |
| return os.path.join(_OUTPUT_DIR, f"{_state_prefix(state_name)}_district_id_map.json") | |
| # ββ Browser fixtures ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def browser(): | |
| """Session-scoped browser β launched once for the entire test run.""" | |
| with sync_playwright() as p: | |
| browser = p.chromium.launch(headless=True, slow_mo=200, args=["--start-minimized"]) | |
| yield browser | |
| browser.close() | |
| def page(browser): | |
| """Session-scoped page β one browser tab reused across all phases.""" | |
| context = browser.new_context(viewport={"width": 1280, "height": 900}) | |
| page = context.new_page() | |
| yield page | |
| context.close() | |