load("@bazel_skylib//rules:select_file.bzl", "select_file")
load("@py_dev_requirements//:requirements.bzl", "requirement")
load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix")
load("@rules_pkg//pkg:pkg.bzl", "pkg_tar")
load("@rules_python//python:defs.bzl", "py_binary", "py_library")
load("@rules_python//python:packaging.bzl", "py_package", "py_wheel")
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
load("//common:defs.bzl", "copy_file")
load("//py:defs.bzl", "generate_devtools", "py_test_suite")
load("//py/private:browsers.bzl", "BROWSERS")
load("//py/private:import.bzl", "py_import")

py_binary(
    name = "selenium-release",
    srcs = [
        "release-selenium.py",
    ],
    args = [
        "upload",
        "$(location :selenium-wheel)",
        "$(location :selenium-sdist)",
    ],
    data = [
        ":selenium-sdist",
        ":selenium-wheel",
    ],
    main = "release-selenium.py",
    deps = [
        requirement("twine"),
    ],
)

py_binary(
    name = "selenium-release-nightly",
    srcs = [
        "release-selenium.py",
    ],
    args = [
        "upload",
        "--repository",
        "testpypi",
        "$(location :selenium-wheel)",
        "$(location :selenium-sdist)",
    ],
    data = [
        ":selenium-sdist",
        ":selenium-wheel",
    ],
    main = "release-selenium.py",
    deps = [
        requirement("twine"),
    ],
)

compile_pip_requirements(
    # base name for generated targets, typically "requirements"
    name = "requirements",
    requirements_in = ":requirements.txt",
    requirements_txt = ":requirements_lock.txt",
    tags = [
        "skip-remote",  # This test won't run on the RBE because of a lack of network connectivity
    ],
)

SE_VERSION = "4.26.1"

BROWSER_VERSIONS = [
    "v85",
    "v128",
    "v129",
    "v130",
]

TEST_DEPS = [
    requirement("attrs"),
    requirement("debugpy"),
    requirement("idna"),
    requirement("iniconfig"),
    requirement("importlib_metadata"),
    requirement("h11"),
    requirement("more_itertools"),
    requirement("multidict"),
    requirement("outcome"),
    requirement("pluggy"),
    requirement("py"),
    requirement("pytest"),
    requirement("pytest-instafail"),
    requirement("pytest-trio"),
    requirement("pytest-mock"),
    requirement("sortedcontainers"),
    requirement("sniffio"),
    requirement("zipp"),
]

copy_file(
    name = "manager-linux",
    src = "//common/manager:selenium-manager-linux",
    out = "selenium/webdriver/common/linux/selenium-manager",
)

copy_file(
    name = "manager-macos",
    src = "//common/manager:selenium-manager-macos",
    out = "selenium/webdriver/common/macos/selenium-manager",
)

copy_file(
    name = "manager-windows",
    src = "//common/manager:selenium-manager-windows",
    out = "selenium/webdriver/common/windows/selenium-manager.exe",
)

copy_file(
    name = "get-attribute",
    src = "//javascript/webdriver/atoms:get-attribute.js",
    out = "selenium/webdriver/remote/getAttribute.js",
)

copy_file(
    name = "is-displayed",
    src = "//javascript/atoms/fragments:is-displayed.js",
    out = "selenium/webdriver/remote/isDisplayed.js",
)

copy_file(
    name = "find-elements",
    src = "//javascript/atoms/fragments:find-elements.js",
    out = "selenium/webdriver/remote/findElements.js",
)

copy_file(
    name = "mutation-listener",
    src = "//javascript/cdp-support:mutation-listener.js",
    out = "selenium/webdriver/common/mutation-listener.js",
)

copy_file(
    name = "firefox-driver-prefs",
    src = "//third_party/js/selenium:webdriver_json",
    out = "selenium/webdriver/firefox/webdriver_prefs.json",
)

copy_file(
    name = "webextensions-selenium-example-xpi",
    src = "//common/extensions:webextensions-selenium-example.xpi",
    out = "test/extensions/webextensions-selenium-example.xpi",
)

copy_file(
    name = "webextensions-selenium-example-zip",
    src = "//common/extensions:webextensions-selenium-example.zip",
    out = "test/extensions/webextensions-selenium-example.zip",
)

copy_file(
    name = "webextensions-selenium-example-unsigned-zip",
    src = "//common/extensions:webextensions-selenium-example-unsigned.zip",
    out = "test/extensions/webextensions-selenium-example-unsigned.zip",
)

