diff --git a/.bazelrc.remote b/.bazelrc.remote index a858484cb1976..3aaff34596a2b 100644 --- a/.bazelrc.remote +++ b/.bazelrc.remote @@ -42,9 +42,6 @@ test:rbe --test_env=HOME=/home/dev # Make sure we sniff credentials properly build:rbe --credential_helper=gypsum.cluster.engflow.com=%workspace%/scripts/credential-helper.sh -# Use pinned browsers when running remotely -build:rbe --//common:pin_browsers - # The remote build machines are pretty small, and 50 threads may leave them # thrashing, but our dev machines are a lot larger. Scale the workload so we # make reasonable usage of everything, everywhere, all at once. diff --git a/.github/workflows/ci-dotnet.yml b/.github/workflows/ci-dotnet.yml index 1e2a2c259382d..0c88afd629d4c 100644 --- a/.github/workflows/ci-dotnet.yml +++ b/.github/workflows/ci-dotnet.yml @@ -24,4 +24,4 @@ jobs: os: windows run: | fsutil 8dot3name set 0 - bazel test //dotnet/test/common:ElementFindingTest-firefox //dotnet/test/common:ElementFindingTest-chrome --pin_browsers=true + bazel test //dotnet/test/common:ElementFindingTest-firefox //dotnet/test/common:ElementFindingTest-chrome diff --git a/.github/workflows/ci-java.yml b/.github/workflows/ci-java.yml index 63727764a0953..f04334fba068c 100644 --- a/.github/workflows/ci-java.yml +++ b/.github/workflows/ci-java.yml @@ -23,7 +23,7 @@ jobs: java-version: 17 run: | fsutil 8dot3name set 0 - bazel test --flaky_test_attempts 3 --pin_browsers=true //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest ` + bazel test --flaky_test_attempts 3 //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest ` //java/test/org/openqa/selenium/federatedcredentialmanagement:FederatedCredentialManagementTest ` //java/test/org/openqa/selenium/firefox:FirefoxDriverBuilderTest ` //java/test/org/openqa/selenium/grid/router:RemoteWebDriverDownloadTest ` @@ -48,7 +48,7 @@ jobs: # https://github.com/bazelbuild/rules_jvm_external/issues/1046 java-version: 17 run: | - bazel test --flaky_test_attempts 3 --pin_browsers=true //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest-remote \ + bazel test --flaky_test_attempts 3 //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest-remote \ //java/test/org/openqa/selenium/federatedcredentialmanagement:FederatedCredentialManagementTest \ //java/test/org/openqa/selenium/firefox:FirefoxDriverBuilderTest \ //java/test/org/openqa/selenium/grid/router:RemoteWebDriverDownloadTest \ @@ -72,4 +72,4 @@ jobs: # https://github.com/bazelbuild/rules_jvm_external/issues/1046 java-version: 17 run: | - bazel test --flaky_test_attempts 3 --pin_browsers=true //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest-remote + bazel test --flaky_test_attempts 3 //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest-remote diff --git a/.github/workflows/ci-python.yml b/.github/workflows/ci-python.yml index 6750bd1b73a11..4136353d96d6a 100644 --- a/.github/workflows/ci-python.yml +++ b/.github/workflows/ci-python.yml @@ -114,7 +114,7 @@ jobs: os: ${{ matrix.os }} cache-key: py-browser-${{ matrix.browser }} run: | - bazel test --local_test_jobs 1 --flaky_test_attempts 3 --pin_browsers=true //py:common-${{ matrix.browser }}-bidi //py:test-${{ matrix.browser }} + bazel test --local_test_jobs 1 --flaky_test_attempts 3 //py:common-${{ matrix.browser }}-bidi //py:test-${{ matrix.browser }} browser-tests-windows: name: Browser Tests @@ -135,7 +135,7 @@ jobs: cache-key: py-browser-${{ matrix.browser }} run: | fsutil 8dot3name set 0 - bazel test --local_test_jobs 1 --flaky_test_attempts 3 --pin_browsers=true //py:common-${{ matrix.browser }}-bidi //py:test-${{ matrix.browser }} + bazel test --local_test_jobs 1 --flaky_test_attempts 3 //py:common-${{ matrix.browser }}-bidi //py:test-${{ matrix.browser }} browser-tests-macos: name: Browser Tests @@ -153,4 +153,4 @@ jobs: os: ${{ matrix.os }} cache-key: py-browser-${{ matrix.browser }} run: | - bazel test --local_test_jobs 1 --flaky_test_attempts 3 --pin_browsers=true //py:common-${{ matrix.browser }} //py:test-${{ matrix.browser }} + bazel test --local_test_jobs 1 --flaky_test_attempts 3 //py:common-${{ matrix.browser }} //py:test-${{ matrix.browser }} diff --git a/.github/workflows/ci-ruby.yml b/.github/workflows/ci-ruby.yml index 08cff26a7eda3..66e0364ce17ed 100644 --- a/.github/workflows/ci-ruby.yml +++ b/.github/workflows/ci-ruby.yml @@ -84,7 +84,6 @@ jobs: --local_test_jobs 1 --test_size_filters large --test_tag_filters ${{ matrix.browser }} - --pin_browsers //rb/spec/... integration-tests-remote: @@ -111,5 +110,4 @@ jobs: --local_test_jobs 1 --test_size_filters large --test_tag_filters ${{ matrix.browser }}-remote - --pin_browsers //rb/spec/... diff --git a/README.md b/README.md index e37561e17ee7e..c630b7fd79ff4 100644 --- a/README.md +++ b/README.md @@ -297,7 +297,7 @@ There are a number of bazel configurations specific for testing. ### Common Options Examples Here are examples of arguments we make use of in testing the Selenium code: -* `--pin_browsers` - run specific browser versions defined in the build (versions are updated regularly) +* `--pin_browsers=false` - use Selenium Manager to locate browsers/drivers * `--headless` - run browsers in headless mode (supported be Chrome, Edge and Firefox) * `--flaky_test_attempts 3` - re-run failed tests up to 3 times * `--local_test_jobs 1` - control parallelism of tests @@ -491,19 +491,19 @@ echo '' > rb/.ruby-version Run all tests with: ```shell -bazel test //dotnet/test/common:AllTests --pin_browsers=true +bazel test //dotnet/test/common:AllTests ``` You can run specific tests by specifying the class name: ```shell -bazel test //dotnet/test/common:ElementFindingTest --pin_browsers=true +bazel test //dotnet/test/common:ElementFindingTest ``` If the module supports multiple browsers: ```shell -bazel test //dotnet/test/common:ElementFindingTest-edge --pin_browsers=true +bazel test //dotnet/test/common:ElementFindingTest-edge ``` diff --git a/common/BUILD.bazel b/common/BUILD.bazel index d83a1899fb612..5cfe390e75844 100644 --- a/common/BUILD.bazel +++ b/common/BUILD.bazel @@ -4,14 +4,7 @@ package(default_visibility = ["//visibility:public"]) bool_flag( name = "pin_browsers", - build_setting_default = False, -) - -config_setting( - name = "use_pinned_browser", - flag_values = { - ":pin_browsers": "true", - }, + build_setting_default = True, ) bool_flag( @@ -47,6 +40,13 @@ config_setting( values = {"stamp": "true"}, ) +config_setting( + name = "use_pinned_browser", + flag_values = { + ":pin_browsers": "true", + }, +) + alias( name = "chromedriver", actual = "@local_drivers//:chromedriver", diff --git a/common/manager/BUILD.bazel b/common/manager/BUILD.bazel index 859cb1024901c..e38ecafdb98e6 100644 --- a/common/manager/BUILD.bazel +++ b/common/manager/BUILD.bazel @@ -11,15 +11,24 @@ package( alias( name = "selenium-manager-linux", - actual = "@download_sm_linux//file", + actual = select({ + "//common:use_pinned_browser": "@download_sm_linux//file", + "//conditions:default": "//rust:selenium-manager-linux", + }), ) alias( name = "selenium-manager-macos", - actual = "@download_sm_macos//file", + actual = select({ + "//common:use_pinned_browser": "@download_sm_macos//file", + "//conditions:default": "//rust:selenium-manager-macos", + }), ) alias( name = "selenium-manager-windows", - actual = "@download_sm_windows//file", + actual = select({ + "//common:use_pinned_browser": "@download_sm_windows//file", + "//conditions:default": "//rust:selenium-manager-windows", + }), ) diff --git a/dotnet/src/webdriver/SeleniumManager.cs b/dotnet/src/webdriver/SeleniumManager.cs index a178796657b0a..70db6823a1bf9 100644 --- a/dotnet/src/webdriver/SeleniumManager.cs +++ b/dotnet/src/webdriver/SeleniumManager.cs @@ -178,6 +178,15 @@ public static Dictionary BinaryPaths(string arguments) { StringBuilder argsBuilder = new StringBuilder(arguments); argsBuilder.Append(" --language-binding csharp"); +#if NET8_0_OR_GREATER + argsBuilder.Append($" --language-version net8.0/{Environment.Version.Major}"); +#elif NETSTANDARD2_0 + argsBuilder.Append($" --language-version netstandard2.0/{Environment.Version.Major}"); +#elif NET462 + argsBuilder.Append(" --language-version net462"); +#else +#error Add support here +#endif argsBuilder.Append(" --output json"); if (_logger.IsEnabled(LogEventLevel.Debug)) { diff --git a/java/src/org/openqa/selenium/manager/SeleniumManager.java b/java/src/org/openqa/selenium/manager/SeleniumManager.java index bed9e56e08dbe..b4b39ec245b8f 100644 --- a/java/src/org/openqa/selenium/manager/SeleniumManager.java +++ b/java/src/org/openqa/selenium/manager/SeleniumManager.java @@ -261,10 +261,12 @@ private void saveToFileSafely(InputStream inputStream, Path target) throws IOExc * @return the locations of the assets from Selenium Manager execution */ public Result getBinaryPaths(List arguments) { - List args = new ArrayList<>(arguments.size() + 5); + List args = new ArrayList<>(arguments.size() + 7); args.addAll(arguments); args.add("--language-binding"); args.add("java"); + args.add("--language-version"); + args.add(Runtime.version().feature() + ""); args.add("--output"); args.add("json"); diff --git a/javascript/selenium-webdriver/common/driverFinder.js b/javascript/selenium-webdriver/common/driverFinder.js index e1a988cb0206f..2bf286800a528 100644 --- a/javascript/selenium-webdriver/common/driverFinder.js +++ b/javascript/selenium-webdriver/common/driverFinder.js @@ -44,7 +44,16 @@ function getBinaryPaths(capabilities) { } function getArgs(options) { - let args = ['--browser', options.getBrowserName(), '--language-binding', 'javascript', '--output', 'json'] + let args = [ + '--browser', + options.getBrowserName(), + '--language-binding', + 'javascript', + '--language-version', + process.versions.node, + '--output', + 'json', + ] if (options.getBrowserVersion() && options.getBrowserVersion() !== '') { args.push('--browser-version', options.getBrowserVersion()) diff --git a/py/selenium/webdriver/common/selenium_manager.py b/py/selenium/webdriver/common/selenium_manager.py index a4a8edd5366fe..adec4a6cf8131 100644 --- a/py/selenium/webdriver/common/selenium_manager.py +++ b/py/selenium/webdriver/common/selenium_manager.py @@ -49,6 +49,8 @@ def binary_paths(self, args: list) -> dict: args.append("--debug") args.append("--language-binding") args.append("python") + args.append("--language-version") + args.append(f"{sys.version_info.major}.{sys.version_info.minor}") args.append("--output") args.append("json") diff --git a/py/test/selenium/webdriver/common/selenium_manager_tests.py b/py/test/selenium/webdriver/common/selenium_manager_tests.py index 13edd5577ce7f..11350c77ec171 100644 --- a/py/test/selenium/webdriver/common/selenium_manager_tests.py +++ b/py/test/selenium/webdriver/common/selenium_manager_tests.py @@ -38,7 +38,15 @@ def test_gets_results(monkeypatch): SeleniumManager().binary_paths([]) mock_get_binary.assert_called_once() - expected_run_args = ["/path/to/sm", "--language-binding", "python", "--output", "json"] + expected_run_args = [ + "/path/to/sm", + "--language-binding", + "python", + "--language-version", + f"{sys.version_info.major}.{sys.version_info.minor}", + "--output", + "json", + ] mock_run.assert_called_once_with(expected_run_args) diff --git a/rb/lib/selenium/webdriver/common/selenium_manager.rb b/rb/lib/selenium/webdriver/common/selenium_manager.rb index 4a8603b6584b0..17124e818fbc4 100644 --- a/rb/lib/selenium/webdriver/common/selenium_manager.rb +++ b/rb/lib/selenium/webdriver/common/selenium_manager.rb @@ -38,6 +38,7 @@ def bin_path # @return [Hash] paths to the requested assets. def binary_paths(*arguments) arguments += %w[--language-binding ruby] + arguments += ['--language-version', RUBY_VERSION.split('.').first(2).join('.')] arguments += %w[--output json] arguments << '--debug' if WebDriver.logger.debug? diff --git a/rust/src/config.rs b/rust/src/config.rs index cff48ea7b6e78..6a1b59d8f25ef 100644 --- a/rust/src/config.rs +++ b/rust/src/config.rs @@ -64,6 +64,7 @@ pub struct ManagerConfig { pub force_browser_download: bool, pub avoid_browser_download: bool, pub language_binding: String, + pub language_binding_version: String, pub selenium_version: String, pub avoid_stats: bool, pub skip_driver_in_path: bool, @@ -131,6 +132,7 @@ impl ManagerConfig { force_browser_download: BooleanKey("force-browser-download", false).get_value(), avoid_browser_download: BooleanKey("avoid-browser-download", false).get_value(), language_binding: StringKey(vec!["language-binding"], "").get_value(), + language_binding_version: StringKey(vec!["language-version"], "").get_value(), selenium_version: StringKey(vec!["selenium-version"], "").get_value(), avoid_stats: BooleanKey("avoid-stats", false).get_value(), skip_driver_in_path: BooleanKey("skip-driver-in-path", false).get_value(), diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 7d8a9a44fbf98..7f19f1ded84c7 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -908,6 +908,7 @@ pub trait SeleniumManager { .unwrap_or(ARCH_OTHER) .to_ascii_lowercase(), lang: self.get_language_binding().to_ascii_lowercase(), + lang_version: self.get_language_binding_version().to_ascii_lowercase(), selenium_version: self.get_selenium_version().to_ascii_lowercase(), }; let http_client = self.get_http_client().to_owned(); @@ -1605,6 +1606,16 @@ pub trait SeleniumManager { } } + fn get_language_binding_version(&self) -> &str { + self.get_config().language_binding_version.as_str() + } + + fn set_language_binding_version(&mut self, language_binding_version: String) { + if !language_binding_version.is_empty() { + self.get_config_mut().language_binding_version = language_binding_version; + } + } + fn get_selenium_version(&self) -> &str { self.get_config().selenium_version.as_str() } diff --git a/rust/src/main.rs b/rust/src/main.rs index fed02f42272db..1c40365924ff0 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -145,6 +145,10 @@ struct Cli { #[clap(long)] language_binding: Option, + /// Version of the language binding invoking Selenium Manager (e.g., 4.18.1, 3.12, net8.0/8) + #[clap(long)] + language_version: Option, + /// Avoid sends usage statistics to plausible.io #[clap(long)] avoid_stats: bool, @@ -223,6 +227,7 @@ fn main() { selenium_manager.set_cache_path(cache_path.clone()); selenium_manager.set_offline(cli.offline); selenium_manager.set_language_binding(cli.language_binding.unwrap_or_default()); + selenium_manager.set_language_binding_version(cli.language_version.unwrap_or_default()); let sm_version = clap::crate_version!(); let selenium_version = sm_version.strip_prefix(SM_BETA_LABEL).unwrap_or(sm_version); selenium_manager.set_selenium_version(selenium_version.to_string()); diff --git a/rust/src/metadata.rs b/rust/src/metadata.rs index 5362b48fc0d5c..105ad7142e83d 100644 --- a/rust/src/metadata.rs +++ b/rust/src/metadata.rs @@ -32,6 +32,7 @@ pub struct Stats { pub os: String, pub arch: String, pub lang: String, + pub lang_version: String, pub selenium_version: String, pub stats_ttl: u64, } @@ -147,6 +148,7 @@ pub fn is_stats_in_metadata(stats_metadata: &[Stats], props: &Props) -> bool { && p.os.eq(&props.os) && p.arch.eq(&props.arch) && p.lang.eq(&props.lang) + && p.lang_version.eq(&props.lang_version) && p.selenium_version.eq(&props.selenium_version) }) .collect(); @@ -188,6 +190,7 @@ pub fn create_stats_metadata(props: &Props, stats_ttl: u64) -> Stats { os: props.os.to_string(), arch: props.arch.to_string(), lang: props.lang.to_string(), + lang_version: props.lang_version.to_string(), selenium_version: props.selenium_version.to_string(), stats_ttl: now_unix_timestamp() + stats_ttl, } diff --git a/rust/src/stats.rs b/rust/src/stats.rs index f8ecca4ccd6ff..54b4c5607b9eb 100644 --- a/rust/src/stats.rs +++ b/rust/src/stats.rs @@ -46,6 +46,7 @@ pub struct Props { pub os: String, pub arch: String, pub lang: String, + pub lang_version: String, pub selenium_version: String, }