| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- import asyncio
- import os
- import subprocess
- import warnings
- from datetime import date, timedelta
- from importlib.resources import files
- from pathlib import Path
- import pytest
- from room_cal._utils import data_home as _data_home
- from room_cal.service_api.types import ServiceAuthError
- def _ts_dir() -> Path:
- return Path(str(files('room_cal.service_api').joinpath('typescript')))
- def _browsers_path() -> Path:
- return _data_home() / '.playwright-browsers'
- def _npm_env() -> dict:
- env = os.environ.copy()
- env.setdefault('ROOM_CAL_DATA_HOME', str(_data_home()))
- env['PLAYWRIGHT_BROWSERS_PATH'] = str(_browsers_path())
- return env
- def _npm_run(script: str, timeout: int, extra_env: dict | None = None) -> subprocess.CompletedProcess:
- ts_dir = _ts_dir()
- if not (ts_dir / 'node_modules').exists():
- subprocess.run(['npm', 'install'], cwd=ts_dir, check=True, capture_output=True)
- env = _npm_env()
- if extra_env:
- env.update(extra_env)
- try:
- return subprocess.run(
- ['npm', 'run', script],
- cwd=ts_dir,
- env=env,
- capture_output=True,
- text=True,
- timeout=timeout,
- )
- except subprocess.TimeoutExpired as exc:
- pytest.fail(f'npm run {script} timed out after {exc.timeout}s')
- except Exception as exc:
- pytest.fail(f'Failed to launch npm run {script}: {exc}')
- @pytest.fixture(scope='session')
- def chrome_installed():
- result = _npm_run('install-browsers', timeout=30)
- if result.returncode != 0:
- pytest.fail(
- f'npm run install-browsers failed (exit {result.returncode})\n'
- f'stdout:\n{result.stdout}\nstderr:\n{result.stderr}'
- )
- browsers = _browsers_path()
- chromium_dirs = [p for p in browsers.iterdir() if p.is_dir() and 'chromium' in p.name] if browsers.exists() else []
- if not chromium_dirs:
- pytest.fail(f'install-browsers exited 0 but no chromium dirs found in {browsers}')
- def test_install_chrome(chrome_installed):
- """npm run install-browsers puts Chromium binaries in the expected location."""
- def test_refresh_cookies_headless(chrome_installed):
- """Cookie-refresh machinery: Chromium must launch and write cookies.
- Pass — cookies updated and API call succeeds.
- Pass + warn — script ran correctly but session is stale (exit 2), cookies
- unchanged, or API auth failed after writing cookies.
- Fail — unexpected error or non-zero exit.
- """
- data = _data_home()
- airbnb_env = data / 'airbnb.env'
- booking_env = data / 'booking.env'
- before = {p: p.read_text() if p.exists() else None for p in (airbnb_env, booking_env)}
- result = _npm_run('refresh-all', timeout=60, extra_env={'HEADLESS': '1'})
- output = f'stdout:\n{result.stdout}\nstderr:\n{result.stderr}'
- if result.returncode == 2:
- warnings.warn(
- 'Session is stale — run `refresh-creds` to re-authenticate.\n' + output,
- UserWarning,
- stacklevel=1,
- )
- return
- if result.returncode != 0:
- pytest.fail(f'npm run refresh-all exited {result.returncode}\n' + output)
- after = {p: p.read_text() if p.exists() else None for p in (airbnb_env, booking_env)}
- if not any(after[p] != before[p] for p in (airbnb_env, booking_env)):
- warnings.warn(
- 'refresh-all exited 0 but neither airbnb.env nor booking.env changed.',
- UserWarning,
- stacklevel=1,
- )
- return
- try:
- from room_cal.service_api import ServiceAPI
- api = ServiceAPI()
- asyncio.run(api.get_prices(date.today() + timedelta(days=1)))
- except ServiceAuthError as exc:
- warnings.warn(
- f'Cookies were updated but API auth failed ({exc}); session may be invalid.',
- UserWarning,
- stacklevel=1,
- )
|