Files

120 lines
4.0 KiB
Python

"""Tests of the lecture script. A fake driver stands in for Chrome, so no browser starts."""
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from scraping_wiki import interaction
from scraping_wiki.constants import (
ARTICLE_COUNT_SELECTOR,
CHROME_BINARY_ENV,
CHROMEDRIVER_PATH_ENV,
HEADLESS_ARGUMENT,
WIKIPEDIA_MAIN_PAGE_URL,
)
class FakeElement:
def __init__(self, text: str) -> None:
self.text = text
class FakeDriver:
def __init__(self, count: str = "7,123,456") -> None:
self.count = count
self.visited: list[str] = []
self.searched: list[tuple[str, str]] = []
self.is_quit = False
def get(self, url: str) -> None:
self.visited.append(url)
def find_element(self, by: str, value: str) -> FakeElement:
self.searched.append((by, value))
return FakeElement(self.count)
def quit(self) -> None:
self.is_quit = True
class RecordingChrome:
def __init__(self, options: object, service: object) -> None:
self.options = options
self.service = service
def test_open_main_page_gets_the_wikipedia_url() -> None:
driver = FakeDriver()
interaction.open_main_page(driver) # type: ignore[arg-type]
assert driver.visited == [WIKIPEDIA_MAIN_PAGE_URL]
def test_read_article_count_uses_the_css_selector_and_returns_the_text() -> None:
driver = FakeDriver("7,000,001")
assert interaction.read_article_count(driver) == "7,000,001" # type: ignore[arg-type]
assert driver.searched == [(By.CSS_SELECTOR, ARTICLE_COUNT_SELECTOR)]
def test_main_prints_the_count_and_quits_the_driver(
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
driver = FakeDriver("6,999,999")
monkeypatch.setattr(interaction, "create_driver", lambda headless=False: driver)
assert interaction.main([]) == 0
assert capsys.readouterr().out == "6,999,999\n"
assert driver.visited == [WIKIPEDIA_MAIN_PAGE_URL]
assert driver.is_quit
def test_main_quits_the_driver_when_reading_fails(monkeypatch: pytest.MonkeyPatch) -> None:
driver = FakeDriver()
def fail(_driver: object) -> str:
raise RuntimeError("element not found")
monkeypatch.setattr(interaction, "create_driver", lambda headless=False: driver)
monkeypatch.setattr(interaction, "read_article_count", fail)
with pytest.raises(RuntimeError):
interaction.main([])
assert driver.is_quit
def test_main_passes_the_headless_flag_to_create_driver(monkeypatch: pytest.MonkeyPatch) -> None:
seen: list[bool] = []
def fake_create(headless: bool = False) -> FakeDriver:
seen.append(headless)
return FakeDriver()
monkeypatch.setattr(interaction, "create_driver", fake_create)
interaction.main(["--headless"])
interaction.main([])
assert seen == [True, False]
def test_create_driver_adds_the_headless_options_only_when_asked(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.delenv(CHROME_BINARY_ENV, raising=False)
monkeypatch.delenv(CHROMEDRIVER_PATH_ENV, raising=False)
monkeypatch.setattr(
webdriver, "Chrome", lambda options, service: RecordingChrome(options, service)
)
plain = interaction.create_driver()
headless = interaction.create_driver(headless=True)
assert HEADLESS_ARGUMENT not in plain.options.arguments # type: ignore[attr-defined]
assert HEADLESS_ARGUMENT in headless.options.arguments # type: ignore[attr-defined]
def test_create_driver_uses_the_binaries_named_in_the_environment(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setenv(CHROME_BINARY_ENV, "/usr/bin/chromium")
monkeypatch.setenv(CHROMEDRIVER_PATH_ENV, "/usr/bin/chromedriver")
monkeypatch.setattr(
webdriver, "Chrome", lambda options, service: RecordingChrome(options, service)
)
driver = interaction.create_driver()
assert driver.options.binary_location == "/usr/bin/chromium" # type: ignore[attr-defined]
assert driver.service.path == "/usr/bin/chromedriver" # type: ignore[attr-defined]