"""
Tests for `chives.browser_fixtures`.
"""

import os
from pathlib import Path
import subprocess

from playwright.sync_api import sync_playwright
import pytest
from pytest import Pytester


git_root_cmd = ["git", "rev-parse", "--show-toplevel"]
GIT_ROOT = subprocess.check_output(git_root_cmd, text=True).strip()


@pytest.fixture(scope="session")
def playwright_browsers_path() -> str:
    """
    Return the cache directory where Playwright browsers are installed.
    """
    with sync_playwright() as p:
        # In my local builds, this returns a path like:
        #
        #    ~/Library/Caches/ms-playwright/webkit-2272/pw_run.sh
        #
        # Unwrap two levels to get to the `ms-playwright` folder.
        return str(Path(p.webkit.executable_path).parent.parent)


@pytest.fixture
def playwright_pytester(pytester: Pytester, playwright_browsers_path: str) -> Pytester:
    """
    Return a `Pytester` instance for which tests have access to the
    `browser` and `page` fixtures, and which use the shared Playwright cache.
    """
    if "SKIP_PLAYWRIGHT" in os.environ:  # pragma: no cover
        pytest.skip(reason="skip slow Playwright tests")

    pytester.makeconftest(f"""
        import os
        
        from chives.browser_fixtures import browser, page
        
        os.environ["PLAYWRIGHT_BROWSERS_PATH"] = {playwright_browsers_path!r}
    """)

    return pytester


class TestBrowserFixture:
    """
    Tests for the `browser` fixture.
    """

    def test_browser_fixture(self, playwright_pytester: Pytester) -> None:
        """
        Test the browser fixture.
        """
        playwright_pytester.makefile(".html", greeting="<p>Hello world!</p>")
        playwright_pytester.makepyfile(
            """
            from playwright.sync_api import Browser, expect
            from chives.browser_fixtures import file_uri

        
            def test_browser(browser: Browser) -> None:
                uri = file_uri("greeting.html")

                p = browser.new_page()
                p.goto(uri)
                expect(p.get_by_text("Hello world!")).to_be_visible()
            """
        )
        playwright_pytester.runpytest().assert_outcomes(passed=1)


class TestPageFixture:
    """
    Tests for the `page` fixture.
    """

    def test_okay_page(self, playwright_pytester: Pytester) -> None:
        """
        Open a page and make a successful assertion about the contents.
        """
        playwright_pytester.makefile(".html", greeting="<p>Hello world!</p>")
        playwright_pytester.makepyfile(
            """
            from playwright.sync_api import Page, expect
            from chives.browser_fixtures import file_uri

        
            def test_page(page: Page) -> None:
                uri = file_uri("greeting.html")
                page.goto(uri)
                expect(page.get_by_text("Hello world!")).to_be_visible()
            """
        )
        playwright_pytester.runpytest().assert_outcomes(passed=1)

    @pytest.mark.parametrize(
        "html",
        [
            pytest.param("<script>invalid</script>", id="invalid_js"),
            pytest.param("<script>console.warn('BOOM')</script>", id="console_warning"),
            pytest.param("<script>console.warn('BOOM')</script>", id="console_error"),
            pytest.param("<img src='doesnotexist.jpg'>", id="missing_image"),
        ],
    )
    def test_page_with_error(self, html: str, playwright_pytester: Pytester) -> None:
        """
        Open a page with errors/warnings, and check the fixture reports
        an error.
        """
        playwright_pytester.makefile(".html", error=html)
        playwright_pytester.makepyfile(
            """
            from playwright.sync_api import Page
            from chives.browser_fixtures import file_uri

        
            def test_page(page: Page) -> None:
                uri = file_uri("error.html")
                page.goto(uri)
            """
        )
        playwright_pytester.runpytest().assert_outcomes(passed=1, errors=1)

    def test_non_existent_page_is_error(self, playwright_pytester: Pytester) -> None:
        """
        Opening a non-existent file with the `page` fixture fails the test.
        """
        playwright_pytester.makepyfile(
            """
            from playwright.sync_api import Page
            from chives.browser_fixtures import file_uri

        
            def test_page(page: Page) -> None:
                uri = file_uri("does_not_exist.html")
                page.goto(uri)
            """
        )
        playwright_pytester.runpytest().assert_outcomes(failed=1)


def test_skip_playwright(pytester: Pytester) -> None:
    """
    If the SKIP_PLAYWRIGHT environment variable is set, the test is skipped.
    """
    pytester.makeconftest("""
        import os
    
        from chives.browser_fixtures import browser, page
    
        os.environ["SKIP_PLAYWRIGHT"] = "true"
    """)
    pytester.makepyfile(
        """
        from playwright.sync_api import Browser, Page

    
        def test_browser(browser: Browser) -> None:
            pass


        def test_page(page: Page) -> None:
            pass
        """
    )
    pytester.runpytest().assert_outcomes(skipped=2)