select_file(
    name = "global-license",
    srcs = "//:license",
    subpath = "LICENSE",
)

copy_file(
    name = "license",
    src = ":global-license",
    out = "LICENSE",
)

copy_file(
    name = "license-wheel",
    src = ":global-license",
    out = "selenium-%s.dist-info/LICENSE" % SE_VERSION,
)

py_library(
    name = "selenium",
    srcs = glob(
        ["selenium/**/*.py"],
        exclude = ["generate.py"],
    ),
    data = [
        "selenium/py.typed",
        ":find-elements",
        ":firefox-driver-prefs",
        ":get-attribute",
        ":is-displayed",
        ":manager-linux",
        ":manager-macos",
        ":manager-windows",
        ":mutation-listener",
    ] + [":create-cdp-srcs-" + n for n in BROWSER_VERSIONS],
    imports = ["."],
    visibility = ["//visibility:public"],
    deps = [
        requirement("urllib3"),
        requirement("trio"),
        requirement("trio_websocket"),
        requirement("certifi"),
        requirement("typing_extensions"),
        requirement("websocket-client"),
    ],
)

py_package(
    name = "selenium-pkg",
    packages = [
        "py.selenium",
        "py.selenium.common",
        "py.selenium.webdriver",
        "py.selenium.webdriver.chrome",
        "py.selenium.webdriver.chromium",
        "py.selenium.webdriver.common",
        "py.selenium.webdriver.common.bidi",
        "py.selenium.webdriver.common.devtools",
        "py.selenium.webdriver.edge",
        "py.selenium.webdriver.firefox",
        "py.selenium.webdriver.remote",
        "py.selenium.webdriver.safari",
    ],
    deps = [":selenium"],
)

pkg_files(
    name = "selenium-sdist-pkg",
    srcs = [
        "CHANGES",
        "MANIFEST.in",
        "README.rst",
        "pyproject.toml",
        "setup.py",
        ":license",
        ":selenium-pkg",
        ":selenium-pkginfo",
        "//rust:selenium_manager_srcs",
    ],
    excludes = [
        ":manager-linux",
        ":manager-macos",
        ":manager-windows",
    ],
    strip_prefix = strip_prefix.from_pkg(),
)

pkg_tar(
    name = "selenium-sdist",
    srcs = [":selenium-sdist-pkg"],
    extension = "tar.gz",
    mode = "0644",
    package_dir = "selenium-%s" % SE_VERSION,
    package_file_name = "selenium-%s.tar.gz" % SE_VERSION,
)

genrule(
    name = "selenium-pkginfo",
    srcs = [":selenium-wheel-lib"],
    outs = ["PKG-INFO"],
    cmd = "cp $(location :selenium-wheel-lib)/selenium-%s.dist-info/METADATA $@" % SE_VERSION,
)

py_import(
    name = "selenium-wheel-lib",
    wheel = ":selenium-wheel",
)

py_wheel(
    name = "selenium-wheel",
    classifiers = [
        "Development Status :: 5 - Production/Stable",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: Apache Software License",
        "Operating System :: POSIX",
        "Operating System :: Microsoft :: Windows",
        "Operating System :: MacOS :: MacOS X",
        "Topic :: Software Development :: Testing",
        "Topic :: Software Development :: Libraries",
        "Programming Language :: Python",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
    ],
    description_file = "README.rst",
    distribution = "selenium",
    homepage = "https://www.selenium.dev",
    license = "Apache 2.0",
    python_requires = ">=3.8",
    python_tag = "py3",
    requires = [
        "urllib3[socks]>=1.26,<3",
        "trio~=0.17",
        "trio-websocket~=0.9",
        "certifi>=2021.10.8",
        "typing_extensions~=4.9",
        "websocket-client~=1.8",
    ],
    strip_path_prefixes = [
        "py/",
    ],
    summary = "Official Python bindings for Selenium WebDriver",
    tags = [
        "release-artifact",
    ],
    version = SE_VERSION,
    visibility = ["//visibility:public"],
    deps = [
        ":license-wheel",
        ":selenium-pkg",
    ],
)

py_library(
    name = "init-tree",
    testonly = True,
    srcs = [
        "conftest.py",
        "test/__init__.py",
        "test/selenium/__init__.py",
        "test/selenium/webdriver/__init__.py",
        "test/selenium/webdriver/chrome/__init__.py",
        "test/selenium/webdriver/common/__init__.py",
        "test/selenium/webdriver/common/conftest.py",
        "test/selenium/webdriver/common/network.py",
        "test/selenium/webdriver/common/webserver.py",
        "test/selenium/webdriver/firefox/__init__.py",
        "test/selenium/webdriver/firefox/conftest.py",
        "test/selenium/webdriver/marionette/__init__.py",
        "test/selenium/webdriver/marionette/conftest.py",
        "test/selenium/webdriver/safari/conftest.py",
        "test/selenium/webdriver/support/__init__.py",
        "test/selenium/webdriver/support/conftest.py",
    ],
    data = [
        "pyproject.toml",
        "setup.cfg",
        "test/selenium/webdriver/common/test_file.txt",
        "test/selenium/webdriver/common/test_file2.txt",
        ":webextensions-selenium-example-unsigned-zip",
        ":webextensions-selenium-example-xpi",
        ":webextensions-selenium-example-zip",
    ],
    imports = ["."],
    deps = [
        ":webserver",
    ],
)

py_binary(
    name = "generate",
    srcs = ["generate.py"],
    srcs_version = "PY3",
    deps = [requirement("inflection")],
)

[generate_devtools(
    name = "create-cdp-srcs-{}".format(devtools_version),
    browser_protocol = "//common/devtools/chromium/{}:browser_protocol".format(devtools_version),
    generator = ":generate",
    js_protocol = "//common/devtools/chromium/{}:js_protocol".format(devtools_version),
    outdir = "selenium/webdriver/common/devtools/{}".format(devtools_version),
    protocol_version = devtools_version,
) for devtools_version in BROWSER_VERSIONS]

py_test_suite(
    name = "unit",
    size = "small",
    srcs = glob([
        "test/unit/**/*.py",
    ]),
    args = [
        "--instafail",
    ],
    deps = [
        ":init-tree",
        ":selenium",
    ] + TEST_DEPS,
)

py_library(
    name = "webserver",
    testonly = True,
    srcs = [
        "test/selenium/webdriver/common/network.py",
        "test/selenium/webdriver/common/webserver.py",
    ],
    data = [
        "//common/src/web",
    ],
    deps = [],
)

BIDI_TESTS = glob(["test/selenium/webdriver/common/**/*bidi*_tests.py"])

[
    py_test_suite(
        name = "common-%s" % browser,
        size = "large",
        srcs = glob(
            [
                "test/selenium/webdriver/common/**/*.py",
                "test/selenium/webdriver/support/**/*.py",
            ],
            exclude = BIDI_TESTS + ["test/selenium/webdriver/common/print_pdf_tests.py"],
        ),
        args = [
            "--instafail",
            "--bidi=false",
        ] + BROWSERS[browser]["args"],
        data = BROWSERS[browser]["data"],
        env_inherit = ["DISPLAY"],
        tags = ["no-sandbox"] + BROWSERS[browser]["tags"],
        deps = [
            ":init-tree",
            ":selenium",
            ":webserver",
        ] + TEST_DEPS,
    )
    for browser in BROWSERS.keys()
]

[
    py_test_suite(
        name = "common-%s-bidi" % browser,
        size = "large",
        srcs = glob(
            [
                "test/selenium/webdriver/common/**/*.py",
                "test/selenium/webdriver/support/**/*.py",
            ],
            exclude = ["test/selenium/webdriver/common/print_pdf_tests.py"],
        ),
        args = [
            "--instafail",
            "--bidi=true",
        ] + BROWSERS[browser]["args"],
        data = BROWSERS[browser]["data"],
        env_inherit = ["DISPLAY"],
        tags = ["no-sandbox"] + BROWSERS[browser]["tags"],
        deps = [
            ":init-tree",
            ":selenium",
            ":webserver",
        ] + TEST_DEPS,
    )
    for browser in BROWSERS.keys()
]

py_test_suite(
    name = "test-chrome",
    size = "large",
    srcs = glob(
        [
            "test/selenium/webdriver/chrome/**/*.py",
        ],
        exclude = ["test/selenium/webdriver/common/print_pdf_tests.py"],
    ),
    args = [
        "--instafail",
    ] + BROWSERS["chrome"]["args"],
    data = BROWSERS["chrome"]["data"],
    env_inherit = ["DISPLAY"],
    tags = [
        "no-sandbox",
    ] + BROWSERS["chrome"]["tags"],
    deps = [
        ":init-tree",
        ":selenium",
        ":webserver",
    ] + TEST_DEPS,
)

py_test_suite(
    name = "test-chrome-headless",
    size = "large",
    srcs = glob(
        [
            "test/selenium/webdriver/chrome/**/*.py",
        ],
    ),
    args = [
        "--instafail",
        "--headless=true",
    ] + BROWSERS["chrome"]["args"],
    data = BROWSERS["chrome"]["data"],
    env_inherit = ["DISPLAY"],
    tags = [
        "no-sandbox",
        "skip-remote",
    ] + BROWSERS["chrome"]["tags"],
    deps = [
        ":init-tree",
        ":selenium",
        ":webserver",
    ] + TEST_DEPS,
)

py_test_suite(
    name = "test-edge",
    size = "large",
    srcs = glob([
        "test/selenium/webdriver/edge/**/*.py",
    ]),
    args = [
        "--instafail",
    ] + BROWSERS["edge"]["args"],
    data = BROWSERS["edge"]["data"],
    env_inherit = ["DISPLAY"],
    tags = [
        "no-sandbox",
    ] + BROWSERS["edge"]["tags"],
    deps = [
        ":init-tree",
        ":selenium",
        ":webserver",
    ] + TEST_DEPS,
)

py_test_suite(
    name = "test-firefox",
    size = "large",
    srcs = glob([
        "test/selenium/webdriver/marionette/**/*.py",
        "test/selenium/webdriver/firefox/**/*.py",
    ]),
    args = [
        "--instafail",
    ] + BROWSERS["firefox"]["args"],
    data = BROWSERS["firefox"]["data"],
    env_inherit = ["DISPLAY"],
    tags = [
        "no-sandbox",
        "skip-remote",
    ] + BROWSERS["firefox"]["tags"],
    deps = [
        ":init-tree",
        ":selenium",
        ":webserver",
    ] + TEST_DEPS,
)

py_test_suite(
    name = "test-remote",
    size = "large",
    srcs = glob(
        [
            "test/selenium/webdriver/common/**/*.py",
            "test/selenium/webdriver/support/**/*.py",
        ],
        exclude = BIDI_TESTS,
    ),
    args = [
        "--instafail",
        "--driver=remote",
    ],
    data = [
        "//java/src/org/openqa/selenium/grid:selenium_server_deploy.jar",
    ],
    tags = [
        "no-sandbox",
        "skip-remote",
    ],
    deps = [
        ":init-tree",
        ":selenium",
        ":webserver",
    ] + TEST_DEPS,
)

py_test_suite(
    name = "test-ie",
    size = "large",
    srcs = glob([
        "test/selenium/webdriver/common/**/*.py",
        "test/selenium/webdriver/ie/**/*.py",
        "test/selenium/webdriver/support/**/*.py",
    ]),
    args = [
        "--instafail",
        "--driver=ie",
    ],
    tags = [
        "no-sandbox",
        "skip-remote",
    ],
    deps = [
        ":init-tree",
        ":selenium",
        ":webserver",
    ] + TEST_DEPS,
)

py_test_suite(
    name = "test-safari",
    size = "large",
    srcs = glob([
        "test/selenium/webdriver/common/**/*.py",
        "test/selenium/webdriver/safari/**/*.py",
        "test/selenium/webdriver/support/**/*.py",
    ]),
    args = [
        "--instafail",
        "--driver=safari",
    ],
    tags = [
        "exclusive-if-local",
        "no-sandbox",
        "skip-remote",
    ],
    deps = [
        ":init-tree",
        ":selenium",
        ":webserver",
    ] + TEST_DEPS,
)

py_test_suite(
    name = "test-webkitgtk",
    size = "large",
    srcs = glob([
        "test/selenium/webdriver/common/**/*.py",
        "test/selenium/webdriver/support/**/*.py",
    ]),
    args = [
        "--instafail",
        "--driver=webkitgtk",
        "--browser-binary=MiniBrowser",
        "--browser-args=--automation",
    ],
    tags = [
        "exclusive-if-local",
        "no-sandbox",
        "skip-remote",
    ],
    deps = [
        ":init-tree",
        ":selenium",
        ":webserver",
    ] + TEST_DEPS,
)

py_test_suite(
    name = "test-wpewebkit",
    size = "large",
    srcs = glob([
        "test/selenium/webdriver/common/**/*.py",
        "test/selenium/webdriver/support/**/*.py",
    ]),
    args = [
        "--instafail",
        "--driver=wpewebkit",
        "--browser-binary=MiniBrowser",
        "--browser-args=--automation --headless",
    ],
    tags = [
        "exclusive-if-local",
        "no-sandbox",
        "skip-remote",
    ],
    deps = [
        ":init-tree",
        ":selenium",
        ":webserver",
    ] + TEST_DEPS,
)
