diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index 70dfd17205a538..c663678f1b00a9 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -46,6 +46,11 @@ on: required: false type: string default: '' + artifact-name: + description: Name of artifact to upload + required: false + type: string + default: 'ignore-artifacts' jobs: bazel: @@ -140,3 +145,14 @@ jobs: title: "Nightly" prerelease: true files: ${{ inputs.nightly-release-files }} + - name: Save changes + if: ${{ always() && inputs.artifact-name != 'ignore-artifacts' }} + run: | + git diff > changes.patch + - name: "Upload changes" + if: ${{ always() && inputs.artifact-name != 'ignore-artifacts' }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.artifact-name }} + path: changes.patch + retention-days: 6 diff --git a/.github/workflows/ci-ruby.yml b/.github/workflows/ci-ruby.yml index 5f59315a1f805d..a92bf9e8bd38e1 100644 --- a/.github/workflows/ci-ruby.yml +++ b/.github/workflows/ci-ruby.yml @@ -45,7 +45,7 @@ jobs: os: windows - ruby-version: 3.0.6 os: macos - - ruby-version: 3.2.2 + - ruby-version: 3.3.0 os: ubuntu - ruby-version: jruby-9.4.5.0 os: ubuntu diff --git a/.github/workflows/ci-rust.yml b/.github/workflows/ci-rust.yml index 47a3b98346f82a..b0a1862446fcaa 100644 --- a/.github/workflows/ci-rust.yml +++ b/.github/workflows/ci-rust.yml @@ -2,6 +2,15 @@ name: CI - Rust on: workflow_call: + inputs: + release: + required: false + type: string + default: false + branch: + required: false + type: string + default: trunk secrets: SELENIUM_CI_TOKEN: required: true @@ -43,6 +52,8 @@ jobs: steps: - name: "Checkout project" uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} - name: "Update Rust" run: | rustup update @@ -55,7 +66,7 @@ jobs: - name: "Rename binary" run: mv rust/target/release/selenium-manager.exe selenium-manager-windows.exe - name: "Upload release binary" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: selenium-manager-windows path: selenium-manager-windows.exe @@ -71,6 +82,8 @@ jobs: steps: - name: "Checkout project" uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} - name: "Update Rust" run: | rustup update @@ -83,7 +96,7 @@ jobs: - name: "Rename binary" run: mv rust/target/debug/selenium-manager.exe selenium-manager-windows-debug.exe - name: "Upload release binary" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: selenium-manager-windows-debug path: selenium-manager-windows-debug.exe @@ -97,6 +110,8 @@ jobs: steps: - name: "Checkout project" uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} - name: "Update Rust" run: | rustup update @@ -111,7 +126,7 @@ jobs: - name: "Rename binary" run: mv rust/target/x86_64-unknown-linux-musl/release/selenium-manager selenium-manager-linux - name: "Upload release binary" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: selenium-manager-linux path: selenium-manager-linux @@ -125,6 +140,8 @@ jobs: steps: - name: "Checkout project" uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} - name: "Update Rust" run: | rustup update @@ -140,7 +157,7 @@ jobs: tar -cvf ../../../../selenium-manager-linux-debug.tar selenium-manager working-directory: rust - name: "Upload release binary" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: selenium-manager-linux-debug path: selenium-manager-linux-debug.tar @@ -156,6 +173,8 @@ jobs: steps: - name: "Checkout project" uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} - name: "Update Rust" run: | rustup update @@ -170,7 +189,7 @@ jobs: target/x86_64-apple-darwin/release/selenium-manager working-directory: rust - name: "Upload release binary" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: selenium-manager-macos path: rust/target/selenium-manager-macos @@ -186,6 +205,8 @@ jobs: steps: - name: "Checkout project" uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} - name: "Update Rust" run: | rustup update @@ -202,7 +223,7 @@ jobs: tar -cvf ../../selenium-manager-macos-debug.tar selenium-manager working-directory: rust - name: "Upload release binary" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: selenium-manager-macos-debug path: selenium-manager-macos-debug.tar @@ -212,7 +233,7 @@ jobs: name: "Release Binaries" runs-on: ubuntu-latest needs: [macos-stable, linux-stable, windows-stable, macos-debug, linux-debug, windows-debug] - if: github.event_name != 'schedule' && github.repository_owner == 'seleniumhq' && github.ref == 'refs/heads/trunk' + if: github.event_name != 'schedule' && github.repository_owner == 'seleniumhq' && (github.ref == 'refs/heads/trunk' || inputs.release == 'true') steps: - name: "Checkout selenium_manager_artifacts" uses: actions/checkout@v4 @@ -220,7 +241,7 @@ jobs: token: ${{ secrets.SELENIUM_CI_TOKEN }} repository: SeleniumHQ/selenium_manager_artifacts - name: "Download Artifacts" - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: path: artifacts - name: "Prepare and Commit" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e49f53bbc8b33..93486387057476 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,10 +9,6 @@ on: - cron: "0 */12 * * *" workflow_dispatch: -concurrency: - group: ${{ github.workflow }}-${{ github.ref }}${{ github.event_name == 'workflow_dispatch' && '-all' || '' }}${{ github.event_name == 'schedule' && '-all' || '' }} - cancel-in-progress: true - jobs: check: name: Check @@ -40,7 +36,7 @@ jobs: id: check-targets run: ./scripts/github-actions/check-bazel-targets.sh env: - COMMIT_RANGE: ${{ github.event.pull_request.base.sha || github.event.before }}..${{ github.event.pull_request.head.sha || github.sha }} + COMMIT_RANGE: ${{ github.event.pull_request.base.sha || github.event.before }}...${{ github.event.pull_request.head.sha || github.sha }} dotnet: name: .NET diff --git a/.github/workflows/pin-browsers.yml b/.github/workflows/pin-browsers.yml new file mode 100644 index 00000000000000..20bf9b7699e638 --- /dev/null +++ b/.github/workflows/pin-browsers.yml @@ -0,0 +1,51 @@ +name: Pin Browsers +on: + schedule: + - cron: 10 0 * * * + workflow_dispatch: + +jobs: + update: + name: Update Pinned Browsers + uses: ./.github/workflows/bazel.yml + with: + name: Pin Browsers + cache-key: pin-browsers + run: bazel run //scripts:pinned_browsers + artifact-name: pinned-browsers + + pull-request: + if: github.repository_owner == 'seleniumhq' + runs-on: ubuntu-latest + needs: update + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Download patch + uses: actions/download-artifact@v4 + with: + name: pinned-browsers + - name: Apply Patch + run: | + git apply changes.patch + rm changes.patch + - name: Check Changes + run: | + if [[ -n $(git status --porcelain common/repositories.bzl) ]]; then + echo "CHANGES_FOUND=true" >> $GITHUB_ENV + fi + - name: Create Pull Request + if: env.CHANGES_FOUND == 'true' + uses: peter-evans/create-pull-request@v5 + with: + token: ${{ secrets.SELENIUM_CI_TOKEN }} + add-paths: common/repositories.bzl + commit-message: "Update pinned browser versions" + committer: Selenium CI Bot + author: Selenium CI Bot + title: "[dotnet][rb][java][js][py] Automated Browser Version Update" + body: | + This is an automated pull request to update pinned browsers and drivers + + Merge after verify the new browser versions properly passing the tests and no bugs need to be filed + branch: "pinned-browser-updates" diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml new file mode 100644 index 00000000000000..5932de8bb43d6a --- /dev/null +++ b/.github/workflows/pre-release.yml @@ -0,0 +1,110 @@ +name: Release Preparation + +on: + workflow_dispatch: + inputs: + version: + description: 'Selenium version to release' + required: true + chrome_channel: + description: 'Chrome Channel for CDP' + required: true + type: choice + default: "stable" + options: + - stable + - early-stable + +jobs: + update-rust: + name: Update Rust Version + runs-on: ubuntu-latest + steps: + - name: "Checkout repo" + uses: actions/checkout@v4 + with: + persist-credentials: false + fetch-depth: 0 + fetch-tags: true + - name: "Prep git" + run: | + git config --local user.email "selenium-ci@users.noreply.github.com" + git config --local user.name "Selenium CI Bot" + if git rev-parse --verify release-${{ github.event.inputs.version }} >/dev/null 2>&1; then + git branch -D release-${{ github.event.inputs.version }} + fi + git checkout -b release-${{ github.event.inputs.version }} + - name: Update Rust Version + run: | + ./go rust:version + ./go rust:version:commit + - name: Push changes + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.SELENIUM_CI_TOKEN }} + branch: release-${{ github.event.inputs.version }} + force: true + + selenium-manager: + name: Release Selenium Manager + needs: update-rust + uses: ./.github/workflows/ci-rust.yml + with: + release: true + branch: release-${{ github.event.inputs.version }} + secrets: + SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }} + + update-files: + name: Update Files + runs-on: ubuntu-latest + needs: selenium-manager + steps: + - name: "Checkout project" + uses: actions/checkout@v4 + with: + persist-credentials: false + fetch-depth: 0 + fetch-tags: true + ref: release-${{ github.event.inputs.version }} + - name: Install Ruby + uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1 + with: + ruby-version: '3.1' + - name: "Prep git" + run: | + git config --local user.email "selenium-ci@users.noreply.github.com" + git config --local user.name "Selenium CI Bot" + - name: Undo rust changelog commit + run: git reset HEAD~1 + - name: Update everything including early release CDP + if: ${{ github.event.inputs.chrome_channel == 'early-stable' }} + run: ./go all:prepare['Beta'] + - name: Update everything including released CDP + if: ${{ github.event.inputs.chrome_channel == 'stable' }} + run: ./go all:prepare + - name: Create Pull Request + uses: peter-evans/create-pull-request@v5 + with: + token: ${{ secrets.SELENIUM_CI_TOKEN }} + author: Selenium CI Bot + delete-branch: true + title: "[build] Prepare for release of Selenium ${{ github.event.inputs.version }}" + body: | + **Warning: Manually update the changelogs before merging** + + This PR: + * Updates Rust version for Selenium Manager release + * Updates Pinned browser version to coincide with new CDP release + * Adds support for new CDP version and removes old CDP version + * Selenium Manager references the new Selenium Manager release + * Updates Maven Dependencies + * Adds new authors to authors file + * Updates all versions for all bindings + * Generates *rough* change logs for each bindings (please tidy them up before merging this) + + - Auto-generated by [create-pull-request][1] + + [1]: https://github.com/peter-evans/create-pull-request + labels: C-build + draft: true diff --git a/AUTHORS b/AUTHORS index bf3f3d9a6ec5e5..c854b4ff261939 100644 --- a/AUTHORS +++ b/AUTHORS @@ -87,6 +87,7 @@ Ashley Trinh Aslak Hellesøy asmundak Atsushi Tatsuma +Aurélien Pupier Austin Michael Wilkins <42476341+amwilkins@users.noreply.github.com> BaerMitUmlaut Baran Ozgul @@ -234,6 +235,7 @@ Dvoryadkin Pavel <52860505+DvoryadkinPavel@users.noreply.github.com> Dylan Lacey Dylan Reichstadt Dylan Semler +Earlopain <14981592+Earlopain@users.noreply.github.com> Eberhard Beilharz Edi Weissmann Edirin Atumah @@ -354,6 +356,7 @@ Jake Garelick Jake Klingensmith Jakub Vrána jamadam +James Braza James Cooper James Garbutt <43081j@users.noreply.github.com> James Hilliard @@ -573,6 +576,7 @@ Michał Herda Michele Sama Mickaël Schoentgen Microsoft Provenance Contributions +middlingphys <38708390+middlingphys@users.noreply.github.com> Miguel Carboni Mike Bellew Mike Melia @@ -731,6 +735,7 @@ seanrand57 Sebastian Meyer Sebastian Monte Sebastien Guillemot +seidnerj Selenium CI Bot Sen ZmaKi <90490506+SenZmaKi@users.noreply.github.com> Sergey Chipiga @@ -773,6 +778,7 @@ sugama sunnyyukaige symonk Take +take0x <89313929+take0x@users.noreply.github.com> Takeshi Kishi Takuho NAKANO Takuma Chiba diff --git a/Rakefile b/Rakefile index 9263ee9bb7c64b..9c4d1f2d4b16e0 100644 --- a/Rakefile +++ b/Rakefile @@ -45,7 +45,6 @@ require 'rake_tasks/bazel/task' # These are the final items mixed into the global NS # These need moving into correct namespaces, and not be globally included require 'rake_tasks/bazel' -require 'rake_tasks/copyright' require 'rake_tasks/python' $DEBUG = orig_verbose != Rake::FileUtilsExt::DEFAULT @@ -102,7 +101,7 @@ JAVA_RELEASE_TARGETS = %w[ //java/src/org/openqa/selenium/chromium:chromium.publish //java/src/org/openqa/selenium/devtools/v119:v119.publish //java/src/org/openqa/selenium/devtools/v120:v120.publish - //java/src/org/openqa/selenium/devtools/v118:v118.publish + //java/src/org/openqa/selenium/devtools/v121:v121.publish //java/src/org/openqa/selenium/devtools/v85:v85.publish //java/src/org/openqa/selenium/edge:edge.publish //java/src/org/openqa/selenium/firefox:firefox.publish @@ -440,39 +439,6 @@ task :authors do sh "(git log --use-mailmap --format='%aN <%aE>' ; cat .OLD_AUTHORS) | sort -uf > AUTHORS" end -namespace :copyright do - desc 'Update Copyright notices on all files in repo' - task :update do - Copyright.new.update( - FileList['javascript/**/*.js'].exclude( - 'javascript/atoms/test/jquery.min.js', - 'javascript/jsunit/**/*.js', - 'javascript/node/selenium-webdriver/node_modules/**/*.js', - 'javascript/selenium-core/lib/**/*.js', - 'javascript/selenium-core/scripts/ui-element.js', - 'javascript/selenium-core/scripts/ui-map-sample.js', - 'javascript/selenium-core/scripts/user-extensions.js', - 'javascript/selenium-core/scripts/xmlextras.js', - 'javascript/selenium-core/xpath/**/*.js', - 'javascript/grid-ui/node_modules/**/*.js' - ) - ) - Copyright.new.update(FileList['javascript/**/*.tsx']) - Copyright.new(comment_characters: '#').update(FileList['py/**/*.py'].exclude( - 'py/selenium/webdriver/common/bidi/cdp.py', - 'py/generate.py', - 'py/selenium/webdriver/common/devtools/**/*', - 'py/venv/**/*' - )) - Copyright.new(comment_characters: '#', prefix: ["# frozen_string_literal: true\n", "\n"]) - .update(FileList['rb/**/*.rb']) - Copyright.new.update(FileList['java/**/*.java']) - Copyright.new.update(FileList['rust/**/*.rs']) - - sh './scripts/format.sh' - end -end - namespace :side do task atoms: [ '//javascript/atoms/fragments:find-element' @@ -525,7 +491,7 @@ namespace :node do desc 'Build Node npm package' task :build, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : [] + args = Array(arguments[:args]) || [] Bazel.execute('build', args, '//javascript/node/selenium-webdriver') end @@ -557,9 +523,11 @@ namespace :node do old_version = node_version new_version = updated_version(old_version, arguments[:version]) - file = 'javascript/node/selenium-webdriver/package.json' - text = File.read(file).gsub(old_version, new_version) - File.open(file, "w") { |f| f.puts text } + ['javascript/node/selenium-webdriver/package.json', + 'javascript/node/selenium-webdriver/package-lock.json'].each do |file| + text = File.read(file).gsub(old_version, new_version) + File.open(file, "w") { |f| f.puts text } + end Rake::Task['node:changelog'].invoke end @@ -573,22 +541,21 @@ end namespace :py do desc 'Build Python wheel and sdist with optional arguments' task :build, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : [] + args = Array(arguments[:args]) || [] Bazel.execute('build', args, '//py:selenium-wheel') Bazel.execute('build', args, '//py:selenium-sdist') end desc 'Release Python wheel and sdist to pypi' task :release, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : ['--stamp'] - Rake::Task['py:build'].invoke(args) - sh "python3 -m twine upload `bazel-bin/py/selenium`-#{python_version}-py3-none-any.whl" - sh "python3 -m twine upload bazel-bin/py/selenium-#{python_version}.tar.gz" + args = Array(arguments[:args]) || ['--stamp'] + Bazel.execute('run', args, '//py:selenium-release') end - desc 'Update generated Python files for local development' - task :update do + desc 'generate and copy files required for local development' + task :local_dev do Bazel.execute('build', [], '//py:selenium') + Rake::Task['grid'].invoke FileUtils.rm_rf('py/selenium/webdriver/common/devtools/') FileUtils.cp_r('bazel-bin/py/selenium/webdriver/.', 'py/selenium/webdriver', remove_destination: true) @@ -666,30 +633,42 @@ namespace :py do File.open(file, "w") { |f| f.puts text } end + old_short_version = old_version.split('.')[0..1].join('.') + new_short_version = new_version.split('.')[0..1].join('.') + + text = File.read('py/docs/source/conf.py').gsub(old_short_version, new_short_version) + File.open('py/docs/source/conf.py', "w") { |f| f.puts text } + Rake::Task['py:changelog'].invoke end desc 'Update Python Syntax' task :lint do - `tox -c py/tox.ini -e linting` + sh 'tox -c py/tox.ini -e linting' end - namespace :test do - desc 'Python unit tests' - task :unit do + namespace :test do + desc 'Python unit tests' + task :unit do + Rake::Task['py:clean'].invoke + Bazel.execute('test', ['--test_size_filters=small'], '//py/...') + end + + %i[chrome edge firefox safari].each do |browser| + desc "Python #{browser} tests" + task browser do Rake::Task['py:clean'].invoke - Bazel.execute('test', ['--test_size_filters=small'], '//py/...') + Bazel.execute('test', [],"//py:common-#{browser}") + Bazel.execute('test', [],"//py:test-#{browser}") end + end - %i[chrome edge firefox safari].each do |browser| - desc "Python #{browser} tests" - task browser do - Rake::Task['py:clean'].invoke - Bazel.execute('test', [],"//py:common-#{browser}") - Bazel.execute('test', [],"//py:test-#{browser}") - end - end + desc "Python Remote tests with Firefox" + task :remote do + Rake::Task['py:clean'].invoke + Bazel.execute('test', [],"//py:test-remote") end + end end def ruby_version @@ -700,13 +679,15 @@ end namespace :rb do desc 'Generate Ruby gems' task :build, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : [] - Bazel.execute('build', args, '//rb:selenium-webdriver') - Bazel.execute('build', args, '//rb:selenium-devtools') + args = Array(arguments[:args]) || [] + webdriver = args.reject! { |item| item == 'webdriver' } + devtools = args.reject! { |item| item == 'devtools' } + Bazel.execute('build', args, '//rb:selenium-webdriver') if webdriver + Bazel.execute('build', args, '//rb:selenium-devtools') if devtools end desc 'Update generated Ruby files for local development' - task :update do + task :local_dev do Bazel.execute('build', [], '@bundle//:bundle') Rake::Task['rb:build'].invoke Rake::Task['grid'].invoke @@ -714,9 +695,9 @@ namespace :rb do desc 'Push Ruby gems to rubygems' task :release, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : ['--stamp'] - Bazel.execute('run', args, '//rb:selenium-webdriver') - Bazel.execute('run', args, '//rb:selenium-devtools') + args = Array(arguments[:args]) || ['--stamp'] + Bazel.execute('run', args, '//rb:selenium-webdriver-release') + Bazel.execute('run', args, '//rb:selenium-devtools-release') end desc 'Generate Ruby documentation' @@ -765,26 +746,26 @@ end namespace :dotnet do desc 'Build nupkg files' task :build, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : [] + args = Array(arguments[:args]) || [] Bazel.execute('build', args, '//dotnet:all') end desc 'Create zipped assets for .NET for uploading to GitHub' task :zip_assets, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : ['--stamp'] + args = Array(arguments[:args]) || ['--stamp'] Rake::Task['dotnet:build'].invoke(args) mkdir_p 'build/dist' FileUtils.rm_f('build/dist/*dotnet*') FileUtils.copy('bazel-bin/dotnet/release.zip', "build/dist/selenium-dotnet-#{dotnet_version}.zip") - FileUtils.chmod(666, "build/dist/selenium-dotnet-#{dotnet_version}.zip") + FileUtils.chmod(0666, "build/dist/selenium-dotnet-#{dotnet_version}.zip") FileUtils.copy('bazel-bin/dotnet/strongnamed.zip', "build/dist/selenium-dotnet-strongnamed-#{dotnet_version}.zip") - FileUtils.chmod(666, "build/dist/selenium-dotnet-strongnamed-#{dotnet_version}.zip") + FileUtils.chmod(0666, "build/dist/selenium-dotnet-strongnamed-#{dotnet_version}.zip") end desc 'Upload nupkg files to Nuget' task :release, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : ['--stamp'] + args = Array(arguments[:args]) || ['--stamp'] Rake::Task['dotnet:build'].invoke(args) Rake::Task['dotnet:zip_assets'].invoke(args) @@ -845,26 +826,26 @@ end namespace :java do desc 'Build Java Client Jars' task :build, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : [] + args = Array(arguments[:args]) || [] Bazel.execute('build', args, '//java/src/org/openqa/selenium:client-combined') end desc 'Build Grid Jar' task :grid, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : [] + args = Array(arguments[:args]) || [] Bazel.execute('build', args, '//java/src/org/openqa/selenium/grid:grid') end desc 'Package Java bindings and grid into releasable packages' task :package, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : [] + args = Array(arguments[:args]) || [] Rake::Task['java:build'].invoke(args) Rake::Task['java-release-zip'].invoke end desc 'Deploy all jars to Maven' task :release, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : ['--stamp'] + args = Array(arguments[:args]) || ['--stamp'] Rake::Task['java:package'].invoke(args) Rake::Task['publish-maven'].invoke end @@ -928,7 +909,7 @@ namespace :java do file = 'java/version.bzl' text = File.read(file).gsub(old_version, new_version) File.open(file, "w") { |f| f.puts text } - Rake::Task['java:changelog'].invoke unless old_version.include?('SNAPSHOT') + Rake::Task['java:changelog'].invoke if old_version.include?('SNAPSHOT') end end @@ -940,7 +921,7 @@ end namespace :rust do desc 'Build Selenium Manager' task :build, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : [] + args = Array(arguments[:args]) || [] Bazel.execute('build', args, '//rust:selenium-manager') end @@ -956,6 +937,8 @@ namespace :rust do update_changelog(version, 'rust', 'rust/src', 'rust/CHANGELOG.md', header) end + # Rust versioning is currently difficult compared to the others because we are using the 0.4.x pattern + # until Selenium Manager comes out of beta desc 'Update Rust version' task :version, [:version] do |_task, arguments| old_version = rust_version.dup @@ -976,6 +959,18 @@ namespace :rust do Rake::Task['rust:changelog'].invoke unless new_version.include?('nightly') Rake::Task['rust:update'].invoke end + + # Creating a special task for this because Rust version needs to be managed at a different place than + # everything else; want to use changelog updates later in process + namespace :version do + desc 'Commits updates from Rust version changes' + task :commit do + @git.reset + commit!("update Rust version to #{rust_version}", + ['rust/BUILD.bazel', 'rust/Cargo.Bazel.lock', 'rust/Cargo.lock', 'rust/Cargo.toml']) + commit!('Rust Changelog', ['rust/CHANGELOG.md']) + end + end end namespace :all do @@ -995,7 +990,7 @@ namespace :all do desc 'Build all artifacts for all language bindings' task :build, [:args] do |_task, arguments| - args = arguments[:args] ? [arguments[:args]] : [] + args = Array(arguments[:args]) || [] Rake::Task['java:build'].invoke(args) Rake::Task['py:build'].invoke(args) Rake::Task['rb:build'].invoke(args) @@ -1009,7 +1004,7 @@ namespace :all do tag = @git.add_tag("selenium-#{java_version}") @git.push('origin', tag.name) - args = arguments[:args] ? [arguments[:args]] : ['--stamp'] + args = Array(arguments[:args]) || ['--stamp'] Rake::Task['java:release'].invoke(args) Rake::Task['py:release'].invoke(args) Rake::Task['rb:release'].invoke(args) @@ -1017,29 +1012,73 @@ namespace :all do Rake::Task['node:release'].invoke(args) Rake::Task['create_release_notes'].invoke(args) Rake::Task['all:docs'].invoke - Rake::Task['all:version'].invoke(['nightly']) + Rake::Task['all:version'].invoke('nightly') - puts "Staging nightly version updates" - @git.add(['java/version.bzl', 'rb/lib/selenium/webdriver/version.rb'], all: true) puts "Committing nightly version updates" - @git.commit('updating versions to nightly') - puts "Pushing changes to upstream repository" - - print 'Do you want to commit the changes? (Y/n): ' + commit!('update versions to nightly', ['java/version.bzl', + 'rb/lib/selenium/webdriver/version.rb', + 'rb/Gemfile.lock', + 'rust/BUILD.bazel', + 'rust/Cargo.Bazel.lock', + 'rust/Cargo.lock', + 'rust/Cargo.toml']) + + print 'Do you want to push the committed changes? (Y/n): ' response = STDIN.gets.chomp.downcase @git.push if response == 'y' || response == 'yes' end - desc 'File updates for versions and metadata' - task :update, [:channel] do |_task, arguments| - args = arguments[:channel] ? ['--', "--chrome_channel=#{arguments[:channel].capitalize}"] : [] - Bazel.execute('run', args, '//scripts:update_cdp') - Bazel.execute('run', args, '//scripts:pinned_browsers') - Bazel.execute('run', args, '//scripts:selenium_manager') - Rake::Task['java:dependencies'].invoke - Rake::Task['authors'].invoke - Rake::Task['copyright:update'].invoke - end + desc 'Update everything in preparation for a release' + task :prepare, [:channel] do |_task, arguments| + args = Array(arguments[:channel]) ? ['--', "--chrome_channel=#{arguments[:channel].capitalize}"] : [] + Bazel.execute('run', args, '//scripts:pinned_browsers') + commit!('Update pinned browser versions', ['common/repositories.bzl']) + + Bazel.execute('run', args, '//scripts:update_cdp') + commit!('Update supported versions for Chrome DevTools', + ['common/devtools/', + 'dotnet/src/webdriver/DevTools/', + 'dotnet/src/webdriver/WebDriver.csproj', + 'dotnet/test/common/DevTools/', + 'dotnet/test/common/CustomDriverConfigs/', + 'dotnet/selenium-dotnet-version.bzl', + 'java/src/org/openqa/selenium/devtools/', + 'javascript/node/selenium-webdriver/BUILD.bazel', + 'py/BUILD.bazel', + 'rb/lib/selenium/devtools/', + 'rb/Gemfile.lock', + 'Rakefile']) + + Bazel.execute('run', args, '//scripts:selenium_manager') + commit!('Update selenium manager version', ['common/selenium_manager.bzl']) + + Rake::Task['java:update'].invoke + commit!('Update Maven Dependencies', ['java/maven_deps.bzl', 'java/maven_install.json']) + + Rake::Task['authors'].invoke + commit!('Update authors file', ['AUTHORS']) + + # Note that this does not include Rust version changes that are handled in separate rake:version task + Rake::Task['all:version'].invoke + commit!("FIX CHANGELOGS BEFORE MERGING!\n\nUpdate versions and change logs to release Selenium #{java_version}", + ['dotnet/CHANGELOG', + 'dotnet/selenium-dotnet-version.bzl', + 'java/CHANGELOG', + 'java/version.bzl', + 'javascript/node/selenium-webdriver/CHANGES.md', + 'javascript/node/selenium-webdriver/package.json', + 'javascript/node/selenium-webdriver/package-lock.json', + 'py/docs/source/conf.py', + 'py/selenium/__init__.py', + 'py/selenium/webdriver/__init__.py', + 'py/BUILD.bazel', + 'py/CHANGES', + 'py/setup.py', + 'rb/lib/selenium/webdriver/version.rb', + 'rb/CHANGES', + 'rb/Gemfile.lock', + 'rust/CHANGELOG.md']) + end desc 'Update all versions' task :version, [:version] do |_task, arguments| @@ -1054,7 +1093,6 @@ namespace :all do Rake::Task['node:version'].invoke(version) Rake::Task['py:version'].invoke(version) Rake::Task['dotnet:version'].invoke(version) - Rake::Task['rust:version'].invoke(version) end end end @@ -1066,28 +1104,28 @@ end desc 'Create Release Notes for Minor Release' task :create_release_notes do range = "#{previous_tag(java_version)}...HEAD" - format = "* [\\`%h\\`](http://github.com/seleniumhq/selenium/commit/%H) - %s :: %an" - git_log_command = %Q(git --no-pager log "#{range}" --pretty=format:"#{format}"--reverse) + format = "* [\\`%h\\`](http://github.com/seleniumhq/selenium/commit/%H) - %s :: %aN" + git_log_command = %Q(git --no-pager log "#{range}" --pretty=format:"#{format}" --reverse) git_log_output = `#{git_log_command}` release_notes = <<~RELEASE_NOTES - ### Changelog + ### Changelog - For each component's detailed changelog, please check: - * [Ruby](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES) - * [Python](https://github.com/SeleniumHQ/selenium/blob/trunk/py/CHANGES) - * [JavaScript](https://github.com/SeleniumHQ/selenium/blob/trunk/javascript/node/selenium-webdriver/CHANGES.md) - * [Java](https://github.com/SeleniumHQ/selenium/blob/trunk/java/CHANGELOG) - * [DotNet](https://github.com/SeleniumHQ/selenium/blob/trunk/dotnet/CHANGELOG) - * [IEDriverServer](https://github.com/SeleniumHQ/selenium/blob/trunk/cpp/iedriverserver/CHANGELOG) + For each component's detailed changelog, please check: + * [Ruby](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES) + * [Python](https://github.com/SeleniumHQ/selenium/blob/trunk/py/CHANGES) + * [JavaScript](https://github.com/SeleniumHQ/selenium/blob/trunk/javascript/node/selenium-webdriver/CHANGES.md) + * [Java](https://github.com/SeleniumHQ/selenium/blob/trunk/java/CHANGELOG) + * [DotNet](https://github.com/SeleniumHQ/selenium/blob/trunk/dotnet/CHANGELOG) + * [IEDriverServer](https://github.com/SeleniumHQ/selenium/blob/trunk/cpp/iedriverserver/CHANGELOG) - ### Commits in this release -
- Click to see all the commits included in this release + ### Commits in this release +
+ Click to see all the commits included in this release - #{git_log_output} + #{git_log_output} -
+
RELEASE_NOTES FileUtils.mkdir_p('build/dist') @@ -1158,15 +1196,12 @@ def update_gh_pages end end - puts "Staging changes for commit" - @git.add('docs/api', all: true) - print 'Do you want to commit the changes? (Y/n): ' response = STDIN.gets.chomp.downcase return restore_git(origin_reference) unless response == 'y' || response == 'yes' puts "Committing changes" - @git.commit('updating all API docs') + commit!('updating all API docs', 'docs/api/') puts "Pushing changes to upstream repository" @git.push @@ -1229,3 +1264,13 @@ def update_changelog(version, language, path, changelog, header) file.truncate(file.pos) end end + +def commit!(message, files = [], all: false) + files.each do |file| + puts "adding: #{file}" + @git.add(file) + end + all ? @git.commit_all(message) : @git.commit(message) +rescue Git::FailedError => ex + puts ex.message +end diff --git a/common/devtools/chromium/v118/BUILD.bazel b/common/devtools/chromium/v121/BUILD.bazel similarity index 100% rename from common/devtools/chromium/v118/BUILD.bazel rename to common/devtools/chromium/v121/BUILD.bazel diff --git a/common/devtools/chromium/v118/browser_protocol.pdl b/common/devtools/chromium/v121/browser_protocol.pdl similarity index 97% rename from common/devtools/chromium/v118/browser_protocol.pdl rename to common/devtools/chromium/v121/browser_protocol.pdl index f19168c9ea39f1..6c81e477a29fbc 100644 --- a/common/devtools/chromium/v118/browser_protocol.pdl +++ b/common/devtools/chromium/v121/browser_protocol.pdl @@ -498,6 +498,7 @@ experimental domain Audits WarnAttributeValueExceedsMaxSize WarnDomainNonASCII WarnThirdPartyPhaseout + WarnCrossSiteRedirectDowngradeChangesInclusion type CookieOperation extends string enum @@ -553,6 +554,7 @@ experimental domain Audits Script ServiceWorker SharedWorker + SpeculationRules Stylesheet Track Video @@ -770,6 +772,15 @@ experimental domain Audits properties array of string trackingSites + # This issue warns about third-party sites that are accessing cookies on the + # current page, and have been permitted due to having a global metadata grant. + # Note that in this context 'site' means eTLD+1. For example, if the URL + # `https://example.test:80/web_page` was accessing cookies, the site reported + # would be `example.test`. + type CookieDeprecationMetadataIssueDetails extends object + properties + array of string allowedSites + type ClientHintIssueReason extends string enum # Items in the accept-ch meta tag allow list must be valid origins. @@ -817,6 +828,8 @@ experimental domain Audits IdTokenHttpNotFound IdTokenNoResponse IdTokenInvalidResponse + IdTokenIdpErrorResponse + IdTokenCrossSiteIdpErrorResponse IdTokenInvalidRequest IdTokenInvalidContentType ErrorIdToken @@ -824,6 +837,7 @@ experimental domain Audits RpPageNotVisible SilentMediationFailure ThirdPartyCookiesBlocked + NotSignedInWithIdp type FederatedAuthUserInfoRequestIssueDetails extends object properties @@ -874,6 +888,24 @@ experimental domain Audits # Contains additional info when the failure was due to a request. optional FailedRequestInfo failedRequestInfo + type PropertyRuleIssueReason extends string + enum + InvalidSyntax + InvalidInitialValue + InvalidInherits + InvalidName + + # This issue warns about errors in property rules that lead to property + # registrations being ignored. + type PropertyRuleIssueDetails extends object + properties + # Source code position of the property rule. + SourceCodeLocation sourceCodeLocation + # Reason why the property rule was discarded. + PropertyRuleIssueReason propertyRuleIssueReason + # The value of the property rule property that failed to parse + optional string propertyValue + # A unique identifier for the type of issue. Each type may use one of the # optional fields in InspectorIssueDetails to convey more specific # information about the kind of issue. @@ -896,8 +928,10 @@ experimental domain Audits ClientHintIssue FederatedAuthRequestIssue BounceTrackingIssue + CookieDeprecationMetadataIssue StylesheetLoadingIssue FederatedAuthUserInfoRequestIssue + PropertyRuleIssue # This struct holds a list of optional fields with additional information # specific to the kind of issue. When adding a new issue code, please also @@ -920,7 +954,9 @@ experimental domain Audits optional ClientHintIssueDetails clientHintIssueDetails optional FederatedAuthRequestIssueDetails federatedAuthRequestIssueDetails optional BounceTrackingIssueDetails bounceTrackingIssueDetails + optional CookieDeprecationMetadataIssueDetails cookieDeprecationMetadataIssueDetails optional StylesheetLoadingIssueDetails stylesheetLoadingIssueDetails + optional PropertyRuleIssueDetails propertyRuleIssueDetails optional FederatedAuthUserInfoRequestIssueDetails federatedAuthUserInfoRequestIssueDetails # A unique id for a DevTools inspector issue. Allows other entities (e.g. @@ -1216,7 +1252,7 @@ domain Browser prompt # Definition of PermissionDescriptor defined in the Permissions API: - # https://w3c.github.io/permissions/#dictdef-permissiondescriptor. + # https://w3c.github.io/permissions/#dom-permissiondescriptor. experimental type PermissionDescriptor extends object properties # Name of permission. @@ -1812,6 +1848,8 @@ experimental domain CSS properties # Font's family name reported by platform. string familyName + # Font's PostScript name reported by platform. + string postScriptName # Indicates if the font was downloaded or resolved locally. boolean isCustomFont # Amount of glyphs that were rendered with this font. @@ -1891,6 +1929,19 @@ experimental domain CSS string syntax + # CSS font-palette-values rule representation. + type CSSFontPaletteValuesRule extends object + properties + # The css style sheet identifier (absent for user agent stylesheet and user-specified + # stylesheet rules) this rule came from. + optional StyleSheetId styleSheetId + # Parent stylesheet's origin. + StyleSheetOrigin origin + # Associated font palette name. + Value fontPaletteName + # Associated style declaration. + CSSStyle style + # CSS property at-rule representation. type CSSPropertyRule extends object properties @@ -2035,6 +2086,8 @@ experimental domain CSS optional array of CSSPropertyRule cssPropertyRules # A list of CSS property registrations matching this node. optional array of CSSPropertyRegistration cssPropertyRegistrations + # A font-palette-values rule matching this node. + optional CSSFontPaletteValuesRule cssFontPaletteValuesRule # Id of the first parent element that does not have display: contents. experimental optional DOM.NodeId parentLayoutNodeId @@ -2095,6 +2148,16 @@ experimental domain CSS string propertyName string value + # Modifies the property rule property name. + command setPropertyRulePropertyName + parameters + StyleSheetId styleSheetId + SourceRange range + string propertyName + returns + # The resulting key text after modification. + Value propertyName + # Modifies the keyframe rule key text. command setKeyframeKey parameters @@ -3238,7 +3301,6 @@ domain DOM # execution will stop on these operations as if there was a regular breakpoint set. domain DOMDebugger depends on DOM - depends on Debugger depends on Runtime # DOM breakpoint type. @@ -3310,7 +3372,8 @@ domain DOMDebugger experimental optional string targetName # Removes breakpoint on particular native event. - experimental command removeInstrumentationBreakpoint + experimental deprecated command removeInstrumentationBreakpoint + redirect EventBreakpoints parameters # Instrumentation name to stop on. string eventName @@ -3345,7 +3408,8 @@ domain DOMDebugger experimental optional string targetName # Sets breakpoint on particular native event. - experimental command setInstrumentationBreakpoint + experimental deprecated command setInstrumentationBreakpoint + redirect EventBreakpoints parameters # Instrumentation name to stop on. string eventName @@ -3356,10 +3420,9 @@ domain DOMDebugger # Resource URL substring. All XHRs having this substring in the URL will get stopped upon. string url -# EventBreakpoints permits setting breakpoints on particular operations and -# events in targets that run JavaScript but do not have a DOM. -# JavaScript execution will stop on these operations as if there was a regular -# breakpoint set. +# EventBreakpoints permits setting JavaScript breakpoints on operations and events +# occurring in native code invoked from JavaScript. Once breakpoint is hit, it is +# reported through Debugger domain, similarly to regular breakpoints being hit. experimental domain EventBreakpoints # Sets breakpoint on particular native event. command setInstrumentationBreakpoint @@ -3373,6 +3436,9 @@ experimental domain EventBreakpoints # Instrumentation name to stop on. string eventName + # Removes all breakpoints + command disable + # This domain facilitates obtaining document snapshots with DOM, layout, and style information. experimental domain DOMSnapshot depends on CSS @@ -3851,6 +3917,13 @@ domain Emulation # A display feature that only splits content will have a 0 mask_length. integer maskLength + type DevicePosture extends object + properties + # Current posture of the device + enum type + continuous + folded + type MediaFeature extends object properties string name @@ -3889,6 +3962,49 @@ domain Emulation optional string bitness optional boolean wow64 + # Used to specify sensor types to emulate. + # See https://w3c.github.io/sensors/#automation for more information. + experimental type SensorType extends string + enum + absolute-orientation + accelerometer + ambient-light + gravity + gyroscope + linear-acceleration + magnetometer + proximity + relative-orientation + + experimental type SensorMetadata extends object + properties + optional boolean available + optional number minimumFrequency + optional number maximumFrequency + + experimental type SensorReadingSingle extends object + properties + number value + + experimental type SensorReadingXYZ extends object + properties + number x + number y + number z + + experimental type SensorReadingQuaternion extends object + properties + number x + number y + number z + number w + + experimental type SensorReading extends object + properties + optional SensorReadingSingle single + optional SensorReadingXYZ xyz + optional SensorReadingQuaternion quaternion + # Tells whether emulation is supported. command canEmulate returns @@ -3965,6 +4081,9 @@ domain Emulation # If set, the display feature of a multi-segment screen. If not set, multi-segment support # is turned-off. experimental optional DisplayFeature displayFeature + # If set, the posture of a foldable device. If not set the posture is set + # to continuous. + experimental optional DevicePosture devicePosture experimental command setScrollbarsHidden parameters @@ -4018,6 +4137,30 @@ domain Emulation # Mock accuracy optional number accuracy + experimental command getOverriddenSensorInformation + parameters + SensorType type + returns + number requestedSamplingFrequency + + # Overrides a platform sensor of a given type. If |enabled| is true, calls to + # Sensor.start() will use a virtual sensor as backend rather than fetching + # data from a real hardware sensor. Otherwise, existing virtual + # sensor-backend Sensor objects will fire an error event and new calls to + # Sensor.start() will attempt to use a real sensor instead. + experimental command setSensorOverrideEnabled + parameters + boolean enabled + SensorType type + optional SensorMetadata metadata + + # Updates the sensor readings reported by a sensor type previously overriden + # by setSensorOverrideEnabled. + experimental command setSensorOverrideReadings + parameters + SensorType type + SensorReading reading + # Overrides the Idle state. experimental command setIdleOverride parameters @@ -4120,7 +4263,7 @@ domain Emulation parameters # User agent to use. string userAgent - # Browser langugage to emulate. + # Browser language to emulate. optional string acceptLanguage # The platform navigator.platform should return. optional string platform @@ -4465,9 +4608,9 @@ domain Input # The normalized tangential pressure, which has a range of [-1,1] (default: 0). experimental optional number tangentialPressure # The plane angle between the Y-Z plane and the plane containing both the stylus axis and the Y axis, in degrees of the range [-90,90], a positive tiltX is to the right (default: 0) - experimental optional integer tiltX + optional number tiltX # The plane angle between the X-Z plane and the plane containing both the stylus axis and the X axis, in degrees of the range [-90,90], a positive tiltY is towards the user (default: 0). - experimental optional integer tiltY + optional number tiltY # The clockwise rotation of a pen stylus around its own major axis, in degrees in the range [0,359] (default: 0). experimental optional integer twist # Identifier used to track touch sources between events, must be unique within an event. @@ -4633,9 +4776,9 @@ domain Input # The normalized tangential pressure, which has a range of [-1,1] (default: 0). experimental optional number tangentialPressure # The plane angle between the Y-Z plane and the plane containing both the stylus axis and the Y axis, in degrees of the range [-90,90], a positive tiltX is to the right (default: 0). - experimental optional integer tiltX + optional number tiltX # The plane angle between the X-Z plane and the plane containing both the stylus axis and the X axis, in degrees of the range [-90,90], a positive tiltY is towards the user (default: 0). - experimental optional integer tiltY + optional number tiltY # The clockwise rotation of a pen stylus around its own major axis, in degrees in the range [0,359] (default: 0). experimental optional integer twist # X delta in CSS pixels for mouse wheel event (default: 0). @@ -5547,6 +5690,10 @@ domain Network # This value is used when the reason is unknown. unspecifiedReason + experimental type ServiceWorkerRouterInfo extends object + properties + integer ruleIdMatched + # HTTP response data. type Response extends object properties @@ -5580,6 +5727,8 @@ domain Network optional boolean fromServiceWorker # Specifies that the request was served from the prefetch cache. optional boolean fromPrefetchCache + # Infomation about how Service Worker Static Router was used. + experimental optional ServiceWorkerRouterInfo serviceWorkerRouterInfo # Total number of bytes received for this request so far. number encodedDataLength # Timing information for the given request. @@ -5695,7 +5844,7 @@ domain Network # Cookie Priority experimental CookiePriority priority # True if cookie is SameParty. - experimental boolean sameParty + experimental deprecated boolean sameParty # Cookie source scheme type. experimental CookieSourceScheme sourceScheme # Cookie source port. Valid values are {-1, [1, 65535]}, -1 indicates an unspecified port. @@ -5726,6 +5875,8 @@ domain Network SameSiteNoneInsecure # The cookie was not stored due to user preferences. UserPreferences + # The cookie was blocked due to third-party cookie phaseout. + ThirdPartyPhaseout # The cookie was blocked by third-party cookie blocking between sites in # the same First-Party Set. ThirdPartyBlockedInFirstPartySet @@ -5771,6 +5922,8 @@ domain Network # character if it appears in the middle of the cookie name, value, an # attribute name, or an attribute value. DisallowedCharacter + # Cookie contains no content or only whitespace. + NoCookieContent # Types of reasons why a cookie may not be sent with a request. experimental type CookieBlockedReason extends string @@ -5797,6 +5950,8 @@ domain Network SameSiteNoneInsecure # The cookie was not sent due to user preferences. UserPreferences + # The cookie was blocked due to third-party cookie phaseout. + ThirdPartyPhaseout # The cookie was blocked by third-party cookie blocking between sites in # the same First-Party Set. ThirdPartyBlockedInFirstPartySet @@ -6291,7 +6446,7 @@ domain Network parameters # User agent to use. string userAgent - # Browser langugage to emulate. + # Browser language to emulate. optional string acceptLanguage # The platform navigator.platform should return. optional string platform @@ -7071,6 +7226,16 @@ experimental domain Overlay # The content box highlight outline color (default: transparent). optional DOM.RGBA outlineColor + # Configuration for Window Controls Overlay + type WindowControlsOverlayConfig extends object + properties + # Whether the title bar CSS should be shown when emulating the Window Controls Overlay. + boolean showCSS + # Seleted platforms to show the overlay. + string selectedPlatform + # The theme color defined in app manifest. + string themeColor + type ContainerQueryHighlightConfig extends object properties # A descriptor for the highlight appearance of container query containers. @@ -7321,6 +7486,12 @@ experimental domain Overlay # An array of node identifiers and descriptors for the highlight appearance. array of IsolatedElementHighlightConfig isolatedElementHighlightConfigs + # Show Window Controls Overlay for PWA + command setShowWindowControlsOverlay + parameters + # Window Controls Overlay data, null means hide Window Controls Overlay + optional WindowControlsOverlayConfig windowControlsOverlayConfig + # Fired when the node should be inspected. This happens after call to `setInspectMode` or when # user manually inspects an element. event inspectNodeRequested @@ -7491,7 +7662,9 @@ domain Page sync-xhr unload usb + usb-unrestricted vertical-scroll + web-printing web-share # Alias for 'window-placement' (crbug.com/1328581). window-management @@ -8000,16 +8173,6 @@ domain Page # as an ad. Only sent if frame is labelled as an ad and id is available. optional AdScriptId adScriptId - # Returns all browser cookies for the page and all of its subframes. Depending - # on the backend support, will return detailed cookie information in the - # `cookies` field. - experimental deprecated command getCookies - # Use 'Network.getCookies' instead - redirect Network - returns - # Array of cookie objects. - array of Network.Cookie cookies - # Returns present frame tree structure. command getFrameTree returns @@ -8152,6 +8315,8 @@ domain Page ReturnAsStream # Whether or not to generate tagged (accessible) PDF. Defaults to embedder choice. experimental optional boolean generateTaggedPDF + # Whether or not to embed the document outline into the PDF. + experimental optional boolean generateDocumentOutline returns # Base64-encoded pdf data. Empty if |returnAsStream| is specified. binary data @@ -8751,6 +8916,17 @@ domain Page PageSupportNeeded Circumstantial + experimental type BackForwardCacheBlockingDetails extends object + properties + # Url of the file where blockage happened. Optional because of tests. + optional string url + # Function name where blockage happened. Optional because of anonymous functions and tests. + optional string function + # Line number in the script (0-based). + integer lineNumber + # Column number in the script (0-based). + integer columnNumber + experimental type BackForwardCacheNotRestoredExplanation extends object properties # Type of the reason @@ -8762,6 +8938,7 @@ domain Page # - EmbedderExtensionSentMessageToCachedFrame: the extension ID. # optional string context + optional array of BackForwardCacheBlockingDetails details experimental type BackForwardCacheNotRestoredExplanationTree extends object properties @@ -9197,6 +9374,7 @@ experimental domain ServiceWorker optional number scriptResponseTime optional array of Target.TargetID controlledClients optional Target.TargetID targetId + optional string routerRules # ServiceWorker error message. type ServiceWorkerErrorMessage extends object @@ -9321,11 +9499,14 @@ experimental domain Storage loaded bid win + additionalBid + additionalBidWin + clear # Ad advertising element inside an interest group. type InterestGroupAd extends object properties - string renderUrl + string renderURL optional string metadata # The full details of an interest group. @@ -9335,10 +9516,10 @@ experimental domain Storage string name Network.TimeSinceEpoch expirationTime string joiningOrigin - optional string biddingUrl - optional string biddingWasmHelperUrl - optional string updateUrl - optional string trustedBiddingSignalsUrl + optional string biddingLogicURL + optional string biddingWasmHelperURL + optional string updateURL + optional string trustedBiddingSignalsURL array of string trustedBiddingSignalsKeys optional string userBiddingSignals array of InterestGroupAd ads @@ -9777,17 +9958,26 @@ experimental domain Storage # duration in seconds array of integer ends + experimental type AttributionReportingTriggerSpec extends object + properties + # number instead of integer because not all uint32 can be represented by + # int + array of number triggerData + AttributionReportingEventReportWindows eventReportWindows + + experimental type AttributionReportingTriggerDataMatching extends string + enum + exact + modulus + experimental type AttributionReportingSourceRegistration extends object properties Network.TimeSinceEpoch time # duration in seconds - optional integer expiry - # eventReportWindow and eventReportWindows are mutually exclusive - # duration in seconds - optional integer eventReportWindow - optional AttributionReportingEventReportWindows eventReportWindows + integer expiry + array of AttributionReportingTriggerSpec triggerSpecs # duration in seconds - optional integer aggregatableReportWindow + integer aggregatableReportWindow AttributionReportingSourceType type string sourceOrigin string reportingOrigin @@ -9797,6 +9987,7 @@ experimental domain Storage array of AttributionReportingFilterDataEntry filterData array of AttributionReportingAggregationKeysEntry aggregationKeys optional UnsignedInt64AsBase10 debugKey + AttributionReportingTriggerDataMatching triggerDataMatching experimental type AttributionReportingSourceRegistrationResult extends string enum @@ -10923,6 +11114,14 @@ experimental domain WebAuthn # Sets whether User Verification succeeds or fails for an authenticator. # Defaults to false. optional boolean isUserVerified + # Credentials created by this authenticator will have the backup + # eligibility (BE) flag set to this value. Defaults to false. + # https://w3c.github.io/webauthn/#sctn-credential-backup + optional boolean defaultBackupEligibility + # Credentials created by this authenticator will have the backup state + # (BS) flag set to this value. Defaults to false. + # https://w3c.github.io/webauthn/#sctn-credential-backup + optional boolean defaultBackupState type Credential extends object properties @@ -11284,7 +11483,6 @@ experimental domain Preload LowEndDevice InvalidSchemeRedirect InvalidSchemeNavigation - InProgressNavigation NavigationRequestBlockedByCsp MainFrameNavigation MojoBinderPolicy @@ -11296,7 +11494,6 @@ experimental domain Preload NavigationBadHttpStatus ClientCertRequested NavigationRequestNetworkError - MaxNumOfRunningPrerendersExceeded CancelAllHostsForTesting DidFailLoad Stop @@ -11308,11 +11505,8 @@ experimental domain Preload MixedContent TriggerBackgrounded MemoryLimitExceeded - # Prerenders can be cancelled when Chrome uses excessive memory. This is - # recorded when it fails to get the memory usage. - FailToGetMemoryUsage DataSaverEnabled - HasEffectiveUrl + TriggerUrlHasEffectiveUrl ActivatedBeforeStarted InactivePageRestriction StartFailed @@ -11341,21 +11535,14 @@ experimental domain Preload MemoryPressureOnTrigger MemoryPressureAfterTriggered PrerenderingDisabledByDevTools - ResourceLoadBlockedByClient SpeculationRuleRemoved ActivatedWithAuxiliaryBrowsingContexts - - # Fired when a prerender attempt is completed. - event prerenderAttemptCompleted - parameters - PreloadingAttemptKey key - # The frame id of the frame initiating prerendering. - Page.FrameId initiatingFrameId - string prerenderingUrl - PrerenderFinalStatus finalStatus - # This is used to give users more information about the name of the API call - # that is incompatible with prerender and has caused the cancellation of the attempt - optional string disallowedApiMethod + MaxNumOfRunningEagerPrerendersExceeded + MaxNumOfRunningNonEagerPrerendersExceeded + MaxNumOfRunningEmbedderPrerendersExceeded + PrerenderingUrlHasEffectiveUrl + RedirectedPrerenderingUrlHasEffectiveUrl + ActivationUrlHasEffectiveUrl # Fired when a preload enabled state is updated. event preloadEnabledStateUpdated @@ -11430,6 +11617,13 @@ experimental domain Preload PrefetchStatus prefetchStatus Network.RequestId requestId + # Information of headers to be displayed when the header mismatch occurred. + type PrerenderMismatchedHeaders extends object + properties + string headerName + optional string initialValue + optional string activationValue + # Fired when a prerender attempt is updated. event prerenderStatusUpdated parameters @@ -11439,6 +11633,7 @@ experimental domain Preload # This is used to give users more information about the name of Mojo interface # that is incompatible with prerender and has caused the cancellation of the attempt. optional string disallowedMojoInterface + optional array of PrerenderMismatchedHeaders mismatchedHeaders # Send a list of sources for all preloading attempts in a document. event preloadingAttemptSourcesUpdated @@ -11455,12 +11650,20 @@ experimental domain FedCm SignIn SignUp - # Whether the dialog shown is an account chooser or an auto re-authentication dialog. + # The types of FedCM dialogs. type DialogType extends string enum AccountChooser AutoReauthn - ConfirmIdpSignin + ConfirmIdpLogin + Error + + # The buttons on the FedCM dialog. + type DialogButton extends string + enum + ConfirmIdpLoginContinue + ErrorGotIt + ErrorMoreDetails # Corresponds to IdentityRequestAccount type Account extends object @@ -11471,7 +11674,7 @@ experimental domain FedCm string givenName string pictureUrl string idpConfigUrl - string idpSigninUrl + string idpLoginUrl LoginState loginState # These two are only set if the loginState is signUp optional string termsOfServiceUrl @@ -11487,6 +11690,12 @@ experimental domain FedCm string title optional string subtitle + # Triggered when a dialog is closed, either by user action, JS abort, + # or a command below. + event dialogClosed + parameters + string dialogId + command enable parameters # Allows callers to disable the promise rejection delay that would @@ -11501,11 +11710,10 @@ experimental domain FedCm string dialogId integer accountIndex - # Only valid if the dialog type is ConfirmIdpSignin. Acts as if the user had - # clicked the continue button. - command confirmIdpSignin + command clickDialogButton parameters string dialogId + DialogButton dialogButton command dismissDialog parameters diff --git a/common/devtools/chromium/v118/js_protocol.pdl b/common/devtools/chromium/v121/js_protocol.pdl similarity index 98% rename from common/devtools/chromium/v118/js_protocol.pdl rename to common/devtools/chromium/v121/js_protocol.pdl index ed6226308c266b..4754f17c5b02d7 100644 --- a/common/devtools/chromium/v118/js_protocol.pdl +++ b/common/devtools/chromium/v121/js_protocol.pdl @@ -1014,8 +1014,7 @@ domain Runtime # Unique script identifier. type ScriptId extends string - # Represents options for serialization. Overrides `generatePreview`, `returnByValue` and - # `generateWebDriverValue`. + # Represents options for serialization. Overrides `generatePreview` and `returnByValue`. type SerializationOptions extends object properties enum serialization @@ -1027,8 +1026,7 @@ domain Runtime # `returnByValue: true`. Overrides `returnByValue`. json # Only remote object id is put in the result. Same bahaviour as if no - # `serializationOptions`, `generatePreview`, `returnByValue` nor `generateWebDriverValue` - # are provided. + # `serializationOptions`, `generatePreview` nor `returnByValue` are provided. idOnly # Deep serialization depth. Default is full depth. Respected only in `deep` serialization mode. @@ -1066,6 +1064,7 @@ domain Runtime arraybuffer node window + generator optional any value optional string objectId # Set if value reference met more then once during serialization. In such @@ -1125,8 +1124,6 @@ domain Runtime optional UnserializableValue unserializableValue # String representation of the object. optional string description - # Deprecated. Use `deepSerializedValue` instead. WebDriver BiDi representation of the value. - deprecated optional DeepSerializedValue webDriverValue # Deep serialized value. experimental optional DeepSerializedValue deepSerializedValue # Unique object identifier (for non-primitive values). @@ -1442,13 +1439,8 @@ domain Runtime # boundaries). # This is mutually exclusive with `executionContextId`. experimental optional string uniqueContextId - # Deprecated. Use `serializationOptions: {serialization:"deep"}` instead. - # Whether the result should contain `webDriverValue`, serialized according to - # https://w3c.github.io/webdriver-bidi. This is mutually exclusive with `returnByValue`, but - # resulting `objectId` is still provided. - deprecated optional boolean generateWebDriverValue # Specifies the result serialization. If provided, overrides - # `generatePreview`, `returnByValue` and `generateWebDriverValue`. + # `generatePreview` and `returnByValue`. experimental optional SerializationOptions serializationOptions returns @@ -1536,14 +1528,8 @@ domain Runtime # boundaries). # This is mutually exclusive with `contextId`. experimental optional string uniqueContextId - # Deprecated. Use `serializationOptions: {serialization:"deep"}` instead. - # Whether the result should contain `webDriverValue`, serialized - # according to - # https://w3c.github.io/webdriver-bidi. This is mutually exclusive with `returnByValue`, but - # resulting `objectId` is still provided. - deprecated optional boolean generateWebDriverValue # Specifies the result serialization. If provided, overrides - # `generatePreview`, `returnByValue` and `generateWebDriverValue`. + # `generatePreview` and `returnByValue`. experimental optional SerializationOptions serializationOptions returns # Evaluation result. diff --git a/common/mirror/selenium b/common/mirror/selenium index 263ba605000d4c..458faa086e4e0d 100644 --- a/common/mirror/selenium +++ b/common/mirror/selenium @@ -3,13 +3,33 @@ "tag_name": "nightly", "assets": [ { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-java-4.17.0-SNAPSHOT.zip" + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-java-4.18.0-SNAPSHOT.zip" }, { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-server-4.17.0-SNAPSHOT.jar" + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-server-4.18.0-SNAPSHOT.jar" }, { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-server-4.17.0-SNAPSHOT.zip" + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-server-4.18.0-SNAPSHOT.zip" + } + ] + }, + { + "tag_name": "selenium-4.17.0", + "assets": [ + { + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.17.0/selenium-dotnet-4.17.0.zip" + }, + { + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.17.0/selenium-dotnet-strongnamed-4.17.0.zip" + }, + { + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.17.0/selenium-java-4.17.0.zip" + }, + { + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.17.0/selenium-server-4.17.0.jar" + }, + { + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.17.0/selenium-server-4.17.0.zip" } ] }, @@ -899,25 +919,5 @@ "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.0.0-alpha-4/selenium-server-4.0.0-alpha-4.zip" } ] - }, - { - "tag_name": "selenium-4.0.0-alpha-3", - "assets": [ - { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.0.0-alpha-3/selenium-dotnet-4.0.0-alpha03.zip" - }, - { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.0.0-alpha-3/selenium-dotnet-strongnamed-4.0.0.alpha03.zip" - }, - { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.0.0-alpha-3/selenium-html-runner-4.0.0-alpha-3.jar" - }, - { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.0.0-alpha-3/selenium-java-4.0.0-alpha-3.zip" - }, - { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.0.0-alpha-3/selenium-server-4.0.0-alpha-3.jar" - } - ] } ] diff --git a/common/repositories.bzl b/common/repositories.bzl index 1f438cfa47108f..6af15603b811a9 100644 --- a/common/repositories.bzl +++ b/common/repositories.bzl @@ -10,8 +10,8 @@ def pin_browsers(): http_archive( name = "linux_firefox", - url = "https://ftp.mozilla.org/pub/firefox/releases/121.0.1/linux-x86_64/en-US/firefox-121.0.1.tar.bz2", - sha256 = "0fb696e03ac444d6c973cf3ff9f9c123b369e2091c80b50753ff1b447f1a96c1", + url = "https://ftp.mozilla.org/pub/firefox/releases/122.0/linux-x86_64/en-US/firefox-122.0.tar.bz2", + sha256 = "0b36d796ba88d48000b0a3e43854a00556148221776879c91fae03735a0e5c21", build_file_content = """ filegroup( name = "files", @@ -27,15 +27,15 @@ exports_files( dmg_archive( name = "mac_firefox", - url = "https://ftp.mozilla.org/pub/firefox/releases/121.0.1/mac/en-US/Firefox%20121.0.1.dmg", - sha256 = "234b599abbbcf2ba553a625e2e97437cef08008a4d8484d9b889d8954372acf2", + url = "https://ftp.mozilla.org/pub/firefox/releases/122.0/mac/en-US/Firefox%20122.0.dmg", + sha256 = "ccd68fe5388b044062410ce71885911f618fd4222cd617e429eb8ab0b68795d4", build_file_content = "exports_files([\"Firefox.app\"])", ) http_archive( name = "linux_beta_firefox", - url = "https://ftp.mozilla.org/pub/firefox/releases/122.0b9/linux-x86_64/en-US/firefox-122.0b9.tar.bz2", - sha256 = "f556ac661b870f791eac7ed5a3cd1299f4cd370cbfd671dd3d26277502470b16", + url = "https://ftp.mozilla.org/pub/firefox/releases/123.0b7/linux-x86_64/en-US/firefox-123.0b7.tar.bz2", + sha256 = "05de0ab4a48c7a2c798172f68a11ba249785f60be97c6729b269dffa78328e12", build_file_content = """ filegroup( name = "files", @@ -51,15 +51,15 @@ exports_files( dmg_archive( name = "mac_beta_firefox", - url = "https://ftp.mozilla.org/pub/firefox/releases/122.0b9/mac/en-US/Firefox%20122.0b9.dmg", - sha256 = "ad9eb86051a84445f8d519cc38ebbf06a55a2ed60d371ddc143c6bf42a548f8e", + url = "https://ftp.mozilla.org/pub/firefox/releases/123.0b7/mac/en-US/Firefox%20123.0b7.dmg", + sha256 = "f598649bae4035bcf5f003b2faf1810d972898da63fff27b13cff8f0fd9e50a7", build_file_content = "exports_files([\"Firefox.app\"])", ) http_archive( name = "linux_dev_firefox", - url = "https://ftp.mozilla.org/pub/firefox/releases/122.0b9/linux-x86_64/en-US/firefox-122.0b9.tar.bz2", - sha256 = "f556ac661b870f791eac7ed5a3cd1299f4cd370cbfd671dd3d26277502470b16", + url = "https://ftp.mozilla.org/pub/firefox/releases/123.0b7/linux-x86_64/en-US/firefox-123.0b7.tar.bz2", + sha256 = "05de0ab4a48c7a2c798172f68a11ba249785f60be97c6729b269dffa78328e12", build_file_content = """ filegroup( name = "files", @@ -75,8 +75,8 @@ exports_files( dmg_archive( name = "mac_dev_firefox", - url = "https://ftp.mozilla.org/pub/firefox/releases/122.0b9/mac/en-US/Firefox%20122.0b9.dmg", - sha256 = "ad9eb86051a84445f8d519cc38ebbf06a55a2ed60d371ddc143c6bf42a548f8e", + url = "https://ftp.mozilla.org/pub/firefox/releases/123.0b7/mac/en-US/Firefox%20123.0b7.dmg", + sha256 = "f598649bae4035bcf5f003b2faf1810d972898da63fff27b13cff8f0fd9e50a7", build_file_content = "exports_files([\"Firefox.app\"])", ) @@ -96,32 +96,32 @@ exports_files( pkg_archive( name = "mac_edge", - url = "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/8e50e03c-aa9a-467d-bbb4-3b93045ed5b9/MicrosoftEdge-120.0.2210.144.pkg", - sha256 = "5f5190720d612224222dfba6746d9893d73f70abe57d14866552b3944b0d01f3", + url = "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/d6fb84d9-f938-4de1-a97f-b3e346a924be/MicrosoftEdge-121.0.2277.106.pkg", + sha256 = "b295496582213abecc4f12e29162a5998d8f47881ba9d9e0927cfe5fc6c0c9cd", move = { - "MicrosoftEdge-120.0.2210.144.pkg/Payload/Microsoft Edge.app": "Edge.app", + "MicrosoftEdge-121.0.2277.106.pkg/Payload/Microsoft Edge.app": "Edge.app", }, build_file_content = "exports_files([\"Edge.app\"])", ) http_archive( name = "linux_edgedriver", - url = "https://msedgedriver.azureedge.net/120.0.2210.144/edgedriver_linux64.zip", - sha256 = "2c44a4024444ccf702f52bc47cb7da8f4cca2653effde7db2462601bcfed7190", + url = "https://msedgedriver.azureedge.net/121.0.2277.98/edgedriver_linux64.zip", + sha256 = "3cc167bc7d605275cedca317989a3064d66b7069a312bbf6b802f6d12bae4bad", build_file_content = "exports_files([\"msedgedriver\"])", ) http_archive( name = "mac_edgedriver", - url = "https://msedgedriver.azureedge.net/120.0.2210.144/edgedriver_mac64.zip", - sha256 = "16513695a0405fefab843a25202d84116ac6e7078b808df45b379160167f4b67", + url = "https://msedgedriver.azureedge.net/121.0.2277.98/edgedriver_mac64.zip", + sha256 = "181ce8040e3c59b3f5a781012b3b37be4cc1ddf0ddb81f7727d94219becbaae7", build_file_content = "exports_files([\"msedgedriver\"])", ) http_archive( name = "linux_chrome", - url = "https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/120.0.6099.109/linux64/chrome-linux64.zip", - sha256 = "bcb22c5242aabf184c6fadd86ee58b3ae35739177edac9de3938ed33791d4ddf", + url = "https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/121.0.6167.85/linux64/chrome-linux64.zip", + sha256 = "0d4c2fbb4db86121bc72450cb9e8659335a72c1719c348e32331cf512ab1487c", build_file_content = """ filegroup( name = "files", @@ -137,8 +137,8 @@ exports_files( http_archive( name = "mac_chrome", - url = "https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/120.0.6099.109/mac-x64/chrome-mac-x64.zip", - sha256 = "2241f06533bf5710668b006bce4c4e8c2c16a94d629b402ab7889696514eb089", + url = "https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/121.0.6167.85/mac-x64/chrome-mac-x64.zip", + sha256 = "e150319a0fb5e13adbc703772545c7c9fa20b0474b56667f99f7967f5eefe0b8", strip_prefix = "chrome-mac-x64", patch_cmds = [ "mv 'Google Chrome for Testing.app' Chrome.app", @@ -149,16 +149,16 @@ exports_files( http_archive( name = "linux_chromedriver", - url = "https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/120.0.6099.109/linux64/chromedriver-linux64.zip", - sha256 = "809eb15e15bced4443be914ff3c2a02ca9b0a050e5a8c375563e8bf9b0dd6d27", + url = "https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/121.0.6167.85/linux64/chromedriver-linux64.zip", + sha256 = "3bc538a59efafcdeeaf5b57b77403ec2522aa9aa33e96c9f6503b87085760883", strip_prefix = "chromedriver-linux64", build_file_content = "exports_files([\"chromedriver\"])", ) http_archive( name = "mac_chromedriver", - url = "https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/120.0.6099.109/mac-x64/chromedriver-mac-x64.zip", - sha256 = "db43a02d6aedc36430c9fa1e86853b5a3987dc8a0e1b8937740c9ae54e5ced07", + url = "https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/121.0.6167.85/mac-x64/chromedriver-mac-x64.zip", + sha256 = "2033dd8eadc5a4bcba63dc64475e66cdb21a97cc23790cf35ad5ae678b8a9b30", strip_prefix = "chromedriver-mac-x64", build_file_content = "exports_files([\"chromedriver\"])", ) diff --git a/common/selenium_manager.bzl b/common/selenium_manager.bzl index 83152c283941a1..62026bb73f577e 100644 --- a/common/selenium_manager.bzl +++ b/common/selenium_manager.bzl @@ -6,20 +6,20 @@ def selenium_manager(): http_file( name = "download_sm_linux", executable = True, - sha256 = "cb0853d449c86bbb0ef5b293bb0d22398ca379549f508c09826398fa06269af3", - url = "https://github.com/SeleniumHQ/selenium_manager_artifacts/releases/download/selenium-manager-60aa87f/selenium-manager-linux", + sha256 = "b417e4faad5ab781102f6ba83f0bfc39b60343fbc43455a2732cab82420dcd0e", + url = "https://github.com/SeleniumHQ/selenium_manager_artifacts/releases/download/selenium-manager-03637c4/selenium-manager-linux", ) http_file( name = "download_sm_macos", executable = True, - sha256 = "db4f28bdf5f84f841e1e400f019bef396b3b73bddf01a7fc4b9b946ee566654a", - url = "https://github.com/SeleniumHQ/selenium_manager_artifacts/releases/download/selenium-manager-60aa87f/selenium-manager-macos", + sha256 = "f0990a97a24db5b0aa9d2fcbc7b69eaad11e96a4f3a75887f667b874bdc5e713", + url = "https://github.com/SeleniumHQ/selenium_manager_artifacts/releases/download/selenium-manager-03637c4/selenium-manager-macos", ) http_file( name = "download_sm_windows", executable = True, - sha256 = "f59390cc8adb76c20fe7701c4367d0a35a4dcd097974a2fa7bff6defab4c7521", - url = "https://github.com/SeleniumHQ/selenium_manager_artifacts/releases/download/selenium-manager-60aa87f/selenium-manager-windows.exe", + sha256 = "cb6e0b5ca072038e7626f77263c4b443b1f3e6c550cf3ebf09bf7d2c237a7389", + url = "https://github.com/SeleniumHQ/selenium_manager_artifacts/releases/download/selenium-manager-03637c4/selenium-manager-windows.exe", ) diff --git a/cpp/iedriverserver/CHANGELOG b/cpp/iedriverserver/CHANGELOG index fbde31ea6bd91e..01bebb086799c8 100644 --- a/cpp/iedriverserver/CHANGELOG +++ b/cpp/iedriverserver/CHANGELOG @@ -133,7 +133,7 @@ v3.141.59.2 v3.141.59.1 =========== - * Added checking for max expiriation date in IE driver cookie handling. + * Added checking for max expiration date in IE driver cookie handling. Attempting to add a cookie with a very large expiration date caused the IE driver to crash because of overflows in the C++ standard library time formatting functions. This commit now avoids the crash by diff --git a/dotnet/CHANGELOG b/dotnet/CHANGELOG index e1642f24d6331b..ed8745347edef5 100644 --- a/dotnet/CHANGELOG +++ b/dotnet/CHANGELOG @@ -1,3 +1,21 @@ +v4.17.0 +====== + +* Add csharp to Selenium Manager input for tracking (see #13288) +* Consider log handlers as null when not initiated +* Lazy initialization of log handlers when required +* Specify the dll as nuget content explicitly (#13332) +* Extract downloadable zip file in memory (#13277) +* Update references from desiredCapabilities to capabilities +* Don't output to user's console, rather use logging (Fixes #13410) +* Add function to enable halting targets until runtime.runIfWaitingForDebugger is invoked (#13330) +* Properly get selenium manager from bazel output (#13452) +* Remove deprecated DriverService constructors with options parameter +* Remove deprecated methods for toggling legacy protocol +* Remove deprecated class RemoteWebElement +* Improve logging performance when it is disabled (#13464) +* Add CDP for Chrome 121 and remove 118 + v4.16.2 ====== diff --git a/dotnet/selenium-dotnet-version.bzl b/dotnet/selenium-dotnet-version.bzl index 1f599887fa9727..8fe3291a4194e8 100644 --- a/dotnet/selenium-dotnet-version.bzl +++ b/dotnet/selenium-dotnet-version.bzl @@ -1,6 +1,6 @@ # BUILD FILE SYNTAX: STARLARK -SE_VERSION = "4.16.2" +SE_VERSION = "4.17.0" ASSEMBLY_VERSION = "4.0.0.0" SUPPORTED_NET_STANDARD_VERSIONS = ["netstandard2.0"] @@ -8,7 +8,7 @@ SUPPORTED_DEVTOOLS_VERSIONS = [ "v85", "v119", "v120", - "v118", + "v121", ] ASSEMBLY_COMPANY = "Selenium Committers" diff --git a/dotnet/src/webdriver/Chrome/ChromeDriverService.cs b/dotnet/src/webdriver/Chrome/ChromeDriverService.cs index 20e2e1d63a68b0..4c48017f43cad8 100644 --- a/dotnet/src/webdriver/Chrome/ChromeDriverService.cs +++ b/dotnet/src/webdriver/Chrome/ChromeDriverService.cs @@ -59,16 +59,22 @@ public static ChromeDriverService CreateDefaultService() /// /// Creates a default instance of the ChromeDriverService using a specified path to the ChromeDriver executable. /// - /// The directory containing the ChromeDriver executable. + /// The path to the executable or the directory containing the ChromeDriver executable. /// A ChromeDriverService using a random port. public static ChromeDriverService CreateDefaultService(string driverPath) { + string fileName; if (File.Exists(driverPath)) { + fileName = Path.GetFileName(driverPath); driverPath = Path.GetDirectoryName(driverPath); } + else + { + fileName = ChromiumDriverServiceFileName(DefaultChromeDriverServiceExecutableName); + } - return CreateDefaultService(driverPath, ChromiumDriverServiceFileName(DefaultChromeDriverServiceExecutableName)); + return CreateDefaultService(driverPath, fileName); } /// diff --git a/dotnet/src/webdriver/Chromium/ChromiumDriverService.cs b/dotnet/src/webdriver/Chromium/ChromiumDriverService.cs index bb24ab75c77600..3c7aafe0378b3e 100644 --- a/dotnet/src/webdriver/Chromium/ChromiumDriverService.cs +++ b/dotnet/src/webdriver/Chromium/ChromiumDriverService.cs @@ -33,7 +33,7 @@ public abstract class ChromiumDriverService : DriverService private string logPath = string.Empty; private string urlPathPrefix = string.Empty; private string portServerAddress = string.Empty; - private string whitelistedIpAddresses = string.Empty; + private string allowedIpAddresses = string.Empty; private int adbPort = -1; private bool disableBuildCheck; private bool enableVerboseLogging; @@ -45,8 +45,7 @@ public abstract class ChromiumDriverService : DriverService /// The full path to the ChromeDriver executable. /// The file name of the ChromeDriver executable. /// The port on which the ChromeDriver executable should listen. - /// The URL from which the driver executable can be downloaded. - protected ChromiumDriverService(string executablePath, string executableFileName, int port, Uri downloadUrl = null) + protected ChromiumDriverService(string executablePath, string executableFileName, int port) : base(executablePath, port, executableFileName) { } @@ -123,10 +122,22 @@ public bool EnableAppendLog /// connect to this instance of the Chrome driver. Defaults to an empty string, /// which means only the local loopback address can connect. /// - public string WhitelistedIPAddresses + [Obsolete("Use AllowedIpAddresses")] + public string WhitelistedIpAddresses { - get { return this.whitelistedIpAddresses; } - set { this.whitelistedIpAddresses = value; } + get { return this.allowedIpAddresses; } + set { this.allowedIpAddresses = value; } + } + + /// + /// Gets or sets the comma-delimited list of IP addresses that are approved to + /// connect to this instance of the Chrome driver. Defaults to an empty string, + /// which means only the local loopback address can connect. + /// + public string AllowedIpAddresses + { + get { return this.allowedIpAddresses; } + set { this.allowedIpAddresses = value; } } /// @@ -177,9 +188,9 @@ protected override string CommandLineArguments argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --port-server={0}", this.portServerAddress); } - if (!string.IsNullOrEmpty(this.whitelistedIpAddresses)) + if (!string.IsNullOrEmpty(this.allowedIpAddresses)) { - argsBuilder.Append(string.Format(CultureInfo.InvariantCulture, " -whitelisted-ips={0}", this.whitelistedIpAddresses)); + argsBuilder.Append(string.Format(CultureInfo.InvariantCulture, " -allowed-ips={0}", this.allowedIpAddresses)); } return argsBuilder.ToString(); diff --git a/dotnet/src/webdriver/DevTools/DevToolsDomains.cs b/dotnet/src/webdriver/DevTools/DevToolsDomains.cs index bae33a070b2251..eabbed72fe0777 100644 --- a/dotnet/src/webdriver/DevTools/DevToolsDomains.cs +++ b/dotnet/src/webdriver/DevTools/DevToolsDomains.cs @@ -37,7 +37,7 @@ public abstract class DevToolsDomains // added to this dictionary. private static readonly Dictionary SupportedDevToolsVersions = new Dictionary() { - { 118, typeof(V118.V118Domains) }, + { 121, typeof(V121.V121Domains) }, { 120, typeof(V120.V120Domains) }, { 119, typeof(V119.V119Domains) }, { 85, typeof(V85.V85Domains) } diff --git a/dotnet/src/webdriver/DevTools/v118/V118Domains.cs b/dotnet/src/webdriver/DevTools/v121/V121Domains.cs similarity index 79% rename from dotnet/src/webdriver/DevTools/v118/V118Domains.cs rename to dotnet/src/webdriver/DevTools/v121/V121Domains.cs index d94562ebda5490..a9d974c3f28965 100644 --- a/dotnet/src/webdriver/DevTools/v118/V118Domains.cs +++ b/dotnet/src/webdriver/DevTools/v121/V121Domains.cs @@ -1,4 +1,4 @@ -// +// // Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -19,20 +19,20 @@ using System.Collections.Generic; using System.Text; -namespace OpenQA.Selenium.DevTools.V118 +namespace OpenQA.Selenium.DevTools.V121 { /// - /// Class containing the domain implementation for version 118 of the DevTools Protocol. + /// Class containing the domain implementation for version 121 of the DevTools Protocol. /// - public class V118Domains : DevToolsDomains + public class V121Domains : DevToolsDomains { private DevToolsSessionDomains domains; /// - /// Initializes a new instance of the V118Domains class. + /// Initializes a new instance of the V121Domains class. /// /// The DevToolsSession to use with this set of domains. - public V118Domains(DevToolsSession session) + public V121Domains(DevToolsSession session) { this.domains = new DevToolsSessionDomains(session); } @@ -40,7 +40,7 @@ public V118Domains(DevToolsSession session) /// /// Gets the DevTools Protocol version for which this class is valid. /// - public static int DevToolsVersion => 118; + public static int DevToolsVersion => 121; /// /// Gets the version-specific domains for the DevTools session. This value must be cast to a version specific type to be at all useful. @@ -50,21 +50,21 @@ public V118Domains(DevToolsSession session) /// /// Gets the object used for manipulating network information in the browser. /// - public override DevTools.Network Network => new V118Network(domains.Network, domains.Fetch); + public override DevTools.Network Network => new V121Network(domains.Network, domains.Fetch); /// /// Gets the object used for manipulating the browser's JavaScript execution. /// - public override JavaScript JavaScript => new V118JavaScript(domains.Runtime, domains.Page); + public override JavaScript JavaScript => new V121JavaScript(domains.Runtime, domains.Page); /// /// Gets the object used for manipulating DevTools Protocol targets. /// - public override DevTools.Target Target => new V118Target(domains.Target); + public override DevTools.Target Target => new V121Target(domains.Target); /// /// Gets the object used for manipulating the browser's logs. /// - public override DevTools.Log Log => new V118Log(domains.Log); + public override DevTools.Log Log => new V121Log(domains.Log); } } diff --git a/dotnet/src/webdriver/DevTools/v118/V118JavaScript.cs b/dotnet/src/webdriver/DevTools/v121/V121JavaScript.cs similarity index 94% rename from dotnet/src/webdriver/DevTools/v118/V118JavaScript.cs rename to dotnet/src/webdriver/DevTools/v121/V121JavaScript.cs index 95d3ef164ec83a..720fb1063ee621 100644 --- a/dotnet/src/webdriver/DevTools/v118/V118JavaScript.cs +++ b/dotnet/src/webdriver/DevTools/v121/V121JavaScript.cs @@ -1,4 +1,4 @@ -// +// // Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -18,25 +18,25 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using OpenQA.Selenium.DevTools.V118.Page; -using OpenQA.Selenium.DevTools.V118.Runtime; +using OpenQA.Selenium.DevTools.V121.Page; +using OpenQA.Selenium.DevTools.V121.Runtime; -namespace OpenQA.Selenium.DevTools.V118 +namespace OpenQA.Selenium.DevTools.V121 { /// - /// Class containing the JavaScript implementation for version 118 of the DevTools Protocol. + /// Class containing the JavaScript implementation for version 121 of the DevTools Protocol. /// - public class V118JavaScript : JavaScript + public class V121JavaScript : JavaScript { private RuntimeAdapter runtime; private PageAdapter page; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The DevTools Protocol adapter for the Runtime domain. /// The DevTools Protocol adapter for the Page domain. - public V118JavaScript(RuntimeAdapter runtime, PageAdapter page) + public V121JavaScript(RuntimeAdapter runtime, PageAdapter page) { this.runtime = runtime; this.page = page; diff --git a/dotnet/src/webdriver/DevTools/v118/V118Log.cs b/dotnet/src/webdriver/DevTools/v121/V121Log.cs similarity index 89% rename from dotnet/src/webdriver/DevTools/v118/V118Log.cs rename to dotnet/src/webdriver/DevTools/v121/V121Log.cs index 099da81dbefc89..e3cde87f6cd8fb 100644 --- a/dotnet/src/webdriver/DevTools/v118/V118Log.cs +++ b/dotnet/src/webdriver/DevTools/v121/V121Log.cs @@ -1,4 +1,4 @@ -// +// // Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -20,22 +20,22 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenQA.Selenium.DevTools.V118.Log; +using OpenQA.Selenium.DevTools.V121.Log; -namespace OpenQA.Selenium.DevTools.V118 +namespace OpenQA.Selenium.DevTools.V121 { /// - /// Class containing the browser's log as referenced by version 118 of the DevTools Protocol. + /// Class containing the browser's log as referenced by version 121 of the DevTools Protocol. /// - public class V118Log : DevTools.Log + public class V121Log : DevTools.Log { private LogAdapter adapter; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The adapter for the Log domain. - public V118Log(LogAdapter adapter) + public V121Log(LogAdapter adapter) { this.adapter = adapter; this.adapter.EntryAdded += OnAdapterEntryAdded; diff --git a/dotnet/src/webdriver/DevTools/v118/V118Network.cs b/dotnet/src/webdriver/DevTools/v121/V121Network.cs similarity index 95% rename from dotnet/src/webdriver/DevTools/v118/V118Network.cs rename to dotnet/src/webdriver/DevTools/v121/V121Network.cs index 38d414ae202de1..0b7005a1cc0e6c 100644 --- a/dotnet/src/webdriver/DevTools/v118/V118Network.cs +++ b/dotnet/src/webdriver/DevTools/v121/V121Network.cs @@ -1,4 +1,4 @@ -// +// // Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -20,25 +20,25 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; -using OpenQA.Selenium.DevTools.V118.Fetch; -using OpenQA.Selenium.DevTools.V118.Network; +using OpenQA.Selenium.DevTools.V121.Fetch; +using OpenQA.Selenium.DevTools.V121.Network; -namespace OpenQA.Selenium.DevTools.V118 +namespace OpenQA.Selenium.DevTools.V121 { /// - /// Class providing functionality for manipulating network calls using version 118 of the DevTools Protocol + /// Class providing functionality for manipulating network calls using version 121 of the DevTools Protocol /// - public class V118Network : DevTools.Network + public class V121Network : DevTools.Network { private FetchAdapter fetch; private NetworkAdapter network; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The adapter for the Network domain. /// The adapter for the Fetch domain. - public V118Network(NetworkAdapter network, FetchAdapter fetch) + public V121Network(NetworkAdapter network, FetchAdapter fetch) { this.network = network; this.fetch = fetch; @@ -216,9 +216,9 @@ public override async Task ContinueWithAuth(string requestId, string userName, s await fetch.ContinueWithAuth(new ContinueWithAuthCommandSettings() { RequestId = requestId, - AuthChallengeResponse = new V118.Fetch.AuthChallengeResponse() + AuthChallengeResponse = new V121.Fetch.AuthChallengeResponse() { - Response = V118.Fetch.AuthChallengeResponseResponseValues.ProvideCredentials, + Response = V121.Fetch.AuthChallengeResponseResponseValues.ProvideCredentials, Username = userName, Password = password } @@ -235,9 +235,9 @@ public override async Task CancelAuth(string requestId) await fetch.ContinueWithAuth(new ContinueWithAuthCommandSettings() { RequestId = requestId, - AuthChallengeResponse = new OpenQA.Selenium.DevTools.V118.Fetch.AuthChallengeResponse() + AuthChallengeResponse = new OpenQA.Selenium.DevTools.V121.Fetch.AuthChallengeResponse() { - Response = V118.Fetch.AuthChallengeResponseResponseValues.CancelAuth + Response = V121.Fetch.AuthChallengeResponseResponseValues.CancelAuth } }).ConfigureAwait(false); } diff --git a/dotnet/src/webdriver/DevTools/v118/V118Target.cs b/dotnet/src/webdriver/DevTools/v121/V121Target.cs similarity index 94% rename from dotnet/src/webdriver/DevTools/v118/V118Target.cs rename to dotnet/src/webdriver/DevTools/v121/V121Target.cs index 3f4a4f620ec956..4afeb6abbe3579 100644 --- a/dotnet/src/webdriver/DevTools/v118/V118Target.cs +++ b/dotnet/src/webdriver/DevTools/v121/V121Target.cs @@ -1,4 +1,4 @@ -// +// // Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -21,22 +21,22 @@ using System.Collections.ObjectModel; using System.Text; using System.Threading.Tasks; -using OpenQA.Selenium.DevTools.V118.Target; +using OpenQA.Selenium.DevTools.V121.Target; -namespace OpenQA.Selenium.DevTools.V118 +namespace OpenQA.Selenium.DevTools.V121 { /// - /// Class providing functionality for manipulating targets for version 118 of the DevTools Protocol + /// Class providing functionality for manipulating targets for version 121 of the DevTools Protocol /// - public class V118Target : DevTools.Target + public class V121Target : DevTools.Target { private TargetAdapter adapter; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The adapter for the Target domain. - public V118Target(TargetAdapter adapter) + public V121Target(TargetAdapter adapter) { this.adapter = adapter; adapter.DetachedFromTarget += OnDetachedFromTarget; diff --git a/dotnet/src/webdriver/DriverService.cs b/dotnet/src/webdriver/DriverService.cs index 77f2eb10e6f3f6..691fc18f21a0f9 100644 --- a/dotnet/src/webdriver/DriverService.cs +++ b/dotnet/src/webdriver/DriverService.cs @@ -50,14 +50,13 @@ public abstract class DriverService : ICommandServer /// The full path to the directory containing the executable providing the service to drive the browser. /// The port on which the driver executable should listen. /// The file name of the driver service executable. - /// This parameter is no longer used; kept for backwards compatibility. /// /// If the path specified is or an empty string. /// /// /// If the specified driver service executable does not exist in the specified directory. /// - protected DriverService(string servicePath, int port, string driverServiceExecutableName, Uri driverServiceDownloadUrl = null) + protected DriverService(string servicePath, int port, string driverServiceExecutableName) { this.driverServicePath = servicePath; this.driverServiceExecutableName = driverServiceExecutableName; diff --git a/dotnet/src/webdriver/Edge/EdgeDriverService.cs b/dotnet/src/webdriver/Edge/EdgeDriverService.cs index 65c94a228211c1..3e150e8400fcdd 100644 --- a/dotnet/src/webdriver/Edge/EdgeDriverService.cs +++ b/dotnet/src/webdriver/Edge/EdgeDriverService.cs @@ -50,6 +50,7 @@ protected override DriverOptions GetDefaultDriverOptions() /// /// Gets or sets a value indicating whether the service should use verbose logging. /// + [Obsolete("Use EnableVerboseLogging")] public bool UseVerboseLogging { get { return this.EnableVerboseLogging; } @@ -72,12 +73,18 @@ public static EdgeDriverService CreateDefaultService() /// An EdgeDriverService using a random port. public static EdgeDriverService CreateDefaultService(string driverPath) { + string fileName; if (File.Exists(driverPath)) { + fileName = Path.GetFileName(driverPath); driverPath = Path.GetDirectoryName(driverPath); } + else + { + fileName = ChromiumDriverServiceFileName(MSEdgeDriverServiceFileName); + } - return CreateDefaultService(driverPath, ChromiumDriverServiceFileName(MSEdgeDriverServiceFileName)); + return CreateDefaultService(driverPath, fileName); } /// diff --git a/dotnet/src/webdriver/Firefox/FirefoxDriverService.cs b/dotnet/src/webdriver/Firefox/FirefoxDriverService.cs index d6a8fa7f4e528e..ce039813f4d6af 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxDriverService.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxDriverService.cs @@ -221,16 +221,22 @@ public static FirefoxDriverService CreateDefaultService() /// /// Creates a default instance of the FirefoxDriverService using a specified path to the Firefox driver executable. /// - /// The directory containing the Firefox driver executable. + /// The path to the executable or the directory containing the Firefox driver executable. /// A FirefoxDriverService using a random port. public static FirefoxDriverService CreateDefaultService(string driverPath) { + string fileName; if (File.Exists(driverPath)) { + fileName = Path.GetFileName(driverPath); driverPath = Path.GetDirectoryName(driverPath); } + else + { + fileName = FirefoxDriverServiceFileName(); + } - return CreateDefaultService(driverPath, FirefoxDriverServiceFileName()); + return CreateDefaultService(driverPath, fileName); } /// diff --git a/dotnet/src/webdriver/IE/InternetExplorerDriverService.cs b/dotnet/src/webdriver/IE/InternetExplorerDriverService.cs index 187890ed4633f4..3a02b9c74d846f 100644 --- a/dotnet/src/webdriver/IE/InternetExplorerDriverService.cs +++ b/dotnet/src/webdriver/IE/InternetExplorerDriverService.cs @@ -161,16 +161,22 @@ public static InternetExplorerDriverService CreateDefaultService() /// /// Creates a default instance of the InternetExplorerDriverService using a specified path to the IEDriverServer executable. /// - /// The directory containing the IEDriverServer executable. + /// The path to the executable or the directory containing the IEDriverServer executable. /// A InternetExplorerDriverService using a random port. public static InternetExplorerDriverService CreateDefaultService(string driverPath) { + string fileName; if (File.Exists(driverPath)) { + fileName = Path.GetFileName(driverPath); driverPath = Path.GetDirectoryName(driverPath); } + else + { + fileName = InternetExplorerDriverServiceFileName; + } - return CreateDefaultService(driverPath, InternetExplorerDriverServiceFileName); + return CreateDefaultService(driverPath, fileName); } /// diff --git a/dotnet/src/webdriver/Remote/RemoteWebDriver.cs b/dotnet/src/webdriver/Remote/RemoteWebDriver.cs index e6898cde3590fa..74d83aec384d99 100644 --- a/dotnet/src/webdriver/Remote/RemoteWebDriver.cs +++ b/dotnet/src/webdriver/Remote/RemoteWebDriver.cs @@ -433,6 +433,11 @@ public DevToolsSession GetDevToolsSession() /// The active session to use to communicate with the Developer Tools debugging protocol. public DevToolsSession GetDevToolsSession(DevToolsOptions options) { + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + if (this.devToolsSession == null) { if (!this.Capabilities.HasCapability(RemoteDevToolsEndPointCapabilityName)) @@ -440,18 +445,24 @@ public DevToolsSession GetDevToolsSession(DevToolsOptions options) throw new WebDriverException("Cannot find " + RemoteDevToolsEndPointCapabilityName + " capability for driver"); } - if (!this.Capabilities.HasCapability(RemoteDevToolsVersionCapabilityName)) - { - throw new WebDriverException("Cannot find " + RemoteDevToolsVersionCapabilityName + " capability for driver"); - } - string debuggerAddress = this.Capabilities.GetCapability(RemoteDevToolsEndPointCapabilityName).ToString(); - string version = this.Capabilities.GetCapability(RemoteDevToolsVersionCapabilityName).ToString(); - bool versionParsed = int.TryParse(version.Substring(0, version.IndexOf(".")), out int devToolsProtocolVersion); - if (!versionParsed) + if (!options.ProtocolVersion.HasValue || options.ProtocolVersion == DevToolsSession.AutoDetectDevToolsProtocolVersion) { - throw new WebDriverException("Cannot parse protocol version from reported version string: " + version); + if (!this.Capabilities.HasCapability(RemoteDevToolsVersionCapabilityName)) + { + throw new WebDriverException("Cannot find " + RemoteDevToolsVersionCapabilityName + " capability for driver"); + } + + string version = this.Capabilities.GetCapability(RemoteDevToolsVersionCapabilityName).ToString(); + + bool versionParsed = int.TryParse(version.Substring(0, version.IndexOf(".")), out int devToolsProtocolVersion); + if (!versionParsed) + { + throw new WebDriverException("Cannot parse protocol version from reported version string: " + version); + } + + options.ProtocolVersion = devToolsProtocolVersion; } try diff --git a/dotnet/src/webdriver/Safari/SafariDriverService.cs b/dotnet/src/webdriver/Safari/SafariDriverService.cs index 03fda3289cf429..10a77ddf48cf84 100644 --- a/dotnet/src/webdriver/Safari/SafariDriverService.cs +++ b/dotnet/src/webdriver/Safari/SafariDriverService.cs @@ -154,16 +154,22 @@ public static SafariDriverService CreateDefaultService() /// /// Creates a default instance of the SafariDriverService using a specified path to the SafariDriver executable. /// - /// The directory containing the SafariDriver executable. + /// The path to the executable or the directory containing the SafariDriver executable. /// A SafariDriverService using a random port. public static SafariDriverService CreateDefaultService(string driverPath) { + string fileName; if (File.Exists(driverPath)) { + fileName = Path.GetFileName(driverPath); driverPath = Path.GetDirectoryName(driverPath); } + else + { + fileName = DefaultSafariDriverServiceExecutableName; + } - return CreateDefaultService(driverPath, DefaultSafariDriverServiceExecutableName); + return CreateDefaultService(driverPath, fileName); } /// diff --git a/dotnet/src/webdriver/WebDriver.csproj b/dotnet/src/webdriver/WebDriver.csproj index 46fe8e0703d8a2..536a48df73f99d 100644 --- a/dotnet/src/webdriver/WebDriver.csproj +++ b/dotnet/src/webdriver/WebDriver.csproj @@ -106,7 +106,7 @@ - + diff --git a/dotnet/test/common/ClickScrollingTest.cs b/dotnet/test/common/ClickScrollingTest.cs index b5ff9d95e99377..73dec27c69d0ab 100644 --- a/dotnet/test/common/ClickScrollingTest.cs +++ b/dotnet/test/common/ClickScrollingTest.cs @@ -101,7 +101,7 @@ public void ShouldNotScrollIfAlreadyScrolledAndElementIsInView() { driver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIs("scroll3.html"); driver.FindElement(By.Id("button2")).Click(); - long scrollTop = GetScrollTop(); + double scrollTop = GetScrollTop(); driver.FindElement(By.Id("button1")).Click(); Assert.AreEqual(scrollTop, GetScrollTop()); } @@ -217,7 +217,7 @@ public void ShouldBeAbleToClickElementThatIsOutOfViewInANestedFrameThatIsOutOfVi public void ShouldNotScrollWhenGettingElementSize() { driver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIs("scroll3.html"); - long scrollTop = GetScrollTop(); + double scrollTop = GetScrollTop(); Size ignoredSize = driver.FindElement(By.Id("button1")).Size; Assert.AreEqual(scrollTop, GetScrollTop()); } @@ -250,9 +250,9 @@ public void ShouldBeAbleToClickInlineTextElementWithChildElementAfterScrolling() Assert.IsFalse(checkbox.Selected, "Checkbox should not be selected after click"); } - private long GetScrollTop() + private double GetScrollTop() { - return (long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.scrollTop;"); + return double.Parse(((IJavaScriptExecutor)driver).ExecuteScript("return document.body.scrollTop;").ToString()); } private Func TitleToBe(string desiredTitle) diff --git a/dotnet/test/common/CustomDriverConfigs/StableChannelChromeDriver.cs b/dotnet/test/common/CustomDriverConfigs/StableChannelChromeDriver.cs index 714acee8974bad..62330cdf374979 100644 --- a/dotnet/test/common/CustomDriverConfigs/StableChannelChromeDriver.cs +++ b/dotnet/test/common/CustomDriverConfigs/StableChannelChromeDriver.cs @@ -20,7 +20,7 @@ public StableChannelChromeDriver(ChromeDriverService service, ChromeOptions opti public static ChromeOptions DefaultOptions { - get { return new ChromeOptions() { BrowserVersion = "120" }; } + get { return new ChromeOptions() { BrowserVersion = "121" }; } } } } diff --git a/dotnet/test/common/DevTools/DevToolsConsoleTest.cs b/dotnet/test/common/DevTools/DevToolsConsoleTest.cs index c04c1f08022111..aae152144be6d7 100644 --- a/dotnet/test/common/DevTools/DevToolsConsoleTest.cs +++ b/dotnet/test/common/DevTools/DevToolsConsoleTest.cs @@ -6,7 +6,7 @@ namespace OpenQA.Selenium.DevTools { - using CurrentCdpVersion = V120; + using CurrentCdpVersion = V121; [TestFixture] public class DevToolsConsoleTest : DevToolsTestFixture diff --git a/dotnet/test/common/DevTools/DevToolsLogTest.cs b/dotnet/test/common/DevTools/DevToolsLogTest.cs index d2a09f91842a1e..75de6361ade3e7 100644 --- a/dotnet/test/common/DevTools/DevToolsLogTest.cs +++ b/dotnet/test/common/DevTools/DevToolsLogTest.cs @@ -6,7 +6,7 @@ namespace OpenQA.Selenium.DevTools { - using CurrentCdpVersion = V120; + using CurrentCdpVersion = V121; [TestFixture] public class DevToolsLogTest : DevToolsTestFixture diff --git a/dotnet/test/common/DevTools/DevToolsNetworkTest.cs b/dotnet/test/common/DevTools/DevToolsNetworkTest.cs index 3d49113e14d58b..080a87a8bc5cde 100644 --- a/dotnet/test/common/DevTools/DevToolsNetworkTest.cs +++ b/dotnet/test/common/DevTools/DevToolsNetworkTest.cs @@ -6,7 +6,7 @@ namespace OpenQA.Selenium.DevTools { - using CurrentCdpVersion = V120; + using CurrentCdpVersion = V121; [TestFixture] public class DevToolsNetworkTest : DevToolsTestFixture diff --git a/dotnet/test/common/DevTools/DevToolsPerformanceTest.cs b/dotnet/test/common/DevTools/DevToolsPerformanceTest.cs index 341b74e2105d45..c1a733fa43cea4 100644 --- a/dotnet/test/common/DevTools/DevToolsPerformanceTest.cs +++ b/dotnet/test/common/DevTools/DevToolsPerformanceTest.cs @@ -3,7 +3,7 @@ namespace OpenQA.Selenium.DevTools { - using CurrentCdpVersion = V120; + using CurrentCdpVersion = V121; [TestFixture] public class DevToolsPerformanceTest : DevToolsTestFixture diff --git a/dotnet/test/common/DevTools/DevToolsProfilerTest.cs b/dotnet/test/common/DevTools/DevToolsProfilerTest.cs index 636e342e3e47cb..cf9c35fc1fdd5d 100644 --- a/dotnet/test/common/DevTools/DevToolsProfilerTest.cs +++ b/dotnet/test/common/DevTools/DevToolsProfilerTest.cs @@ -5,7 +5,7 @@ namespace OpenQA.Selenium.DevTools { - using CurrentCdpVersion = V120; + using CurrentCdpVersion = V121; [TestFixture] public class DevToolsProfilerTest : DevToolsTestFixture diff --git a/dotnet/test/common/DevTools/DevToolsSecurityTest.cs b/dotnet/test/common/DevTools/DevToolsSecurityTest.cs index f77fb335894052..c7da098bcd96e7 100644 --- a/dotnet/test/common/DevTools/DevToolsSecurityTest.cs +++ b/dotnet/test/common/DevTools/DevToolsSecurityTest.cs @@ -6,7 +6,7 @@ namespace OpenQA.Selenium.DevTools { - using CurrentCdpVersion = V120; + using CurrentCdpVersion = V121; [TestFixture] public class DevToolsSecurityTest : DevToolsTestFixture diff --git a/dotnet/test/common/DevTools/DevToolsTargetTest.cs b/dotnet/test/common/DevTools/DevToolsTargetTest.cs index 00a7909573a40d..ad0d7e0a9584ca 100644 --- a/dotnet/test/common/DevTools/DevToolsTargetTest.cs +++ b/dotnet/test/common/DevTools/DevToolsTargetTest.cs @@ -6,7 +6,7 @@ namespace OpenQA.Selenium.DevTools { - using CurrentCdpVersion = V120; + using CurrentCdpVersion = V121; [TestFixture] public class DevToolsTargetTest : DevToolsTestFixture diff --git a/dotnet/test/common/Environment/RemoteSeleniumServer.cs b/dotnet/test/common/Environment/RemoteSeleniumServer.cs index a8fdc46973edfe..0f1b667c5a3739 100644 --- a/dotnet/test/common/Environment/RemoteSeleniumServer.cs +++ b/dotnet/test/common/Environment/RemoteSeleniumServer.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using System.IO; using System.Net; +using System.Net.Http; namespace OpenQA.Selenium.Environment { @@ -39,19 +40,22 @@ public void Start() webserverProcess.Start(); DateTime timeout = DateTime.Now.Add(TimeSpan.FromSeconds(30)); bool isRunning = false; + + // Poll until the webserver is correctly serving pages. + using var httpClient = new HttpClient(); + while (!isRunning && DateTime.Now < timeout) { - // Poll until the webserver is correctly serving pages. - HttpWebRequest request = WebRequest.Create("http://localhost:6000/wd/hub/status") as HttpWebRequest; try { - HttpWebResponse response = request.GetResponse() as HttpWebResponse; + using var response = httpClient.GetAsync("http://localhost:6000/wd/hub/status").GetAwaiter().GetResult(); + if (response.StatusCode == HttpStatusCode.OK) { isRunning = true; } } - catch (WebException) + catch (Exception ex) when (ex is HttpRequestException || ex is TimeoutException) { } } @@ -65,14 +69,15 @@ public void Start() public void Stop() { - if (autoStart && (webserverProcess != null && !webserverProcess.HasExited)) + if (autoStart && webserverProcess != null && !webserverProcess.HasExited) { - HttpWebRequest request = WebRequest.Create("http://localhost:6000/selenium-server/driver?cmd=shutDownSeleniumServer") as HttpWebRequest; + using var httpClient = new HttpClient(); + try { - request.GetResponse(); + using var response = httpClient.GetAsync("http://localhost:6000/selenium-server/driver?cmd=shutDownSeleniumServer").GetAwaiter().GetResult(); } - catch (WebException) + catch (Exception ex) when (ex is HttpRequestException || ex is TimeoutException) { } diff --git a/dotnet/test/common/Environment/TestWebServer.cs b/dotnet/test/common/Environment/TestWebServer.cs index b5381a1c0b3a2e..fbae1fed90d347 100644 --- a/dotnet/test/common/Environment/TestWebServer.cs +++ b/dotnet/test/common/Environment/TestWebServer.cs @@ -119,19 +119,22 @@ public void Start() TimeSpan timeout = TimeSpan.FromSeconds(30); DateTime endTime = DateTime.Now.Add(TimeSpan.FromSeconds(30)); bool isRunning = false; + + // Poll until the webserver is correctly serving pages. + using var httpClient = new HttpClient(); + while (!isRunning && DateTime.Now < endTime) { - // Poll until the webserver is correctly serving pages. - HttpWebRequest request = WebRequest.Create(EnvironmentManager.Instance.UrlBuilder.LocalWhereIs("simpleTest.html")) as HttpWebRequest; try { - HttpWebResponse response = request.GetResponse() as HttpWebResponse; + using var response = httpClient.GetAsync(EnvironmentManager.Instance.UrlBuilder.LocalWhereIs("simpleTest.html")).GetAwaiter().GetResult(); + if (response.StatusCode == HttpStatusCode.OK) { isRunning = true; } } - catch (WebException) + catch (Exception ex) when (ex is HttpRequestException || ex is TimeoutException) { } } @@ -154,16 +157,16 @@ public void Start() public void Stop() { - using (var httpClient = new HttpClient()) + if (webserverProcess != null) { - using (var quitResponse = httpClient.GetAsync(EnvironmentManager.Instance.UrlBuilder.LocalWhereIs("quitquitquit")).GetAwaiter().GetResult()) + using (var httpClient = new HttpClient()) { + using (var quitResponse = httpClient.GetAsync(EnvironmentManager.Instance.UrlBuilder.LocalWhereIs("quitquitquit")).GetAwaiter().GetResult()) + { + } } - } - if (webserverProcess != null) - { try { webserverProcess.WaitForExit(10000); diff --git a/dotnet/test/common/Environment/UrlBuilder.cs b/dotnet/test/common/Environment/UrlBuilder.cs index 01f1864dad3bc1..8207eb622de626 100644 --- a/dotnet/test/common/Environment/UrlBuilder.cs +++ b/dotnet/test/common/Environment/UrlBuilder.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using Newtonsoft.Json; using System.Text; -using System.IO; +using System.Net.Http; namespace OpenQA.Selenium.Environment { @@ -105,25 +105,21 @@ public string WhereIsSecure(string page) public string CreateInlinePage(InlinePage page) { Uri createPageUri = new Uri(new Uri(WhereIs(string.Empty)), "createPage"); - Dictionary payloadDictionary = new Dictionary(); - payloadDictionary["content"] = page.ToString(); + + Dictionary payloadDictionary = new Dictionary + { + ["content"] = page.ToString() + }; + string commandPayload = JsonConvert.SerializeObject(payloadDictionary); - byte[] data = Encoding.UTF8.GetBytes(commandPayload); - - HttpWebRequest request = HttpWebRequest.Create(createPageUri) as HttpWebRequest; - request.Method = "POST"; - request.ContentType = "application/json;charset=utf8"; - request.ServicePoint.Expect100Continue = false; - Stream requestStream = request.GetRequestStream(); - requestStream.Write(data, 0, data.Length); - requestStream.Close(); - - HttpWebResponse response = request.GetResponse() as HttpWebResponse; - // StreamReader.Close also closes the underlying stream. - Stream responseStream = response.GetResponseStream(); - StreamReader responseStreamReader = new StreamReader(responseStream, Encoding.UTF8); - string responseString = responseStreamReader.ReadToEnd(); - responseStreamReader.Close(); + + using var httpClient = new HttpClient(); + + var postHttpContent = new StringContent(commandPayload, Encoding.UTF8, "application/json"); + + using var response = httpClient.PostAsync(createPageUri, postHttpContent).GetAwaiter().GetResult(); + + var responseString = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); // The response string from the Java remote server has trailing null // characters. This is due to the fix for issue 288. diff --git a/java/CHANGELOG b/java/CHANGELOG index 54c2a19b355fd1..f830df55253cfd 100644 --- a/java/CHANGELOG +++ b/java/CHANGELOG @@ -1,3 +1,67 @@ +v4.17.0 +====== + +* Self-signed certificate do not require certificate file (#13268) +* Remove deprecated event listener classes (#13200) +* Add ability to disable UI on grid (#13212) +* Recognise `chrome-headless-shell` as Chrome browser (#13292) +* Remove most of guava from remote package +* Add java to Selenium Manager input for tracking (see #13288) +* Add cookie support for network module (#13325) +* Refactored log capture and formatting code (#13322) +* Add support for Input module (Actions) (#13259) +* Close http connection for RemoteNode (#13313) +* Add Duration overload to SlowLoadableComponent constructor and deprecate the int (#13309) +* Improve logging errors (#13327) +* Ensure calling close() and quit() don't cause BiDi websocket errors (#13333) +* Check for emptiness instead of using length or size (#13335) +* Remove unnecessary overridden methods (#13336) +* improved logging when driver discovery failed +* WebSocket NoVNC session against the grid URL contains trailing slash (#13353) +* Updating channel name from Aurora to Dev +* Removing mentions to firefox-bin in docs and tests +* Deprecate FirefoxBinary class +* Deprecate json wire related ErrorCodes +* Fix the ScreenshotException message +* Add ShadowRoot.hashCode / .equals #13326 +* Deprecate unused RemoteStatus +* Remove use of guava from FluentWait +* Remove all references to firefox-bin +* Deprecate all html5 offline storage implementations See #10397 (#13373) +* Remove endpoints and commands that are not w3c compliant (#13372) +* Deprecate methods for getting and setting location (#13372) +* Deprecate methods for getting and setting network connection (#13372) +* remove non-w3c endpoint references that are mobile specific +* Add auth required event +* Copy the output in a daemon thread +* No longer accept session requests with desiredCapabilities +* Remove requiredCapabilities from metadata ignored list +* Deprecate `AddWebStorage` augmenter provider as well (#13399) +* Update logging and errors for driver management +* Deprecate `ContextAware` interface (#13405) +* Add check back to driver service session factory +* Fix broken driver finder conditional +* Node WebSocket not working with sub-path option (#13407) +* Add window proxy properties class +* Schema HTTPS in Distributor, SessionQueue, SessionMap (#13413) +* Add BiDi Input module release command (#13362) +* Add Node properties class as precursor to BiDi's locateNodes command +* Deprecate `NoSuchContextException` (#13425) +* Ensure the worker thread is stopped +* Log the complete exception +* Add deprecation annotation to FirefoxBinary +* Add a warning while passing a decorated driver to augmenter (#13246) +* Tapping the Node session when there is WebSocket activity (#12223) +* Small code improvement in ProxyWebsocketsIntoGrid +* Using `max-sessions` from Node when it was declared (#12836) +* Fix typo in NodeFlags (#13440) +* Add locate nodes command (#13445) +* Add user friendly methods to locate nodes +* Add click dialog support to Federated Credential Management implementation +* Use the ErrorCodec to encode exceptions +* Ignore null text of UnhandledAlertException +* Add CDP for Chrome 121 and remove 118 + v4.16.1 ====== diff --git a/java/maven_deps.bzl b/java/maven_deps.bzl index c51cd79c3ed025..60b6ef0cfbc85d 100644 --- a/java/maven_deps.bzl +++ b/java/maven_deps.bzl @@ -4,7 +4,7 @@ def selenium_java_deps(): maven_install( artifacts = [ "com.beust:jcommander:1.82", - "com.github.javaparser:javaparser-core:3.25.7", + "com.github.javaparser:javaparser-core:3.25.8", "com.github.spotbugs:spotbugs:4.8.3", "com.github.stephenc.jcip:jcip-annotations:1.0-1", "com.google.code.gson:gson:2.10.1", @@ -12,36 +12,36 @@ def selenium_java_deps(): "com.google.auto:auto-common:1.2.2", "com.google.auto.service:auto-service:1.1.1", "com.google.auto.service:auto-service-annotations:1.1.1", - "com.google.googlejavaformat:google-java-format:jar:1.19.1", + "com.google.googlejavaformat:google-java-format:jar:1.19.2", "com.graphql-java:graphql-java:20.2", "com.graphql-java:java-dataloader:3.2.0", "dev.failsafe:failsafe:3.3.2", - "io.grpc:grpc-context:1.60.1", - "io.lettuce:lettuce-core:6.3.0.RELEASE", - "io.netty:netty-buffer:4.1.104.Final", - "io.netty:netty-codec-http:4.1.104.Final", - "io.netty:netty-codec-http2:4.1.104.Final", - "io.netty:netty-common:4.1.104.Final", - "io.netty:netty-handler:4.1.104.Final", - "io.netty:netty-handler-proxy:4.1.104.Final", - "io.netty:netty-transport:4.1.104.Final", - "io.opentelemetry:opentelemetry-api:1.33.0", - "io.opentelemetry:opentelemetry-context:1.33.0", - "io.opentelemetry:opentelemetry-exporter-logging:1.33.0", - "io.opentelemetry:opentelemetry-sdk:1.33.0", - "io.opentelemetry:opentelemetry-sdk-common:1.33.0", - "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.33.0", - "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.33.0", - "io.opentelemetry:opentelemetry-sdk-testing:1.33.0", - "io.opentelemetry:opentelemetry-sdk-trace:1.33.0", + "io.grpc:grpc-context:1.61.0", + "io.lettuce:lettuce-core:6.3.1.RELEASE", + "io.netty:netty-buffer:4.1.106.Final", + "io.netty:netty-codec-http:4.1.106.Final", + "io.netty:netty-codec-http2:4.1.106.Final", + "io.netty:netty-common:4.1.106.Final", + "io.netty:netty-handler:4.1.106.Final", + "io.netty:netty-handler-proxy:4.1.106.Final", + "io.netty:netty-transport:4.1.106.Final", + "io.opentelemetry:opentelemetry-api:1.34.1", + "io.opentelemetry:opentelemetry-context:1.34.1", + "io.opentelemetry:opentelemetry-exporter-logging:1.34.1", + "io.opentelemetry:opentelemetry-sdk:1.34.1", + "io.opentelemetry:opentelemetry-sdk-common:1.34.1", + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.34.1", + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.34.1", + "io.opentelemetry:opentelemetry-sdk-testing:1.34.1", + "io.opentelemetry:opentelemetry-sdk-trace:1.34.1", "io.opentelemetry.semconv:opentelemetry-semconv:1.23.1-alpha", "io.ous:jtoml:2.0.0", "it.ozimov:embedded-redis:0.7.3", "net.bytebuddy:byte-buddy:1.14.11", - "org.htmlunit:htmlunit-core-js:3.9.0", + "org.htmlunit:htmlunit-core-js:3.10.0", "org.apache.commons:commons-exec:1.3", - "org.apache.logging.log4j:log4j-core:2.22.0", - "org.assertj:assertj-core:3.24.2", + "org.apache.logging.log4j:log4j-core:2.22.1", + "org.assertj:assertj-core:3.25.1", "org.bouncycastle:bcpkix-jdk18on:1.77", "org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5", "org.hsqldb:hsqldb:2.7.2", @@ -52,11 +52,11 @@ def selenium_java_deps(): "org.junit.platform:junit-platform-reporting:1.10.1", "org.junit.platform:junit-platform-commons:1.10.1", "org.junit.platform:junit-platform-engine:1.10.1", - "org.mockito:mockito-core:5.8.0", + "org.mockito:mockito-core:5.9.0", "org.mockito:mockito-inline:5.2.0", - "org.redisson:redisson:3.25.2", - "org.slf4j:slf4j-api:2.0.9", - "org.slf4j:slf4j-jdk14:2.0.9", + "org.redisson:redisson:3.26.0", + "org.slf4j:slf4j-api:2.0.11", + "org.slf4j:slf4j-jdk14:2.0.11", "org.zeromq:jeromq:0.5.4", ], excluded_artifacts = [ diff --git a/java/maven_install.json b/java/maven_install.json index d0c045f5821e10..5be19360e420cb 100644 --- a/java/maven_install.json +++ b/java/maven_install.json @@ -1,7 +1,7 @@ { "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", - "__INPUT_ARTIFACTS_HASH": -1132813251, - "__RESOLVED_ARTIFACTS_HASH": 1655089516, + "__INPUT_ARTIFACTS_HASH": 892178197, + "__RESOLVED_ARTIFACTS_HASH": -1231266529, "artifacts": { "com.beust:jcommander": { "shasums": { @@ -12,10 +12,10 @@ }, "com.esotericsoftware:kryo": { "shasums": { - "jar": "4b902a21d99f7b4c32e6f7400e91f9284fd184db881bb9e18328e14d8127f7f9", - "sources": "a7fe17d9e5c3f18ba2070b1356aeafc3f1626e8ebb6161a70d84c2f17adcd072" + "jar": "ead0f39530d6f30d27791eeb81621f3d7445331a06c32b3302e0ebe9e04b3a5d", + "sources": "fe808d5e9370797ebeddd87f1aefb84c15281a18148388645c79c2382acc1e5f" }, - "version": "5.5.0" + "version": "5.6.0" }, "com.esotericsoftware:minlog": { "shasums": { @@ -33,38 +33,38 @@ }, "com.fasterxml.jackson.core:jackson-annotations": { "shasums": { - "jar": "aae865c3d88256d61b11523cb1e88bd48d5b9ad5855fa1fc859504fd2204708a", - "sources": "9b3f2b6791a3e775cec9b9be575add9406b8423d8b49662b78c1017f22952528" + "jar": "a4730771e6a495dd3793a42cdb8ce6bddb96c77e15f40c98fd8d9a7ae09e7286", + "sources": "cebdb714198d5b3a152efb9e940dc9eb26cb37aa688ce34431b99afb790f6be3" }, - "version": "2.15.3" + "version": "2.16.1" }, "com.fasterxml.jackson.core:jackson-core": { "shasums": { - "jar": "51fab7aad51ed588482edc507fd542747936c5094d1ab76ed21ddb63b96b610d", - "sources": "31cb17527c55716c59fb0a10736b1b29306b4db0de8476e1ab6e54f85fe4ff55" + "jar": "f5f8ef90609e64fec82eb908e497dc7d81b2eb983fe509b870292a193cde4dfb", + "sources": "1bd334b0de7d02d7f8a6591f775a28126b1cdce9cd9ae6dc260482b7bdd9a04c" }, - "version": "2.15.3" + "version": "2.16.1" }, "com.fasterxml.jackson.core:jackson-databind": { "shasums": { - "jar": "c3c53333a2172a80678bda1803e39cff45bec6ae3e9c7d4f44a81ec4e2ab18dc", - "sources": "d692cdf070e03c11e95306da08ecdf312aac559f158019a5bfcdc6e0798d5456" + "jar": "baf8a8ebee8f45ef68cdd5e2dd3923b3e296c0937b96ec0b4806aa3a31bccd1d", + "sources": "91390204018cbeb9c5ed6e60c2624b63c8221082af9b0e94ce7f2d926ec48e2c" }, - "version": "2.15.3" + "version": "2.16.1" }, "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml": { "shasums": { - "jar": "2dd70a080e8542dc5ee727387abed963fc24122cd784ab38355f87d0e08d9772", - "sources": "25889879ca0a0612fa94711cca7e49137069984c979dab51dda9e736d1a1c881" + "jar": "fd67e0fafe368ad3dfc1b545eb8fe084a5c64628fb71ef70bd94a4dab27aefff", + "sources": "fee5fa554e06bf36f697e32f98d255528b54fc8901bcf59ad5ce41c4e35784b5" }, - "version": "2.15.3" + "version": "2.16.1" }, "com.github.javaparser:javaparser-core": { "shasums": { - "jar": "159f5e5024d0548ec63cf9d2488ad410d646164581570235ed04eef69242d2d6", - "sources": "83383028a7f0fa648f26e74977d3ebbf86f98f6fb7ba58d9605d8c2832485575" + "jar": "3ac2c42a234c1ee43a55bc22911934ddd537bba78931265d072ed34c22b06d96", + "sources": "b6eb63a106b16e0c2953b985d15c3126fa772e550d9f9be60c0cdd2d4d29880d" }, - "version": "3.25.7" + "version": "3.25.8" }, "com.github.spotbugs:spotbugs": { "shasums": { @@ -131,10 +131,10 @@ }, "com.google.googlejavaformat:google-java-format": { "shasums": { - "jar": "ff15abac529f6ecb97878aa2ae271a4d3b15f526c1f823757dd8781c0b11c73b", - "sources": "14970cf44a06ae9e7e160ed9888c7d8ffa229dbdbdc57ad4725d5ceaaa9a7273" + "jar": "bac84458eb12499585f2fabb1ac13bbe5b455c120bf3d19db21597814a27c863", + "sources": "003cadae4d160a84e9ce62ffb375e5e13b4cd129c4581a93739f0209d289d80b" }, - "version": "1.19.1" + "version": "1.19.2" }, "com.google.guava:failureaccess": { "shasums": { @@ -215,115 +215,115 @@ }, "io.grpc:grpc-api": { "shasums": { - "jar": "bdcefde43d7c542e748adb7b2bccc46db16313ba86ab46f8ba3b54677c7c5883", - "sources": "23d0d4bb5eed8cf0b5732ab96c815028071e2b3537bd39f5dfe0c8f16731e74c" + "jar": "30f314fd84e03053d07b4ddf84bcc5889cf30aac219bb1d08d8fc2f8c54f4255", + "sources": "857004e81fc269c60ccbe810fb9be529a957677785c676520bf1e1b42e28734a" }, - "version": "1.60.1" + "version": "1.61.0" }, "io.grpc:grpc-context": { "shasums": { - "jar": "4ab6efb9cbadc88f8dc723ada3a61785da367697373d4432aef5222312aa70f6", - "sources": "90655e7ff0d7ee867fbdf7c6ac6db13ef9b339f4e8e3af15665f5a98101f9674" + "jar": "21f4ac4c5e9517a2d0282438fd83f0659e8cac226bf05e0860f84c899bceab61", + "sources": "8bede6b622dd0d7dd7c5a69e97e01c54eb0e1a4e2cdc2a67f3bf0b2e275c6fa4" }, - "version": "1.60.1" + "version": "1.61.0" }, "io.lettuce:lettuce-core": { "shasums": { - "jar": "9dfcc129e672004933675fa1595432989207bfe71a06813c9eb35daa76e9b380", - "sources": "4bc510812fe188972129cfe37ddbb3099f242766411cdc15a95c6dd0f42574ed" + "jar": "bc74138f8be5a2eac27a7a91fa076d012fc882a363d5b171e7f9d7fd481ae935", + "sources": "021f28d8ac9b1d125ce0407316440c032245a73b7bf0166489eb28d09c78b490" }, - "version": "6.3.0.RELEASE" + "version": "6.3.1.RELEASE" }, "io.netty:netty-buffer": { "shasums": { - "jar": "1e5361d1371ae75836717a22d0b0fba8393ef3ddb345abd7581c97c37aeac568", - "sources": "52313acd4c59490aa920f60e6d4a1dcd011938cb83d7960b9b65492a45b3566c" + "jar": "d5067bdbe476d63cb43293822832a749a7c38a38c1c516107c73d257c39bed21", + "sources": "3f372883eb88f27777870a55e02964fb84e3c474693e9c2213c04b6a246386ec" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.netty:netty-codec": { "shasums": { - "jar": "36d9840e76de66fbf60da20d740b3974a3545b0a4d68a16a7c19ae998f541098", - "sources": "01a138c7598cde0a8c10212eb07e502fb07694da0622d2b6a65d8c25a4681a86" + "jar": "93863dfd690f7ace7c26e4c808fdc24780adad465b3cdcb7ce3fc73c422df76f", + "sources": "7a2fa3c3645023d7ff66a5784e18ca18c0019a18fa9b7eb77fcb8e97e358af4e" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.netty:netty-codec-dns": { "shasums": { - "jar": "e85d0929d017f0f625495e5ce1c033b1ba6f30d53b1fb5f403cac0a7e996babe", - "sources": "a1e04a990582dc3a2a264c65b3ebe8c85a4b550ee80eec1dca3d149506557089" + "jar": "d174befa24f1259366d234a1f814260534a6a8ec57079bfa444db183ca83954b", + "sources": "797e1f5e56634384b742d9dfaf17061a417d14c17e82c33ddce04f112f79397e" }, - "version": "4.1.101.Final" + "version": "4.1.104.Final" }, "io.netty:netty-codec-http": { "shasums": { - "jar": "8e635413e623f3f1b337524931be620feb0369def735ede338f67db55cf8fc9b", - "sources": "46c2d7925f206182690dbf65c2ce3e3b5b1c3d238d74a07e6f38fc766667a854" + "jar": "ba177a03adc587fa63e96f1dbae9c46ff25f59397ea34d960b45e05d0296026e", + "sources": "0e6837b9333587132112dcaadd57944ce857629f3c3de83b1892be76290e0765" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.netty:netty-codec-http2": { "shasums": { - "jar": "fc03e6a2cc2d59f80fb1ec2957621e2630a952db36e069ccbbd72e0662796881", - "sources": "0d4ad8ee856810d067cab5bdb29cfe8bbfaeb70350ce5215694e1cff850ba679" + "jar": "c2b821d57a733cd671ea2ab0642002b17e0a2b89004ca026c6eae8f5381cf81e", + "sources": "c777aeac2033d0ab523c59a2c4415d29bc008d7a1521b12ab0954dc53fbadcea" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.netty:netty-codec-socks": { "shasums": { - "jar": "c8fac27f4d78fb3abd627907a5412fbe85fecc0671fa36f9ef7d0d26670caf05", - "sources": "116e937045816dc6ec366b3a0d056d9889480262d74cabab3fe81cf58442ae18" + "jar": "9811f9bf20a6128518d92182527867e40a0dbc41ea5380d61e284ff9f4f488a3", + "sources": "a9087a65786fec2ed3acc2be70905718ece9fbc67967e9e543b88fd1a351ef5a" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.netty:netty-common": { "shasums": { - "jar": "b98b35afc0c704039dc636c5531583e3100c65e1c6bbf1b109761324bbedb06a", - "sources": "fa2558b8e4b6cdda2e68cad36599c2002bd378dd84a8ec10f216adafbcbbb7e4" + "jar": "5ffbe01bd845617a916de3613010d5fda57c5eb694147d38d04f791e9834d5c3", + "sources": "f4ab6ad6fbf4fde6614bbbde3dc2d9193759404e20b8dc13c366c8e34b91b64a" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.netty:netty-handler": { "shasums": { - "jar": "4c30c26d158fbf6dcebb54f8524e902a0df4fc6157f597af96a27f5459f7d046", - "sources": "e8b58f68d193e51f7a4b195aa7586f358c6c184d14764e0d8e155614508f6075" + "jar": "5a919ad88b6d9e9f08c3069980bc656a62926a00e6ba2da5859aa0ee4e202e44", + "sources": "d0c62a058047fa34b2798adb766a968516f27897a6c81cc89a3f60a01a5554f0" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.netty:netty-handler-proxy": { "shasums": { - "jar": "a61bbbbe33c116a278b1e5baa567c6b5d6bd77814360870093bf6e51c12c6157", - "sources": "dbf11d2c29e5fb707ab7e7cb346497cbbc5481d1ff39ed9e0bd67ece93c93d1b" + "jar": "829a9c49afe0cb72d8c27a067d6bd61afb698ffa0db8117411b7437ecd83db7a", + "sources": "67cfaa69d8af1f9aa26b5d7bafde6856c3eebc085b5f772f13fc0e30010153d5" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.netty:netty-resolver": { "shasums": { - "jar": "7d1cf459a1094cdefdae457686118d9dcc00d96b0ad1cea798483a43ffca1064", - "sources": "dd7e89f78a5550712ff52dd6a97d8adf1faa7a1d78aed45cbc45e9f76a2c1134" + "jar": "404958b8f0590ee526013d011cd2354dab78adbaad743d7d444db33a3f9eabac", + "sources": "ee95bd01f3c06cebb78ae1a8c09a96650f1be5f423e47d69bb3004010807a489" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.netty:netty-resolver-dns": { "shasums": { - "jar": "a1b7fef032fce3446a7307e5aeb02126d92c0b38f00aae4f2f0de65d3215cd90", - "sources": "4116ddb2af3d20d55b99c9c17d594e461dc5d26e871d0daf0fb8abb94832158d" + "jar": "f40076554db69eec20e0f8de5c92a540d3c50909e416d2c7d8f7e1b27d84b4a8", + "sources": "2f9b1e3f239f4ebebe6b314914aa6ae53c3eb173dbe4794db2730717e79e8a33" }, - "version": "4.1.101.Final" + "version": "4.1.104.Final" }, "io.netty:netty-transport": { "shasums": { - "jar": "28fd78156e8908146e66d247985aa5018a4bce9503c5b3d883481448b23270d3", - "sources": "91ee6de4bba5621e0cf78233254a6e27ae363244b15b425b148074c3a89909b7" + "jar": "23ea9a39009b41e9d0aa1515b3073af9ee4da4e16c2e869b5aa8aa9f109d4251", + "sources": "7e69c12c5a160af900ebba3aa00a7c41e9072fca5ee78ea41b4ddcdaf398b492" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.netty:netty-transport-native-unix-common": { "shasums": { - "jar": "c12f39c8f12a6ba64078caf75fd97a7fbd05643001f424e8b84829b35d402f4e", - "sources": "9b7cd573f01b2210131ac16189af586a4a097f4edd13f9969c71c7488c63d285" + "jar": "f52d4b38c571066bfaae964a7867fa937f0e54fb5ff467c576cb650a20a854e8", + "sources": "9e7893c3c8538d7f948a5aabae1f0eecd8ce8fb6ad22f48b09c9124058695ca7" }, - "version": "4.1.104.Final" + "version": "4.1.106.Final" }, "io.opentelemetry.semconv:opentelemetry-semconv": { "shasums": { @@ -334,94 +334,94 @@ }, "io.opentelemetry:opentelemetry-api": { "shasums": { - "jar": "f3bf6f0ded42812cb41f88f7bfe5812e28f76b94679ff69ac4c2cc6aec12a267", - "sources": "da4e5f96b3c44797d994c38e73c57488141235de1d6493f1aaf21516c9df7f4a" + "jar": "3820fbe846e9f3cad55f0fe1ba72467da9343d1a14cc7a7bd536d4040ab17df9", + "sources": "dad218a595d81790e6cff69a9fa5350e4252d4d35696c6a16deb08d74b220bd6" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.opentelemetry:opentelemetry-api-events": { "shasums": { - "jar": "27016923be7cf92568a8ad596797cf2ec00d242e775ffa7c3fb65bf15b268fba", - "sources": "35746fba74c7703561be68933a6a17323b9b3752a9a8ac91d6d62b265e87188b" + "jar": "f79a27b8300ddb57eb21c7d662db469b34d9f86253529c720eb067ce55c1b345", + "sources": "004befb8e11373ece1d1e87ad2126479fd5e4b5ca99a097bdb27c4913aafe70c" }, - "version": "1.33.0-alpha" + "version": "1.34.1-alpha" }, "io.opentelemetry:opentelemetry-context": { "shasums": { - "jar": "8aa867f353036c6a8e8bf06ae2fec54658d8eafda82f857506ff934fd403048a", - "sources": "34a17f4a25995243ccb8b63fcf3b27e922d2a785496b4cb46b406e39b6208015" + "jar": "62d34f3dbf37783dc0223afe612bccecdccf404eb25cef95a3ab90fcaa689975", + "sources": "ff18ed9626cc2865963b4c248a83baebb3eade37eef902a9edac83096834f2e4" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.opentelemetry:opentelemetry-exporter-logging": { "shasums": { - "jar": "d548ce63e219abbbcf67b45affc5a15579962078d783d1a89f6eba9985723d8f", - "sources": "a6f37c6c47f0f2be34e34f9f4c70b6ae0ea8967b128b448ec93001ed5a685b81" + "jar": "ebe441682652ad91cf4a6daf7d17974f31571dc21dc5d8c60b21d1c2986270f1", + "sources": "7128531aed3017840193e6c1fde8af5ded44b9b9ac1ef70c3d0b1680648024e2" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.opentelemetry:opentelemetry-extension-incubator": { "shasums": { - "jar": "18123858e17f0aed3cb029562add36b47e1a302707fd2948ce2cb19f679863fc", - "sources": "1b477c0eb0f497fece039a12f42bfe5e3d2d4924a09b97aca1392e15a197f95e" + "jar": "63f7948e7d34b81b8adb11ac8cee5738a333e57954c7da28231eca168656514d", + "sources": "464fc29e010668b209e8754b30e6b9650a447c12aa2109f8a19899ce2a7612c1" }, - "version": "1.33.0-alpha" + "version": "1.34.1-alpha" }, "io.opentelemetry:opentelemetry-sdk": { "shasums": { - "jar": "8a9b32722e9732d4c22402e1351dbd4cec5131447f151b560a184a4680e67d84", - "sources": "bdccb49cae5aea8029c603f17e95f986e2d3a831d43bb41a2489466bd38c6dd9" + "jar": "de1f9ab3f1d0ddfcf6d698f3059352f6ecfbdff4318424eeca62e1eea6b745cd", + "sources": "5d96356bb6dfec674c72f4d627c1a539b357315d2e0a17fb109ae657f9b794e6" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.opentelemetry:opentelemetry-sdk-common": { "shasums": { - "jar": "b344a6d2d5f82c03615c7b84f2ea6b666a86ec1ae5da27121179d349579e811f", - "sources": "51ee1e4ff1c1d42dda4f23616f1a99442682d4fa6c9be219e76945fcb869d52b" + "jar": "bfe9c8efe2c397294527b9a347934187f9b0de805d2cad642017ec7d9b71afc5", + "sources": "3e66c9ef8c1eded8ddd9624d92a61310c2084c498d9a76d34a3a4f6f761ecf66" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure": { "shasums": { - "jar": "30d9368e3fd812b148b78460c55de4e3092931c1be40c935123f00bcd3bc86ed", - "sources": "421002ec45e634fd612f6e5241f82483186ef60b2de85b9c52018944c89ec40b" + "jar": "7332d834f3b35082550a22c99db52596b6d9d9b344076210e4a3bc0627704356", + "sources": "190f7e9246f3248f9880008fc5447399a3bb94e2c5cc3b75df1ce54605953a69" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi": { "shasums": { - "jar": "ed8e236e1ad56721ceed9df349b9b9b25f8fd8d603a1f8840ee517516894c736", - "sources": "f184bf2d58d71df8e0bf493ad8e35f0e98c81d5a50efc27146b2d43db4e36f7d" + "jar": "5a3bc2619fa50f176c21abf08ecfa98dd8e8980f154cca2b74a0a74e7d1cf473", + "sources": "74408a88c497e4ed859ff2529fdfc353a0910e66d46d37c7adf59a70966abb0e" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.opentelemetry:opentelemetry-sdk-logs": { "shasums": { - "jar": "2e0be0791f28595388cf922c145ab7ad889395935b3b45c4ec606b7b5604116f", - "sources": "ced5036da94572576212061314ecb1a766c1c53e31fab8d85bd2668e783a94f2" + "jar": "0bf40a630aa4115fd549fdd7dcf77eb1f6c079e0d02ab0d81a415d5fb0848f35", + "sources": "e6bcf41a857fe1ad43b84367f407b0df8ffbf34f8f6ab9c19356cad9c76e7bbe" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.opentelemetry:opentelemetry-sdk-metrics": { "shasums": { - "jar": "62fb0c0839538adf9b6976d352f06e46adc2a54e79043ff7934c1ae0fc114b4e", - "sources": "e46ca8c65e839b5b6ad06e28926daf83c6b1b5e00f42c3dbf28248012a46a1ab" + "jar": "a983e742c26006ba08888a5fb89f085f92dd81c923febe3ac5c6259b7ec9935d", + "sources": "d94634ef319b19fc6701786c75100cacb057857cd614c9ec9d8b5becd6087ad9" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.opentelemetry:opentelemetry-sdk-testing": { "shasums": { - "jar": "c75adc09985a49467a0d8a413a9d76f69760325aaf7368f04b5c2e0465e541d8", - "sources": "c2aaa9739c36a57ae3f1ed8b4ed7aefba3d19060f3a71563ae0bc526bdd6fd97" + "jar": "15cf6d948e3c7822b8c3ea97058115b3972da1909e8e954eab568d643c471ff5", + "sources": "785fe453db6b77fe748c910fd7e72a7ad47437853b3eee53b17356e51eb8eea8" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.opentelemetry:opentelemetry-sdk-trace": { "shasums": { - "jar": "dd9c2a5949263cc7777720090c11036221ddce4a5fa33d65d4bae47ba157178a", - "sources": "9e09c2f8f78d13c8da5ad183158df03f610ff5922596a8e8c6dbaca528b55225" + "jar": "973b2d7b70cdd7a6ac122b1e2e7a756f18840b6bfddccb3710f59d5c18ec7b6c", + "sources": "0c5602581d96d7afc97d153ecef1b256e404ef005e42c39fc7a5e612d6769389" }, - "version": "1.33.0" + "version": "1.34.1" }, "io.ous:jtoml": { "shasums": { @@ -432,10 +432,10 @@ }, "io.projectreactor:reactor-core": { "shasums": { - "jar": "1b37779edf618eb526d27986329740fa5c25c61568ca812812d0cca127ceeac1", - "sources": "daf5a79a7b462122794f7073075aabe79a6c077a8c44a8bf0e7bd5c847dd679e" + "jar": "6e235f0be9732ebd6a42c585dfd53274065978bfbc28d721d7ecf487fde27b52", + "sources": "57e48b121636923ec362aa337556150edc8bc29ccba686c21d36016e05207b23" }, - "version": "3.6.0" + "version": "3.6.2" }, "io.reactivex.rxjava3:rxjava": { "shasums": { @@ -474,10 +474,10 @@ }, "net.bytebuddy:byte-buddy-agent": { "shasums": { - "jar": "67993a89d47ca58ff868802a4448ddd150e5fe4e5a5645ded990d7b4d557a6b9", - "sources": "aebd1ea7ef0cf57d7ce3dfcf7ab73479c5a8158144a4d2bece6dd2587674b3ea" + "jar": "2f537a621a64fa7013d68c695a76a34ee8d79dad74e635caca16dd56257aeb80", + "sources": "1e3618de3b0f81a43c7480aea392dd7905f9dce275e6665003ec331b4531ced4" }, - "version": "1.14.10" + "version": "1.14.11" }, "net.sf.saxon:Saxon-HE": { "shasums": { @@ -537,17 +537,17 @@ }, "org.apache.logging.log4j:log4j-api": { "shasums": { - "jar": "1342c86c2a0848fc2f3d16b8544849f29fa31bf7af79f6066c2677ba29e47cf3", - "sources": "f5a159788be335a4458f4b1330a13a9ab9c7f52a17897f8445d9cde8d9c8e411" + "jar": "5d7beae7ff15d8516d6517121d7f12a79a6ac180df64b5fcec55d5be21056e53", + "sources": "da73464bd4887421a2b0677f8e29158e5af8642f0a8523a99cec6064b637197d" }, - "version": "2.22.0" + "version": "2.22.1" }, "org.apache.logging.log4j:log4j-core": { "shasums": { - "jar": "aacb1b935c0070f644060c1fbc9b555f344cbfe8d0ef1234b464eb58bd7b8ad2", - "sources": "3a1f8e5b74026f4950feb125b9cdc0ddd46364e6b4d971af2a543555e92b4d09" + "jar": "46dccecac556623d8e2ce8648496824a82951d139062a4e61148aff1a25ed18d", + "sources": "07eaa7939a5940c7c99f5acfda3a06dbb04d74f083455b535e42811a45c1b07e" }, - "version": "2.22.0" + "version": "2.22.1" }, "org.apiguardian:apiguardian-api": { "shasums": { @@ -558,10 +558,10 @@ }, "org.assertj:assertj-core": { "shasums": { - "jar": "df3d0b348f1fe806bdddcb10fa4ae63c6679e9888d4bc7055f09848517976aa3", - "sources": "67cbf29f82539b16e985a073937b19373443af000983986d05a5962ff9108fa7" + "jar": "620da4e4de03108c2f412ec17a7ed44b0112dc65e181bd0732dc96fa3b65356f", + "sources": "511d810fd60b6d4874326354eff9e657bbe37fa3a2b8658f22c49a48fe5fa195" }, - "version": "3.24.2" + "version": "3.25.1" }, "org.bouncycastle:bcpkix-jdk18on": { "shasums": { @@ -614,10 +614,10 @@ }, "org.htmlunit:htmlunit-core-js": { "shasums": { - "jar": "8e67c1435dac87884300dfe91e7c4900275c4328ac9432d4aec955e3f2f3ab16", - "sources": "e381737dcd02d18300bb62d64350960dd6ebdeeed032d119bb1d258d49718e5c" + "jar": "3c0a5b41e073fac91272bca9a252be88ef2a2bc33f0413c4b7adf5a71cf64e94", + "sources": "fd1757e62c918051000fb08702f30ef898b73baabcb06de23be84149941ad489" }, - "version": "3.9.0" + "version": "3.10.0" }, "org.jboss.marshalling:jboss-marshalling": { "shasums": { @@ -698,10 +698,10 @@ }, "org.mockito:mockito-core": { "shasums": { - "jar": "c320f662a03c2951edcc51a44b64d79a8e994373ff548453b5fdaf69debe4682", - "sources": "c47a3b0a3a4766a058d3fc458eea45420fdd4e39ef4d09d88cc70d002fdf4386" + "jar": "bbad9185ed734965fac7e367f0e51596f69531e51d8b2cbcec1048dd6fb41f2c", + "sources": "3da5c463fe8daeec00829a9d6eaaea59e552fca3114be918cfcb01d52fd2c6a1" }, - "version": "5.8.0" + "version": "5.9.0" }, "org.mockito:mockito-inline": { "shasums": { @@ -768,24 +768,24 @@ }, "org.redisson:redisson": { "shasums": { - "jar": "8219a757a49087fa468163706b05356176fbe41f5c1fc2be756cd6c9e41b5924", - "sources": "87f895c24e641bd676e19aefea5123aaa45bce2b9a09efa3ae09a45ba6839dfb" + "jar": "20ad8dbd0a55d0d0f41b0d91aaed5b08dcb8fe41a698df58bd52763db1a2653b", + "sources": "c39037b2195417b347eb3463e6ed7f80510a389ad65d8648211000a151b20bea" }, - "version": "3.25.2" + "version": "3.26.0" }, "org.slf4j:slf4j-api": { "shasums": { - "jar": "0818930dc8d7debb403204611691da58e49d42c50b6ffcfdce02dadb7c3c2b6c", - "sources": "0d83bc49452416dd121ee41cebf41cdc64b69e7f7fdc97c2762ec406336c7ad3" + "jar": "ce0e71d673acb9036bb55d0244b261cf033f8e4c1245f14f931dfb1937dd4c95", + "sources": "3c1357260d1c649aa747bc6ba7b78fb6ea1bd2f7e6fabd9c6412e9d5c6e2ea0c" }, - "version": "2.0.9" + "version": "2.0.11" }, "org.slf4j:slf4j-jdk14": { "shasums": { - "jar": "1052aa82851c36f76465e64539ad4450338a86094e638a5cb1b3ce7a0dabfb18", - "sources": "a9386cb9fe3e29aad418a945c5f1c21947695de5fbf955151ff69ba66f147cf3" + "jar": "1ce8ae1f20dec00a0ac08bb92a773168a57651bac69869a457285a5a7c8c7097", + "sources": "66146380abf8465c53599d76b480167476ae2f5ce795ef82109c5cdb83d6bea3" }, - "version": "2.0.9" + "version": "2.0.11" }, "org.slf4j:slf4j-simple": { "shasums": { @@ -804,10 +804,10 @@ }, "org.yaml:snakeyaml": { "shasums": { - "jar": "69a4537045ddbcaed4c68eef074462eb12d324d7953f62c5ecd35df645e8aec9", - "sources": "73380d803d59b1db194521449d2cc3617a2d5a0eb5528cdc2cd70fdaa4074de0" + "jar": "1467931448a0817696ae2805b7b8b20bfb082652bf9c4efaed528930dc49389b", + "sources": "8f7cf911cf63db55fd980a926d155bd846317737351a2f48ef1c1088c414538a" }, - "version": "2.1" + "version": "2.2" }, "org.zeromq:jeromq": { "shasums": { @@ -832,9 +832,6 @@ "com.fasterxml.jackson.core:jackson-databind", "org.yaml:snakeyaml" ], - "com.github.javaparser:javaparser-core": [ - "com.google.guava:guava" - ], "com.github.spotbugs:spotbugs": [ "com.github.spotbugs:spotbugs-annotations", "com.github.stephenc.jcip:jcip-annotations", @@ -2763,6 +2760,7 @@ "org.redisson.api.map", "org.redisson.api.map.event", "org.redisson.api.mapreduce", + "org.redisson.api.options", "org.redisson.api.queue", "org.redisson.api.redisnode", "org.redisson.api.search", diff --git a/java/src/org/openqa/selenium/bidi/BrowsingContextInspector.java b/java/src/org/openqa/selenium/bidi/BrowsingContextInspector.java index 9eb4048c7ac999..08f4b9ddef2daa 100644 --- a/java/src/org/openqa/selenium/bidi/BrowsingContextInspector.java +++ b/java/src/org/openqa/selenium/bidi/BrowsingContextInspector.java @@ -113,7 +113,7 @@ public void onBrowsingContextCreated(Consumer consumer) { } } - private void onBrowsingContextDestroyed(Consumer consumer) { + public void onBrowsingContextDestroyed(Consumer consumer) { if (browsingContextIds.isEmpty()) { this.bidi.addListener(browsingContextDestroyed, consumer); } else { diff --git a/java/src/org/openqa/selenium/bidi/Network.java b/java/src/org/openqa/selenium/bidi/Network.java index 4cba35cc180fcd..6bd26205068be8 100644 --- a/java/src/org/openqa/selenium/bidi/Network.java +++ b/java/src/org/openqa/selenium/bidi/Network.java @@ -19,9 +19,12 @@ import java.util.Collections; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.function.Consumer; +import org.openqa.selenium.UsernameAndPassword; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.bidi.network.AddInterceptParameters; import org.openqa.selenium.bidi.network.BeforeRequestSent; import org.openqa.selenium.bidi.network.ResponseDetails; import org.openqa.selenium.internal.Require; @@ -64,6 +67,53 @@ public Network(Set browsingContextIds, WebDriver driver) { this.browsingContextIds = browsingContextIds; } + public String addIntercept(AddInterceptParameters parameters) { + return this.bidi.send( + new Command<>( + "network.addIntercept", + parameters.toMap(), + jsonInput -> { + Map result = jsonInput.read(Map.class); + return (String) result.get("intercept"); + })); + } + + public void removeIntercept(String interceptId) { + this.bidi.send(new Command<>("network.removeIntercept", Map.of("intercept", interceptId))); + } + + public void continueWithAuth(String requestId, UsernameAndPassword usernameAndPassword) { + this.bidi.send( + new Command<>( + "network.continueWithAuth", + Map.of( + "request", + requestId, + "action", + "provideCredentials", + "credentials", + Map.of( + "type", "password", + "username", usernameAndPassword.username(), + "password", usernameAndPassword.password())))); + } + + public void continueWithAuthNoCredentials(String requestId) { + this.bidi.send( + new Command<>( + "network.continueWithAuth", Map.of("request", requestId, "action", "default"))); + } + + public void cancelAuth(String requestId) { + this.bidi.send( + new Command<>( + "network.continueWithAuth", Map.of("request", requestId, "action", "cancel"))); + } + + public void failRequest(String requestId) { + this.bidi.send(new Command<>("network.failRequest", Map.of("request", requestId))); + } + public void onBeforeRequestSent(Consumer consumer) { if (browsingContextIds.isEmpty()) { this.bidi.addListener(beforeRequestSentEvent, consumer); diff --git a/java/src/org/openqa/selenium/bidi/network/AddInterceptParameters.java b/java/src/org/openqa/selenium/bidi/network/AddInterceptParameters.java new file mode 100644 index 00000000000000..1c0611364e98c1 --- /dev/null +++ b/java/src/org/openqa/selenium/bidi/network/AddInterceptParameters.java @@ -0,0 +1,67 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.bidi.network; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class AddInterceptParameters { + + private final List phases = new ArrayList<>(); + + private final List> urlPatterns = new ArrayList<>(); + + public AddInterceptParameters(InterceptPhase phase) { + this.phases.add(phase.toString()); + } + + public AddInterceptParameters(List phases) { + phases.forEach(phase -> this.phases.add(phase.toString())); + } + + public AddInterceptParameters urlPattern(UrlPattern pattern) { + this.urlPatterns.add(pattern.toMap()); + return this; + } + + public AddInterceptParameters urlPatterns(List patterns) { + patterns.forEach(pattern -> this.urlPatterns.add(pattern.toMap())); + return this; + } + + public AddInterceptParameters urlStringPattern(String pattern) { + this.urlPatterns.add(Map.of("type", "string", "pattern", pattern)); + return this; + } + + public AddInterceptParameters urlStringPatterns(List patterns) { + patterns.forEach(pattern -> this.urlPatterns.add(Map.of("type", "string", "pattern", pattern))); + return this; + } + + public Map toMap() { + Map map = new HashMap<>(); + map.put("phases", phases); + if (!urlPatterns.isEmpty()) { + map.put("urlPatterns", urlPatterns); + } + return map; + } +} diff --git a/java/src/org/openqa/selenium/bidi/network/InterceptPhase.java b/java/src/org/openqa/selenium/bidi/network/InterceptPhase.java new file mode 100644 index 00000000000000..bec0b451360aeb --- /dev/null +++ b/java/src/org/openqa/selenium/bidi/network/InterceptPhase.java @@ -0,0 +1,34 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.openqa.selenium.bidi.network; + +public enum InterceptPhase { + BEFORE_REQUEST_SENT("beforeRequestSent"), + RESPONSE_STARTED("responseStarted"), + AUTH_REQUIRED("authRequired"); + + private final String value; + + InterceptPhase(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } +} diff --git a/java/src/org/openqa/selenium/bidi/network/UrlPattern.java b/java/src/org/openqa/selenium/bidi/network/UrlPattern.java new file mode 100644 index 00000000000000..eb021db05b1ef6 --- /dev/null +++ b/java/src/org/openqa/selenium/bidi/network/UrlPattern.java @@ -0,0 +1,55 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.bidi.network; + +import java.util.HashMap; +import java.util.Map; + +public class UrlPattern { + private final Map map = new HashMap<>(); + + public UrlPattern protocol(String protocol) { + map.put("protocol", protocol); + return this; + } + + public UrlPattern hostname(String hostname) { + map.put("hostname", hostname); + return this; + } + + public UrlPattern port(String port) { + map.put("port", port); + return this; + } + + public UrlPattern pathname(String pathname) { + map.put("pathname", pathname); + return this; + } + + public UrlPattern search(String search) { + map.put("search", search); + return this; + } + + public Map toMap() { + map.put("type", "pattern"); + return map; + } +} diff --git a/java/src/org/openqa/selenium/devtools/events/CdpEventTypes.java b/java/src/org/openqa/selenium/devtools/events/CdpEventTypes.java index f69f8a79bd2d6b..88a797ce392b39 100644 --- a/java/src/org/openqa/selenium/devtools/events/CdpEventTypes.java +++ b/java/src/org/openqa/selenium/devtools/events/CdpEventTypes.java @@ -105,9 +105,13 @@ public void initializeListener(WebDriver driver) { Map values = JSON.toType(json, MAP_TYPE); String id = (String) values.get("target"); - List elements = - driver.findElements( - By.cssSelector(String.format("*[data-__webdriver_id='%s']", id))); + List elements; + + synchronized (this) { + elements = + driver.findElements( + By.cssSelector(String.format("*[data-__webdriver_id='%s']", id))); + } if (!elements.isEmpty()) { DomMutationEvent event = diff --git a/java/src/org/openqa/selenium/devtools/v118/BUILD.bazel b/java/src/org/openqa/selenium/devtools/v121/BUILD.bazel similarity index 98% rename from java/src/org/openqa/selenium/devtools/v118/BUILD.bazel rename to java/src/org/openqa/selenium/devtools/v121/BUILD.bazel index 98f55addb160bb..8e93a15944fb45 100644 --- a/java/src/org/openqa/selenium/devtools/v118/BUILD.bazel +++ b/java/src/org/openqa/selenium/devtools/v121/BUILD.bazel @@ -2,7 +2,7 @@ load("//common:defs.bzl", "copy_file") load("//java:defs.bzl", "java_export", "java_library") load("//java:version.bzl", "SE_VERSION") -cdp_version = "v118" +cdp_version = "v121" java_export( name = cdp_version, diff --git a/java/src/org/openqa/selenium/devtools/v118/v118CdpInfo.java b/java/src/org/openqa/selenium/devtools/v121/v121CdpInfo.java similarity index 86% rename from java/src/org/openqa/selenium/devtools/v118/v118CdpInfo.java rename to java/src/org/openqa/selenium/devtools/v121/v121CdpInfo.java index 5266ef6626e21f..f33326d67c591d 100644 --- a/java/src/org/openqa/selenium/devtools/v118/v118CdpInfo.java +++ b/java/src/org/openqa/selenium/devtools/v121/v121CdpInfo.java @@ -15,15 +15,15 @@ // specific language governing permissions and limitations // under the License. -package org.openqa.selenium.devtools.v118; +package org.openqa.selenium.devtools.v121; import com.google.auto.service.AutoService; import org.openqa.selenium.devtools.CdpInfo; @AutoService(CdpInfo.class) -public class v118CdpInfo extends CdpInfo { +public class v121CdpInfo extends CdpInfo { - public v118CdpInfo() { - super(118, v118Domains::new); + public v121CdpInfo() { + super(121, v121Domains::new); } } diff --git a/java/src/org/openqa/selenium/devtools/v118/v118Domains.java b/java/src/org/openqa/selenium/devtools/v121/v121Domains.java similarity index 77% rename from java/src/org/openqa/selenium/devtools/v118/v118Domains.java rename to java/src/org/openqa/selenium/devtools/v121/v121Domains.java index 0985ae1ce9860c..7975902fb5fcc6 100644 --- a/java/src/org/openqa/selenium/devtools/v118/v118Domains.java +++ b/java/src/org/openqa/selenium/devtools/v121/v121Domains.java @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -package org.openqa.selenium.devtools.v118; +package org.openqa.selenium.devtools.v121; import org.openqa.selenium.devtools.DevTools; import org.openqa.selenium.devtools.idealized.Domains; @@ -26,21 +26,21 @@ import org.openqa.selenium.devtools.idealized.target.Target; import org.openqa.selenium.internal.Require; -public class v118Domains implements Domains { +public class v121Domains implements Domains { - private final v118Javascript js; - private final v118Events events; - private final v118Log log; - private final v118Network network; - private final v118Target target; + private final v121Javascript js; + private final v121Events events; + private final v121Log log; + private final v121Network network; + private final v121Target target; - public v118Domains(DevTools devtools) { + public v121Domains(DevTools devtools) { Require.nonNull("DevTools", devtools); - events = new v118Events(devtools); - js = new v118Javascript(devtools); - log = new v118Log(); - network = new v118Network(devtools); - target = new v118Target(); + events = new v121Events(devtools); + js = new v121Javascript(devtools); + log = new v121Log(); + network = new v121Network(devtools); + target = new v121Target(); } @Override diff --git a/java/src/org/openqa/selenium/devtools/v118/v118Events.java b/java/src/org/openqa/selenium/devtools/v121/v121Events.java similarity index 86% rename from java/src/org/openqa/selenium/devtools/v118/v118Events.java rename to java/src/org/openqa/selenium/devtools/v121/v121Events.java index 0dde35dc7023c3..0148e8f42a52c7 100644 --- a/java/src/org/openqa/selenium/devtools/v118/v118Events.java +++ b/java/src/org/openqa/selenium/devtools/v121/v121Events.java @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -package org.openqa.selenium.devtools.v118; +package org.openqa.selenium.devtools.v121; import java.time.Instant; import java.util.List; @@ -28,15 +28,15 @@ import org.openqa.selenium.devtools.events.ConsoleEvent; import org.openqa.selenium.devtools.idealized.Events; import org.openqa.selenium.devtools.idealized.runtime.model.RemoteObject; -import org.openqa.selenium.devtools.v118.runtime.Runtime; -import org.openqa.selenium.devtools.v118.runtime.model.ConsoleAPICalled; -import org.openqa.selenium.devtools.v118.runtime.model.ExceptionDetails; -import org.openqa.selenium.devtools.v118.runtime.model.ExceptionThrown; -import org.openqa.selenium.devtools.v118.runtime.model.StackTrace; +import org.openqa.selenium.devtools.v121.runtime.Runtime; +import org.openqa.selenium.devtools.v121.runtime.model.ConsoleAPICalled; +import org.openqa.selenium.devtools.v121.runtime.model.ExceptionDetails; +import org.openqa.selenium.devtools.v121.runtime.model.ExceptionThrown; +import org.openqa.selenium.devtools.v121.runtime.model.StackTrace; -public class v118Events extends Events { +public class v121Events extends Events { - public v118Events(DevTools devtools) { + public v121Events(DevTools devtools) { super(devtools); } @@ -77,7 +77,7 @@ protected ConsoleEvent toConsoleEvent(ConsoleAPICalled event) { protected JavascriptException toJsException(ExceptionThrown event) { ExceptionDetails details = event.getExceptionDetails(); Optional maybeTrace = details.getStackTrace(); - Optional maybeException = + Optional maybeException = details.getException(); String message = diff --git a/java/src/org/openqa/selenium/devtools/v118/v118Javascript.java b/java/src/org/openqa/selenium/devtools/v121/v121Javascript.java similarity index 85% rename from java/src/org/openqa/selenium/devtools/v118/v118Javascript.java rename to java/src/org/openqa/selenium/devtools/v121/v121Javascript.java index 987e170321645b..f6fe984321300b 100644 --- a/java/src/org/openqa/selenium/devtools/v118/v118Javascript.java +++ b/java/src/org/openqa/selenium/devtools/v121/v121Javascript.java @@ -15,21 +15,21 @@ // specific language governing permissions and limitations // under the License. -package org.openqa.selenium.devtools.v118; +package org.openqa.selenium.devtools.v121; import java.util.Optional; import org.openqa.selenium.devtools.Command; import org.openqa.selenium.devtools.DevTools; import org.openqa.selenium.devtools.Event; import org.openqa.selenium.devtools.idealized.Javascript; -import org.openqa.selenium.devtools.v118.page.Page; -import org.openqa.selenium.devtools.v118.page.model.ScriptIdentifier; -import org.openqa.selenium.devtools.v118.runtime.Runtime; -import org.openqa.selenium.devtools.v118.runtime.model.BindingCalled; +import org.openqa.selenium.devtools.v121.page.Page; +import org.openqa.selenium.devtools.v121.page.model.ScriptIdentifier; +import org.openqa.selenium.devtools.v121.runtime.Runtime; +import org.openqa.selenium.devtools.v121.runtime.model.BindingCalled; -public class v118Javascript extends Javascript { +public class v121Javascript extends Javascript { - public v118Javascript(DevTools devtools) { + public v121Javascript(DevTools devtools) { super(devtools); } diff --git a/java/src/org/openqa/selenium/devtools/v118/v118Log.java b/java/src/org/openqa/selenium/devtools/v121/v121Log.java similarity index 89% rename from java/src/org/openqa/selenium/devtools/v118/v118Log.java rename to java/src/org/openqa/selenium/devtools/v121/v121Log.java index b7eb6a55e423f6..84528c17106372 100644 --- a/java/src/org/openqa/selenium/devtools/v118/v118Log.java +++ b/java/src/org/openqa/selenium/devtools/v121/v121Log.java @@ -15,19 +15,19 @@ // specific language governing permissions and limitations // under the License. -package org.openqa.selenium.devtools.v118; +package org.openqa.selenium.devtools.v121; import java.util.function.Function; import java.util.logging.Level; import org.openqa.selenium.devtools.Command; import org.openqa.selenium.devtools.ConverterFunctions; import org.openqa.selenium.devtools.Event; -import org.openqa.selenium.devtools.v118.log.Log; -import org.openqa.selenium.devtools.v118.log.model.LogEntry; -import org.openqa.selenium.devtools.v118.runtime.model.Timestamp; +import org.openqa.selenium.devtools.v121.log.Log; +import org.openqa.selenium.devtools.v121.log.model.LogEntry; +import org.openqa.selenium.devtools.v121.runtime.model.Timestamp; import org.openqa.selenium.json.JsonInput; -public class v118Log implements org.openqa.selenium.devtools.idealized.log.Log { +public class v121Log implements org.openqa.selenium.devtools.idealized.log.Log { @Override public Command enable() { diff --git a/java/src/org/openqa/selenium/devtools/v118/v118Network.java b/java/src/org/openqa/selenium/devtools/v121/v121Network.java similarity index 92% rename from java/src/org/openqa/selenium/devtools/v118/v118Network.java rename to java/src/org/openqa/selenium/devtools/v121/v121Network.java index 4eee5cdc79151a..0addc563c81202 100644 --- a/java/src/org/openqa/selenium/devtools/v118/v118Network.java +++ b/java/src/org/openqa/selenium/devtools/v121/v121Network.java @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -package org.openqa.selenium.devtools.v118; +package org.openqa.selenium.devtools.v121; import static java.net.HttpURLConnection.HTTP_OK; @@ -30,35 +30,35 @@ import org.openqa.selenium.devtools.DevToolsException; import org.openqa.selenium.devtools.Event; import org.openqa.selenium.devtools.idealized.Network; -import org.openqa.selenium.devtools.v118.fetch.Fetch; -import org.openqa.selenium.devtools.v118.fetch.model.*; -import org.openqa.selenium.devtools.v118.network.model.Request; +import org.openqa.selenium.devtools.v121.fetch.Fetch; +import org.openqa.selenium.devtools.v121.fetch.model.*; +import org.openqa.selenium.devtools.v121.network.model.Request; import org.openqa.selenium.internal.Either; import org.openqa.selenium.remote.http.HttpRequest; import org.openqa.selenium.remote.http.HttpResponse; -public class v118Network extends Network { +public class v121Network extends Network { - private static final Logger LOG = Logger.getLogger(v118Network.class.getName()); + private static final Logger LOG = Logger.getLogger(v121Network.class.getName()); - public v118Network(DevTools devTools) { + public v121Network(DevTools devTools) { super(devTools); } @Override protected Command setUserAgentOverride(UserAgent userAgent) { - return org.openqa.selenium.devtools.v118.network.Network.setUserAgentOverride( + return org.openqa.selenium.devtools.v121.network.Network.setUserAgentOverride( userAgent.userAgent(), userAgent.acceptLanguage(), userAgent.platform(), Optional.empty()); } @Override protected Command enableNetworkCaching() { - return org.openqa.selenium.devtools.v118.network.Network.setCacheDisabled(false); + return org.openqa.selenium.devtools.v121.network.Network.setCacheDisabled(false); } @Override protected Command disableNetworkCaching() { - return org.openqa.selenium.devtools.v118.network.Network.setCacheDisabled(true); + return org.openqa.selenium.devtools.v121.network.Network.setCacheDisabled(true); } @Override diff --git a/java/src/org/openqa/selenium/devtools/v118/v118Target.java b/java/src/org/openqa/selenium/devtools/v121/v121Target.java similarity index 83% rename from java/src/org/openqa/selenium/devtools/v118/v118Target.java rename to java/src/org/openqa/selenium/devtools/v121/v121Target.java index ce441bd32caf51..33528c10a21a57 100644 --- a/java/src/org/openqa/selenium/devtools/v118/v118Target.java +++ b/java/src/org/openqa/selenium/devtools/v121/v121Target.java @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -package org.openqa.selenium.devtools.v118; +package org.openqa.selenium.devtools.v121; import java.util.List; import java.util.Map; @@ -28,21 +28,21 @@ import org.openqa.selenium.devtools.idealized.browser.model.BrowserContextID; import org.openqa.selenium.devtools.idealized.target.model.SessionID; import org.openqa.selenium.devtools.idealized.target.model.TargetID; -import org.openqa.selenium.devtools.v118.target.Target; -import org.openqa.selenium.devtools.v118.target.model.TargetInfo; +import org.openqa.selenium.devtools.v121.target.Target; +import org.openqa.selenium.devtools.v121.target.model.TargetInfo; import org.openqa.selenium.json.JsonInput; import org.openqa.selenium.json.TypeToken; -public class v118Target implements org.openqa.selenium.devtools.idealized.target.Target { +public class v121Target implements org.openqa.selenium.devtools.idealized.target.Target { @Override public Command detachFromTarget( Optional sessionId, Optional targetId) { return Target.detachFromTarget( sessionId.map( - id -> new org.openqa.selenium.devtools.v118.target.model.SessionID(id.toString())), + id -> new org.openqa.selenium.devtools.v121.target.model.SessionID(id.toString())), targetId.map( - id -> new org.openqa.selenium.devtools.v118.target.model.TargetID(id.toString()))); + id -> new org.openqa.selenium.devtools.v121.target.model.TargetID(id.toString()))); } @Override @@ -74,19 +74,19 @@ public Command detachFromTarget( @Override public Command attachToTarget(TargetID targetId) { - Function mapper = + Function mapper = ConverterFunctions.map( - "sessionId", org.openqa.selenium.devtools.v118.target.model.SessionID.class); + "sessionId", org.openqa.selenium.devtools.v121.target.model.SessionID.class); return new Command<>( "Target.attachToTarget", Map.of( "targetId", - new org.openqa.selenium.devtools.v118.target.model.TargetID(targetId.toString()), + new org.openqa.selenium.devtools.v121.target.model.TargetID(targetId.toString()), "flatten", true), input -> { - org.openqa.selenium.devtools.v118.target.model.SessionID id = mapper.apply(input); + org.openqa.selenium.devtools.v121.target.model.SessionID id = mapper.apply(input); return new SessionID(id.toString()); }); } @@ -101,9 +101,9 @@ public Event detached() { return new Event<>( "Target.detachedFromTarget", input -> { - Function converter = + Function converter = ConverterFunctions.map( - "targetId", org.openqa.selenium.devtools.v118.target.model.TargetID.class); + "targetId", org.openqa.selenium.devtools.v121.target.model.TargetID.class); return new TargetID(converter.apply(input).toString()); }); } diff --git a/java/src/org/openqa/selenium/devtools/versions.bzl b/java/src/org/openqa/selenium/devtools/versions.bzl index ecb520a870372c..bbf0e350a1f3a3 100644 --- a/java/src/org/openqa/selenium/devtools/versions.bzl +++ b/java/src/org/openqa/selenium/devtools/versions.bzl @@ -2,7 +2,7 @@ CDP_VERSIONS = [ "v85", # Required by Firefox "v119", "v120", - "v118", + "v121", ] CDP_DEPS = ["//java/src/org/openqa/selenium/devtools/%s" % v for v in CDP_VERSIONS] diff --git a/java/src/org/openqa/selenium/grid/node/config/NodeFlags.java b/java/src/org/openqa/selenium/grid/node/config/NodeFlags.java index dedc561404001b..3d49df5f713b3d 100644 --- a/java/src/org/openqa/selenium/grid/node/config/NodeFlags.java +++ b/java/src/org/openqa/selenium/grid/node/config/NodeFlags.java @@ -151,9 +151,10 @@ public class NodeFlags implements HasRoles { + "file to improve readability. Command line example: " + "--driver-configuration display-name=\"Firefox Nightly\" max-sessions=2 " + "webdriver-path=\"/usr/local/bin/geckodriver\" " - + "stereotype='{\"browserName\": \"firefox\", \"browserVersion\": \"86\", " - + "\"moz:firefoxOptions\": " - + "{\"binary\":\"/Applications/Firefox Nightly.app/Contents/MacOS/firefox\"}}'", + + "stereotype=\"{\\\"browserName\\\": \\\"firefox\\\", " + + "\\\"browserVersion\\\": \\\"86\\\", " + + "\\\"moz:firefoxOptions\\\": " + + "{\\\"binary\":\"/Applications/Firefox Nightly.app/Contents/MacOS/firefox\\\"}}\"", arity = 4, variableArity = true, splitter = NonSplittingSplitter.class) diff --git a/java/src/org/openqa/selenium/grid/node/config/NodeOptions.java b/java/src/org/openqa/selenium/grid/node/config/NodeOptions.java index 972e8b790db1f0..8f7ea2dd68aaab 100644 --- a/java/src/org/openqa/selenium/grid/node/config/NodeOptions.java +++ b/java/src/org/openqa/selenium/grid/node/config/NodeOptions.java @@ -370,6 +370,10 @@ private void addDriverConfigs( .ifPresent( drivers -> { List> configList = new ArrayList<>(); + if (drivers.isEmpty()) { + // This is the case when the configuration is provided through the CLI. + config.getAll(NODE_SECTION, "driver-configuration").ifPresent(drivers::add); + } // iterate over driver configurations for (List driver : drivers) { diff --git a/java/src/org/openqa/selenium/grid/security/SecretOptions.java b/java/src/org/openqa/selenium/grid/security/SecretOptions.java index 35c57458f353d1..ee72015b969f8d 100644 --- a/java/src/org/openqa/selenium/grid/security/SecretOptions.java +++ b/java/src/org/openqa/selenium/grid/security/SecretOptions.java @@ -41,8 +41,7 @@ public SecretOptions(Config config) { public Secret getRegistrationSecret() { String secret = ""; - if ((isSecure() || isSelfSigned()) - && !config.get(SERVER_SECTION, "registration-secret").isPresent()) { + if ((isSecure()) && !config.get(SERVER_SECTION, "registration-secret").isPresent()) { try { secret = getEncoder() diff --git a/java/src/org/openqa/selenium/logging/LogType.java b/java/src/org/openqa/selenium/logging/LogType.java index e48ff46ae3739d..67c9c1488b61d9 100644 --- a/java/src/org/openqa/selenium/logging/LogType.java +++ b/java/src/org/openqa/selenium/logging/LogType.java @@ -32,7 +32,7 @@ public class LogType { /** This log type pertains to logs relating to performance timings. */ public static final String PERFORMANCE = "performance"; - /** This log type pertains to logs relating to performance timings. */ + /** This log type pertains to logs relating to profiler timings. */ public static final String PROFILER = "profiler"; /** This log type pertains to logs from the remote server. */ diff --git a/java/src/org/openqa/selenium/remote/ErrorCodes.java b/java/src/org/openqa/selenium/remote/ErrorCodes.java index 619bac07f0ef66..a32b7588566125 100644 --- a/java/src/org/openqa/selenium/remote/ErrorCodes.java +++ b/java/src/org/openqa/selenium/remote/ErrorCodes.java @@ -173,7 +173,7 @@ public class ErrorCodes { 405, UnsupportedCommandException.class, false, - true), + false), new KnownError( METHOD_NOT_ALLOWED, "unsupported operation", diff --git a/java/src/org/openqa/selenium/remote/ErrorHandler.java b/java/src/org/openqa/selenium/remote/ErrorHandler.java index 689af8e81c81e6..59a52ddb389cae 100644 --- a/java/src/org/openqa/selenium/remote/ErrorHandler.java +++ b/java/src/org/openqa/selenium/remote/ErrorHandler.java @@ -17,8 +17,6 @@ package org.openqa.selenium.remote; -import static org.openqa.selenium.remote.ErrorCodes.SUCCESS; - import java.lang.reflect.Constructor; import java.math.BigDecimal; import java.math.RoundingMode; @@ -82,7 +80,7 @@ public void setIncludeServerErrors(boolean includeServerErrors) { @SuppressWarnings("unchecked") public Response throwIfResponseFailed(Response response, long duration) throws RuntimeException { - if (response.getStatus() == null || response.getStatus() == SUCCESS) { + if ("success".equals(response.getState())) { return response; } diff --git a/java/src/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodec.java b/java/src/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodec.java index a666e7a17282f4..c525b0c350f1a4 100644 --- a/java/src/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodec.java +++ b/java/src/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodec.java @@ -90,10 +90,12 @@ public Response decode(HttpResponse encodedResponse) { if (!encodedResponse.isSuccessful()) { LOG.fine("Processing an error"); if (HTTP_BAD_METHOD == encodedResponse.getStatus()) { + response.setState("unknown command"); response.setStatus(ErrorCodes.UNKNOWN_COMMAND); response.setValue(content); } else if (HTTP_GATEWAY_TIMEOUT == encodedResponse.getStatus() || HTTP_BAD_GATEWAY == encodedResponse.getStatus()) { + response.setState("unknown error"); response.setStatus(ErrorCodes.UNHANDLED_ERROR); response.setValue(content); } else { diff --git a/java/src/org/openqa/selenium/support/events/EventFiringDecorator.java b/java/src/org/openqa/selenium/support/events/EventFiringDecorator.java index c1846bb260643a..0eeb60f17e7f0a 100644 --- a/java/src/org/openqa/selenium/support/events/EventFiringDecorator.java +++ b/java/src/org/openqa/selenium/support/events/EventFiringDecorator.java @@ -230,6 +230,9 @@ private void fireBeforeEvents( listener.beforeAnyOptionsCall((WebDriver.Options) target.getOriginal(), method, args); } else if (target.getOriginal() instanceof WebDriver.Timeouts) { listener.beforeAnyTimeoutsCall((WebDriver.Timeouts) target.getOriginal(), method, args); + } else if (target.getOriginal() instanceof WebDriver.TargetLocator) { + listener.beforeAnyTargetLocatorCall( + (WebDriver.TargetLocator) target.getOriginal(), method, args); } else if (target.getOriginal() instanceof WebDriver.Window) { listener.beforeAnyWindowCall((WebDriver.Window) target.getOriginal(), method, args); } @@ -287,6 +290,9 @@ private void fireAfterEvents( listener.afterAnyOptionsCall((WebDriver.Options) target.getOriginal(), method, args, res); } else if (target.getOriginal() instanceof WebDriver.Timeouts) { listener.afterAnyTimeoutsCall((WebDriver.Timeouts) target.getOriginal(), method, args, res); + } else if (target.getOriginal() instanceof WebDriver.TargetLocator) { + listener.afterAnyTargetLocatorCall( + (WebDriver.TargetLocator) target.getOriginal(), method, args, res); } else if (target.getOriginal() instanceof WebDriver.Window) { listener.afterAnyWindowCall((WebDriver.Window) target.getOriginal(), method, args, res); } diff --git a/java/src/org/openqa/selenium/support/events/WebDriverListener.java b/java/src/org/openqa/selenium/support/events/WebDriverListener.java index b55ae99e5d5d2d..4aae76df3c77ac 100644 --- a/java/src/org/openqa/selenium/support/events/WebDriverListener.java +++ b/java/src/org/openqa/selenium/support/events/WebDriverListener.java @@ -34,6 +34,7 @@ import org.openqa.selenium.ScriptKey; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.WindowType; import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.interactions.Sequence; import org.openqa.selenium.remote.RemoteWebDriver; @@ -1058,4 +1059,48 @@ default void beforeFullscreen(WebDriver.Window window) {} * @param window The window object that will be called */ default void afterFullscreen(WebDriver.Window window) {} + + // Target Locator + + /** + * Called before any method in {@link WebDriver.TargetLocator} class. + * + * @param targetLocator the target locator being used for the action + * @param method the method being invoked + * @param args the arguments to the method + */ + default void beforeAnyTargetLocatorCall( + WebDriver.TargetLocator targetLocator, Method method, Object[] args) {} + + /** + * Called after any method in {@link WebDriver.TargetLocator} class. + * + * @param targetLocator the target locator being used for the action + * @param method the method being invoked + * @param args the arguments to the method + * @param result the result of the method call + */ + default void afterAnyTargetLocatorCall( + WebDriver.TargetLocator targetLocator, Method method, Object[] args, Object result) {} + + /** + * This action will be performed each time before {@link + * org.openqa.selenium.WebDriver.TargetLocator#window(String)} + * + * @param targetLocator the target locator being used for the action + * @param nameOrHandle The name of the window or the handle as returned by {@link + * org.openqa.selenium.WebDriver#getWindowHandle()} or null if switching to a new + * window created by {@link org.openqa.selenium.WebDriver.TargetLocator#newWindow(WindowType)} + */ + default void beforeWindow(WebDriver.TargetLocator targetLocator, String nameOrHandle) {} + + /** + * @param targetLocator the target locator being used for the action + * @param nameOrHandle The name of the window or the handle as returned by {@link + * org.openqa.selenium.WebDriver#getWindowHandle()} or null if switching to a new + * window created by {@link org.openqa.selenium.WebDriver.TargetLocator#newWindow(WindowType)} + * @param driver WebDriver + */ + default void afterWindow( + WebDriver.TargetLocator targetLocator, String nameOrHandle, WebDriver driver) {} } diff --git a/java/test/org/openqa/selenium/bidi/browsingcontext/BrowsingContextInspectorTest.java b/java/test/org/openqa/selenium/bidi/browsingcontext/BrowsingContextInspectorTest.java index f9c42018998c40..9f1e77b2cd5ce9 100644 --- a/java/test/org/openqa/selenium/bidi/browsingcontext/BrowsingContextInspectorTest.java +++ b/java/test/org/openqa/selenium/bidi/browsingcontext/BrowsingContextInspectorTest.java @@ -73,6 +73,31 @@ void canListenToWindowBrowsingContextCreatedEvent() } } + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(CHROME) + @NotYetImplemented(EDGE) + void canListenToBrowsingContextDestroyedEvent() + throws ExecutionException, InterruptedException, TimeoutException { + try (BrowsingContextInspector inspector = new BrowsingContextInspector(driver)) { + CompletableFuture future = new CompletableFuture<>(); + + inspector.onBrowsingContextDestroyed(future::complete); + + String windowHandle = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); + + driver.close(); + + BrowsingContextInfo browsingContextInfo = future.get(5, TimeUnit.SECONDS); + + assertThat(browsingContextInfo.getId()).isEqualTo(windowHandle); + assertThat("about:blank").isEqualTo(browsingContextInfo.getUrl()); + assertThat(browsingContextInfo.getChildren()).isEqualTo(null); + assertThat(browsingContextInfo.getParentBrowsingContext()).isEqualTo(null); + } + } + @Test @NotYetImplemented(SAFARI) @NotYetImplemented(IE) diff --git a/java/test/org/openqa/selenium/bidi/input/DefaultKeyboardTest.java b/java/test/org/openqa/selenium/bidi/input/DefaultKeyboardTest.java index 3386769b3f24c9..648af977be7261 100644 --- a/java/test/org/openqa/selenium/bidi/input/DefaultKeyboardTest.java +++ b/java/test/org/openqa/selenium/bidi/input/DefaultKeyboardTest.java @@ -21,7 +21,6 @@ import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.openqa.selenium.testing.TestUtilities.getEffectivePlatform; import static org.openqa.selenium.testing.drivers.Browser.EDGE; -import static org.openqa.selenium.testing.drivers.Browser.FIREFOX; import static org.openqa.selenium.testing.drivers.Browser.IE; import static org.openqa.selenium.testing.drivers.Browser.SAFARI; @@ -222,9 +221,6 @@ void canGenerateKeyboardShortcuts() { @NotYetImplemented(SAFARI) @NotYetImplemented(IE) @NotYetImplemented(EDGE) - @NotYetImplemented( - value = FIREFOX, - reason = "https://bugzilla.mozilla.org/show_bug.cgi?id=1422583") public void testSelectionSelectBySymbol() { driver.get(appServer.whereIs("single_text_input.html")); @@ -254,9 +250,6 @@ public void testSelectionSelectBySymbol() { @NotYetImplemented(IE) @NotYetImplemented(EDGE) @Ignore(IE) - @NotYetImplemented( - value = FIREFOX, - reason = "https://bugzilla.mozilla.org/show_bug.cgi?id=1422583") public void testSelectionSelectByWord() { assumeFalse(getEffectivePlatform(driver).is(Platform.MAC), "MacOS has alternative keyboard"); diff --git a/java/test/org/openqa/selenium/bidi/network/AddInterceptParametersTest.java b/java/test/org/openqa/selenium/bidi/network/AddInterceptParametersTest.java new file mode 100644 index 00000000000000..9174699d84d901 --- /dev/null +++ b/java/test/org/openqa/selenium/bidi/network/AddInterceptParametersTest.java @@ -0,0 +1,168 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.bidi.network; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.openqa.selenium.testing.Safely.safelyCall; +import static org.openqa.selenium.testing.drivers.Browser.EDGE; +import static org.openqa.selenium.testing.drivers.Browser.FIREFOX; +import static org.openqa.selenium.testing.drivers.Browser.IE; +import static org.openqa.selenium.testing.drivers.Browser.SAFARI; + +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.bidi.Network; +import org.openqa.selenium.environment.webserver.AppServer; +import org.openqa.selenium.environment.webserver.NettyAppServer; +import org.openqa.selenium.testing.JupiterTestBase; +import org.openqa.selenium.testing.NotYetImplemented; + +class AddInterceptParametersTest extends JupiterTestBase { + + private AppServer server; + + @BeforeEach + public void setUp() { + server = new NettyAppServer(); + server.start(); + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canAddInterceptPhase() { + try (Network network = new Network(driver)) { + String intercept = + network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT)); + assertThat(intercept).isNotNull(); + } + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canAddInterceptPhases() { + try (Network network = new Network(driver)) { + String intercept = + network.addIntercept( + new AddInterceptParameters( + List.of(InterceptPhase.BEFORE_REQUEST_SENT, InterceptPhase.RESPONSE_STARTED))); + assertThat(intercept).isNotNull(); + } + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canAddStringUrlPattern() { + try (Network network = new Network(driver)) { + String intercept = + network.addIntercept( + new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT) + .urlStringPattern("http://localhost:4444/basicAuth")); + assertThat(intercept).isNotNull(); + } + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canAddStringUrlPatterns() { + try (Network network = new Network(driver)) { + String intercept = + network.addIntercept( + new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT) + .urlStringPatterns( + List.of( + "http://localhost:4444/basicAuth", + "http://localhost:4445/logEntryAdded"))); + assertThat(intercept).isNotNull(); + } + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canAddUrlPattern() { + try (Network network = new Network(driver)) { + UrlPattern pattern = + new UrlPattern() + .hostname("localhost") + .pathname("/logEntryAdded") + .port("4444") + .protocol("http") + .search(""); + + String intercept = + network.addIntercept( + new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT).urlPattern(pattern)); + assertThat(intercept).isNotNull(); + } + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canAddUrlPatterns() { + try (Network network = new Network(driver)) { + UrlPattern pattern1 = + new UrlPattern() + .hostname("localhost") + .pathname("/logEntryAdded") + .port("4444") + .protocol("http") + .search(""); + + UrlPattern pattern2 = + new UrlPattern() + .hostname("localhost") + .pathname("/basicAuth") + .port("4445") + .protocol("https") + .search("auth"); + + String intercept = + network.addIntercept( + new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT) + .urlPatterns(List.of(pattern1, pattern2))); + assertThat(intercept).isNotNull(); + } + } + + @AfterEach + public void quitDriver() { + if (driver != null) { + driver.quit(); + } + safelyCall(server::stop); + } +} diff --git a/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java b/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java new file mode 100644 index 00000000000000..681b2b1c4fd790 --- /dev/null +++ b/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java @@ -0,0 +1,166 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.bidi.network; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.openqa.selenium.testing.Safely.safelyCall; +import static org.openqa.selenium.testing.drivers.Browser.EDGE; +import static org.openqa.selenium.testing.drivers.Browser.FIREFOX; +import static org.openqa.selenium.testing.drivers.Browser.IE; +import static org.openqa.selenium.testing.drivers.Browser.SAFARI; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.Alert; +import org.openqa.selenium.By; +import org.openqa.selenium.TimeoutException; +import org.openqa.selenium.UsernameAndPassword; +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.bidi.Network; +import org.openqa.selenium.environment.webserver.AppServer; +import org.openqa.selenium.environment.webserver.NettyAppServer; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.testing.JupiterTestBase; +import org.openqa.selenium.testing.NotYetImplemented; + +class NetworkCommandsTest extends JupiterTestBase { + private String page; + private AppServer server; + + @BeforeEach + public void setUp() { + server = new NettyAppServer(); + server.start(); + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canAddIntercept() { + try (Network network = new Network(driver)) { + String intercept = + network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT)); + assertThat(intercept).isNotNull(); + } + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canRemoveIntercept() { + try (Network network = new Network(driver)) { + String intercept = + network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT)); + assertThat(intercept).isNotNull(); + + network.removeIntercept(intercept); + } + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canContinueWithAuthCredentials() { + try (Network network = new Network(driver)) { + network.addIntercept(new AddInterceptParameters(InterceptPhase.AUTH_REQUIRED)); + network.onAuthRequired( + responseDetails -> + network.continueWithAuth( + responseDetails.getRequest().getRequestId(), + new UsernameAndPassword("test", "test"))); + + page = server.whereIs("basicAuth"); + driver.get(page); + assertThat(driver.findElement(By.tagName("h1")).getText()).isEqualTo("authorized"); + } + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canContinueWithoutAuthCredentials() { + try (Network network = new Network(driver)) { + network.addIntercept(new AddInterceptParameters(InterceptPhase.AUTH_REQUIRED)); + network.onAuthRequired( + responseDetails -> + // Does not handle the alert + network.continueWithAuthNoCredentials(responseDetails.getRequest().getRequestId())); + page = server.whereIs("basicAuth"); + driver.get(page); + // This would fail if alert was handled + Alert alert = wait.until(ExpectedConditions.alertIsPresent()); + alert.dismiss(); + } + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canCancelAuth() { + try (Network network = new Network(driver)) { + network.addIntercept(new AddInterceptParameters(InterceptPhase.AUTH_REQUIRED)); + network.onAuthRequired( + responseDetails -> + // Does not handle the alert + network.cancelAuth(responseDetails.getRequest().getRequestId())); + page = server.whereIs("basicAuth"); + driver.get(page); + assertThatThrownBy(() -> wait.until(ExpectedConditions.alertIsPresent())) + .isInstanceOf(TimeoutException.class); + } + } + + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canFailRequest() { + try (Network network = new Network(driver)) { + network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT)); + network.onBeforeRequestSent( + responseDetails -> network.failRequest(responseDetails.getRequest().getRequestId())); + page = server.whereIs("basicAuth"); + driver.manage().timeouts().pageLoadTimeout(Duration.of(5, ChronoUnit.SECONDS)); + + assertThatThrownBy(() -> driver.get(page)).isInstanceOf(WebDriverException.class); + } + } + + @AfterEach + public void quitDriver() { + if (driver != null) { + driver.quit(); + } + safelyCall(server::stop); + } +} diff --git a/java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java b/java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java index 6f45915d4b2995..9c87b75b804944 100644 --- a/java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java +++ b/java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java @@ -20,7 +20,6 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.openqa.selenium.testing.Safely.safelyCall; import static org.openqa.selenium.testing.drivers.Browser.EDGE; -import static org.openqa.selenium.testing.drivers.Browser.FIREFOX; import static org.openqa.selenium.testing.drivers.Browser.IE; import static org.openqa.selenium.testing.drivers.Browser.SAFARI; @@ -148,7 +147,6 @@ void canListenToResponseCompletedEventWithCookie() @NotYetImplemented(SAFARI) @NotYetImplemented(IE) @NotYetImplemented(EDGE) - @NotYetImplemented(FIREFOX) // Implemented in Firefox Nightly version 123 void canListenToOnAuthRequiredEvent() throws ExecutionException, InterruptedException, TimeoutException { try (Network network = new Network(driver)) { diff --git a/java/test/org/openqa/selenium/remote/AugmenterTest.java b/java/test/org/openqa/selenium/remote/AugmenterTest.java index 8674dd73c446ae..55d4e12648267f 100644 --- a/java/test/org/openqa/selenium/remote/AugmenterTest.java +++ b/java/test/org/openqa/selenium/remote/AugmenterTest.java @@ -308,6 +308,7 @@ protected StubExecutor(Capabilities capabilities) { public Response execute(Command command) { if (DriverCommand.NEW_SESSION.equals(command.getName())) { Response response = new Response(new SessionId("foo")); + response.setState("success"); response.setValue(capabilities.asMap()); return response; } @@ -316,6 +317,7 @@ public Response execute(Command command) { if (possibleMatch.commandName.equals(command.getName()) && possibleMatch.args.equals(command.getParameters())) { Response response = new Response(new SessionId("foo")); + response.setState("success"); response.setValue(possibleMatch.returnValue); return response; } diff --git a/java/test/org/openqa/selenium/remote/ErrorHandlerTest.java b/java/test/org/openqa/selenium/remote/ErrorHandlerTest.java index e30eb205b0cf46..c4e9e18ba1db8d 100644 --- a/java/test/org/openqa/selenium/remote/ErrorHandlerTest.java +++ b/java/test/org/openqa/selenium/remote/ErrorHandlerTest.java @@ -480,6 +480,7 @@ private Response createResponse(int status) { private Response createResponse(int status, Object value) { Response response = new Response(); response.setStatus(status); + response.setState(new ErrorCodes().toState(status)); response.setValue(value); return response; } diff --git a/java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java b/java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java index 2465151342e28b..111cac68e5085f 100644 --- a/java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java +++ b/java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java @@ -167,6 +167,7 @@ void canHandleUnknownPlatformNameAndFallsBackToUnix() { void canHandleNonStandardCapabilitiesReturnedByRemoteEnd() throws IOException { Response resp = new Response(); resp.setSessionId(UUID.randomUUID().toString()); + resp.setState("success"); resp.setValue(ImmutableMap.of("platformName", "xxx")); CommandExecutor executor = mock(CommandExecutor.class); when(executor.execute(any())).thenReturn(resp); diff --git a/java/test/org/openqa/selenium/remote/WebDriverFixture.java b/java/test/org/openqa/selenium/remote/WebDriverFixture.java index 3ccb00b0727344..0bf3c4721b088b 100644 --- a/java/test/org/openqa/selenium/remote/WebDriverFixture.java +++ b/java/test/org/openqa/selenium/remote/WebDriverFixture.java @@ -156,6 +156,7 @@ private boolean areEqual(Object left, Object right) { public static Function valueResponder(Object value) { return cmd -> { Response response = new Response(); + response.setState("success"); response.setValue(value); response.setSessionId(cmd.getSessionId() != null ? cmd.getSessionId().toString() : null); return response; @@ -181,6 +182,7 @@ public static Function errorResponder(String state, Object va Collection capabilities = (Collection) cmd.getParameters().get("capabilities"); + response.setState("success"); response.setValue( capabilities.iterator().next().asMap().entrySet().stream() .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toString()))); diff --git a/java/test/org/openqa/selenium/support/events/EventFiringDecoratorTest.java b/java/test/org/openqa/selenium/support/events/EventFiringDecoratorTest.java index 1c1d9a9b477e17..95edd2a732ae9f 100644 --- a/java/test/org/openqa/selenium/support/events/EventFiringDecoratorTest.java +++ b/java/test/org/openqa/selenium/support/events/EventFiringDecoratorTest.java @@ -778,6 +778,58 @@ public void afterExecuteAsyncScript( "afterAnyCall executeAsyncScript")); } + @Test + void shouldFireTargetLocatorEvents() { + WebDriver driver = mock(WebDriver.class); + WebDriver.TargetLocator targetLocator = mock(WebDriver.TargetLocator.class); + when(driver.switchTo()).thenReturn(targetLocator); + + CollectorListener listener = + new CollectorListener() { + @Override + public void beforeAnyTargetLocatorCall( + WebDriver.TargetLocator targetLocator, Method method, Object[] args) { + acc.append("beforeAnyTargetLocatorCall ").append(method.getName()).append("\n"); + } + + @Override + public void afterAnyTargetLocatorCall( + WebDriver.TargetLocator targetLocator, Method method, Object[] args, Object result) { + acc.append("afterAnyTargetLocatorCall ").append(method.getName()).append("\n"); + } + + @Override + public void beforeWindow(WebDriver.TargetLocator targetLocator, String windowName) { + acc.append("beforeWindow ").append(windowName).append("\n"); + } + + @Override + public void afterWindow( + WebDriver.TargetLocator targetLocator, String windowName, WebDriver driver) { + acc.append("afterWindow ").append(windowName).append("\n"); + } + }; + + WebDriver decorated = new EventFiringDecorator<>(listener).decorate(driver); + + decorated.switchTo().window("windowName"); + + assertThat(listener.acc.toString().trim()) + .isEqualTo( + String.join( + "\n", + "beforeAnyCall switchTo", + "beforeAnyWebDriverCall switchTo", + "afterAnyWebDriverCall switchTo", + "afterAnyCall switchTo", + "beforeAnyCall window", + "beforeAnyTargetLocatorCall window", + "beforeWindow windowName", + "afterWindow windowName", + "afterAnyTargetLocatorCall window", + "afterAnyCall window")); + } + @Test void shouldSuppressExceptionInBeforeAnyCall() { WebDriver driver = mock(WebDriver.class); diff --git a/java/test/org/openqa/selenium/support/ui/WebDriverWaitTest.java b/java/test/org/openqa/selenium/support/ui/WebDriverWaitTest.java index 3cb976e38ba35b..50d396b0497029 100644 --- a/java/test/org/openqa/selenium/support/ui/WebDriverWaitTest.java +++ b/java/test/org/openqa/selenium/support/ui/WebDriverWaitTest.java @@ -62,6 +62,7 @@ public void createMocks() { void shouldIncludeRemoteInfoForWrappedDriverTimeout() throws IOException { Capabilities caps = new MutableCapabilities(); Response response = new Response(new SessionId("foo")); + response.setState("success"); response.setValue(caps.asMap()); CommandExecutor executor = mock(CommandExecutor.class); when(executor.execute(any(Command.class))).thenReturn(response); diff --git a/java/version.bzl b/java/version.bzl index aa18ce770a6f61..579d06445b01ed 100644 --- a/java/version.bzl +++ b/java/version.bzl @@ -1,2 +1,2 @@ -SE_VERSION = "4.17.0-SNAPSHOT" +SE_VERSION = "4.18.0-SNAPSHOT" TOOLS_JAVA_VERSION = "17" diff --git a/javascript/atoms/dom.js b/javascript/atoms/dom.js index ecc6ac4b85144c..30aa362dbe8130 100644 --- a/javascript/atoms/dom.js +++ b/javascript/atoms/dom.js @@ -1325,7 +1325,9 @@ bot.dom.appendVisibleTextLinesFromNodeInComposedDom_ = function( } else { shadowChildren = contentElem.assignedNodes(); } - goog.array.forEach(shadowChildren, function(node) { + const childrenToTraverse = + shadowChildren.length > 0 ? shadowChildren : contentElem.childNodes; + goog.array.forEach(childrenToTraverse, function (node) { bot.dom.appendVisibleTextLinesFromNodeInComposedDom_( node, lines, shown, whitespace, textTransform); }); diff --git a/javascript/atoms/test/text_shadow_test.html b/javascript/atoms/test/text_shadow_test.html index fbb292bc6e19ae..388ba9306a037e 100644 --- a/javascript/atoms/test/text_shadow_test.html +++ b/javascript/atoms/test/text_shadow_test.html @@ -71,7 +71,31 @@ let customEl = findElement({ tagName: 'open-shadow-element' }); let text = getText(customEl); - assertEquals(text, 'full link text'); + assertEquals('full link text', text); + } + + function testTextForSlotValueInShadowDOM() { + setCustomElement('full'); + + let customEl = findElement({ id: 'custom-text' }); + let text = getText(customEl); + assertEquals('custom', text); + } + + function testTextForSlotAndExtraValueInShadowDOM() { + setCustomElement('full text'); + + let customEl = findElement({ id: 'custom-text' }); + let text = getText(customEl); + assertEquals('custom text', text); + } + + function testTextForDefaultSlotValueInShadowDOM() { + setCustomElement('full text'); + + let customEl = findElement({ tagName: 'open-shadow-element' }); + let text = getText(customEl); + assertEquals('full text', text); } function testHiddenTextInShadowDOM() { @@ -81,7 +105,7 @@ let customEl = findElement({ tagName: 'open-shadow-element' }); let text = getText(customEl); - assertEquals(text, 'full text'); + assertEquals('full text', text); } function testTextForElementWithinClosedShadowDOM() { @@ -89,13 +113,14 @@ let customEl = findElement({ tagName: 'closed-shadow-element' }); let innerEl = findElement({ css: 'a' }, customEl._shadowRoot); let text = getText(innerEl); - assertEquals(text, 'full link text'); + assertEquals('full link text', text); } + custom diff --git a/javascript/node/selenium-webdriver/BUILD.bazel b/javascript/node/selenium-webdriver/BUILD.bazel index 3b9514fb08b724..53c8ffe5a36f4b 100644 --- a/javascript/node/selenium-webdriver/BUILD.bazel +++ b/javascript/node/selenium-webdriver/BUILD.bazel @@ -6,7 +6,7 @@ BROWSER_VERSIONS = [ "v85", "v119", "v120", - "v118", + "v121", ] SRC_FILES = [ diff --git a/javascript/node/selenium-webdriver/CHANGES.md b/javascript/node/selenium-webdriver/CHANGES.md index f342a3c0c44e8a..1a29c8a37a7c54 100644 --- a/javascript/node/selenium-webdriver/CHANGES.md +++ b/javascript/node/selenium-webdriver/CHANGES.md @@ -1,3 +1,20 @@ +## 4.17.0 + +* Add javascript to Selenium Manager input for tracking (see #13288) +* remove deprecated headless methods and associated references +* Add script message event (#13153) +* Update channel name from Aurora to Dev +* Remove firefox_channels.js example as Channels is deprecated +* Add Input module command (#13360) +* remove all references to firefox-bin +* download files from remote server (#13102) +* Add auth required event +* Add traverse history command +* Add test to get iframe's browsing context +* Add Input module JS command +* Add test for node properties in +* Add CDP for Chrome 121 and remove 118 + ## 4.16.0 #### :bug: Bug fix diff --git a/javascript/node/selenium-webdriver/bidi/browsingContextInspector.js b/javascript/node/selenium-webdriver/bidi/browsingContextInspector.js index 1504cf0ac1f01a..3bdd286ec83ada 100644 --- a/javascript/node/selenium-webdriver/bidi/browsingContextInspector.js +++ b/javascript/node/selenium-webdriver/bidi/browsingContextInspector.js @@ -37,6 +37,13 @@ class BrowsingContextInspector { ) } + async onBrowsingContextDestroyed(callback) { + await this.subscribeAndHandleEvent( + 'browsingContext.contextDestroyed', + callback + ) + } + async onNavigationStarted(callback) { await this.subscribeAndHandleEvent( 'browsingContext.navigationStarted', diff --git a/javascript/node/selenium-webdriver/bidi/scriptManager.js b/javascript/node/selenium-webdriver/bidi/scriptManager.js index 0aca9d8f942209..f02aedc62628e6 100644 --- a/javascript/node/selenium-webdriver/bidi/scriptManager.js +++ b/javascript/node/selenium-webdriver/bidi/scriptManager.js @@ -359,6 +359,10 @@ class ScriptManager { await this.subscribeAndHandleEvent('script.realmCreated', callback) } + async onRealmDestroyed(callback) { + await this.subscribeAndHandleEvent('script.realmDestroyed', callback) + } + async subscribeAndHandleEvent(eventType, callback) { if (this._browsingContextIds != null) { await this.bidi.subscribe(eventType, this._browsingContextIds) diff --git a/javascript/node/selenium-webdriver/chromium.js b/javascript/node/selenium-webdriver/chromium.js index 403a06e41e103b..5225d0b1cf5ca9 100644 --- a/javascript/node/selenium-webdriver/chromium.js +++ b/javascript/node/selenium-webdriver/chromium.js @@ -835,9 +835,8 @@ class Driver extends webdriver.WebDriver { * containing the friendly device names of available cast sink targets. */ getCastSinks() { - return this.schedule( - new command.Command(Command.GET_CAST_SINKS), - 'Driver.getCastSinks()' + return this.execute( + new command.Command(Command.GET_CAST_SINKS) ) } @@ -849,12 +848,11 @@ class Driver extends webdriver.WebDriver { * when the target device has been selected to respond further webdriver commands. */ setCastSinkToUse(deviceName) { - return this.schedule( + return this.execute( new command.Command(Command.SET_CAST_SINK_TO_USE).setParameter( 'sinkName', deviceName - ), - 'Driver.setCastSinkToUse(' + deviceName + ')' + ) ) } @@ -866,12 +864,11 @@ class Driver extends webdriver.WebDriver { * when the mirror command has been issued to the device. */ startDesktopMirroring(deviceName) { - return this.schedule( + return this.execute( new command.Command(Command.START_CAST_DESKTOP_MIRRORING).setParameter( 'sinkName', deviceName - ), - 'Driver.startDesktopMirroring(' + deviceName + ')' + ) ) } @@ -883,12 +880,11 @@ class Driver extends webdriver.WebDriver { * when the mirror command has been issued to the device. */ startCastTabMirroring(deviceName) { - return this.schedule( + return this.execute( new command.Command(Command.START_CAST_TAB_MIRRORING).setParameter( 'sinkName', deviceName - ), - 'Driver.startCastTabMirroring(' + deviceName + ')' + ) ) } @@ -898,9 +894,8 @@ class Driver extends webdriver.WebDriver { * when the mirror command has been issued to the device. */ getCastIssueMessage() { - return this.schedule( - new command.Command(Command.GET_CAST_ISSUE_MESSAGE), - 'Driver.getCastIssueMessage()' + return this.execute( + new command.Command(Command.GET_CAST_ISSUE_MESSAGE) ) } @@ -912,12 +907,11 @@ class Driver extends webdriver.WebDriver { * when the stop command has been issued to the device. */ stopCasting(deviceName) { - return this.schedule( + return this.execute( new command.Command(Command.STOP_CASTING).setParameter( 'sinkName', deviceName - ), - 'Driver.stopCasting(' + deviceName + ')' + ) ) } } diff --git a/javascript/node/selenium-webdriver/package-lock.json b/javascript/node/selenium-webdriver/package-lock.json index 20617d3e1f3aed..dc503a74f3bf5f 100644 --- a/javascript/node/selenium-webdriver/package-lock.json +++ b/javascript/node/selenium-webdriver/package-lock.json @@ -1,12 +1,12 @@ { "name": "selenium-webdriver", - "version": "4.16.0", + "version": "4.17.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "selenium-webdriver", - "version": "4.16.0", + "version": "4.17.0", "license": "Apache-2.0", "dependencies": { "jszip": "^3.10.1", diff --git a/javascript/node/selenium-webdriver/package.json b/javascript/node/selenium-webdriver/package.json index a50f78f2c42081..72eabdc9af0800 100644 --- a/javascript/node/selenium-webdriver/package.json +++ b/javascript/node/selenium-webdriver/package.json @@ -1,6 +1,6 @@ { "name": "selenium-webdriver", - "version": "4.16.0", + "version": "4.17.0", "description": "The official WebDriver JavaScript bindings from the Selenium project", "license": "Apache-2.0", "keywords": [ diff --git a/javascript/node/selenium-webdriver/test/bidi/browsingcontext_inspector_test.js b/javascript/node/selenium-webdriver/test/bidi/browsingcontext_inspector_test.js index 7222872f171ec3..dcc4219f6a49d6 100644 --- a/javascript/node/selenium-webdriver/test/bidi/browsingcontext_inspector_test.js +++ b/javascript/node/selenium-webdriver/test/bidi/browsingcontext_inspector_test.js @@ -56,6 +56,24 @@ suite( assert.equal(contextInfo.parentBrowsingContext, null) }) + it('can listen to browsing context destroyed event', async function () { + let contextInfo = null + const browsingcontextInspector = await BrowsingContextInspector(driver) + await browsingcontextInspector.onBrowsingContextDestroyed((entry) => { + contextInfo = entry + }) + + await driver.switchTo().newWindow('window') + + const windowHandle = await driver.getWindowHandle() + await driver.close() + + assert.equal(contextInfo.id, windowHandle) + assert.equal(contextInfo.url, 'about:blank') + assert.equal(contextInfo.children, null) + assert.equal(contextInfo.parentBrowsingContext, null) + }) + it('can listen to tab browsing context created event', async function () { let contextInfo = null const browsingcontextInspector = await BrowsingContextInspector(driver) diff --git a/javascript/node/selenium-webdriver/test/bidi/network_test.js b/javascript/node/selenium-webdriver/test/bidi/network_test.js index a91437d066b4b4..01acc2c5cdd269 100644 --- a/javascript/node/selenium-webdriver/test/bidi/network_test.js +++ b/javascript/node/selenium-webdriver/test/bidi/network_test.js @@ -186,6 +186,25 @@ suite( assert.equal(onResponseCompleted[0].redirectCount, 0) }) + xit('can listen to auth required event', async function () { + let authRequiredEvent = null + const inspector = await NetworkInspector(driver) + await inspector.authRequired(function (event) { + authRequiredEvent = event + }) + + await driver.get(Pages.basicAuth) + + const url = authRequiredEvent.request.url + assert.equal(authRequiredEvent.id, await driver.getWindowHandle()) + assert.equal(authRequiredEvent.request.method, 'GET') + assert.equal(url.includes('basicAuth'), true) + + assert.equal(authRequiredEvent.response.status, 401) + assert.equal(authRequiredEvent.response.headers.length > 1, true) + assert.equal(authRequiredEvent.response.url.includes('basicAuth'), true) + }) + it('test response completed mime type', async function () { let onResponseCompleted = [] const inspector = await NetworkInspector(driver) diff --git a/javascript/node/selenium-webdriver/test/bidi/script_test.js b/javascript/node/selenium-webdriver/test/bidi/script_test.js index f1e67173d79cf9..3749c215b5e9dd 100644 --- a/javascript/node/selenium-webdriver/test/bidi/script_test.js +++ b/javascript/node/selenium-webdriver/test/bidi/script_test.js @@ -1006,6 +1006,27 @@ suite( assert.notEqual(realmInfo.realmId, null) assert.equal(realmInfo.realmType, RealmType.WINDOW) }) + + xit('can listen to realm destroyed message', async function () { + const manager = await ScriptManager(undefined, driver) + + let realmInfo = null + + await manager.onRealmDestroyed((result) => { + realmInfo = result + }) + + const id = await driver.getWindowHandle() + const browsingContext = await BrowsingContext(driver, { + browsingContextId: id, + }) + + await browsingContext.close() + + assert.notEqual(realmInfo, null) + assert.notEqual(realmInfo.realmId, null) + assert.equal(realmInfo.realmType, RealmType.WINDOW) + }) }) }, {browsers: [Browser.FIREFOX]} diff --git a/javascript/node/selenium-webdriver/test/chrome/cast_test.js b/javascript/node/selenium-webdriver/test/chrome/cast_test.js new file mode 100644 index 00000000000000..02251d0fdb3085 --- /dev/null +++ b/javascript/node/selenium-webdriver/test/chrome/cast_test.js @@ -0,0 +1,49 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +'use strict' + +const assert = require('assert') +const chrome = require('../../chrome') +const test = require('../../lib/test') +const { ignore } = require('../../lib/test') +const { Browser } = require('../../index') + +test.suite( + function (env) { + let driver + + beforeEach(async function () { + driver = await env + .builder() + .build() + }) + afterEach(async () => await driver.quit()) + describe('can cast to devices', () => { + it( + 'get sinks returns a list of devices', + async function () { + + // Just testing if we can set get cast sink command. + // Testing this is tough because we need a device to cast to for the test. + const castSinks = await driver.getCastSinks() + } + ) + }) + }, + { browsers: ['chrome'] } +) diff --git a/javascript/node/selenium-webdriver/test/virtualAuthenticator_test.js b/javascript/node/selenium-webdriver/test/virtualAuthenticator_test.js index d599132d8f95d6..5dd607c04e6f44 100644 --- a/javascript/node/selenium-webdriver/test/virtualAuthenticator_test.js +++ b/javascript/node/selenium-webdriver/test/virtualAuthenticator_test.js @@ -35,7 +35,7 @@ const GET_CREDENTIAL = `getCredential([{ "id": Int8Array.from(arguments[0]), }]).then(arguments[arguments.length - 1]);` -async function createRkEnabledU2fAuthenticator(driver) { +async function createRkEnabledU2fAuthenticator (driver) { let options options = new virtualAuthenticatorOptions() options.setProtocol(Protocol['U2F']) @@ -44,7 +44,7 @@ async function createRkEnabledU2fAuthenticator(driver) { return driver } -async function createRkDisabledU2fAuthenticator(driver) { +async function createRkDisabledU2fAuthenticator (driver) { let options options = new virtualAuthenticatorOptions() options.setProtocol(Protocol['U2F']) @@ -53,7 +53,7 @@ async function createRkDisabledU2fAuthenticator(driver) { return driver } -async function createRkEnabledCTAP2Authenticator(driver) { +async function createRkEnabledCTAP2Authenticator (driver) { let options options = new virtualAuthenticatorOptions() options.setProtocol(Protocol['CTAP2']) @@ -64,7 +64,7 @@ async function createRkEnabledCTAP2Authenticator(driver) { return driver } -async function createRkDisabledCTAP2Authenticator(driver) { +async function createRkDisabledCTAP2Authenticator (driver) { let options options = new virtualAuthenticatorOptions() options.setProtocol(Protocol['CTAP2']) @@ -75,15 +75,15 @@ async function createRkDisabledCTAP2Authenticator(driver) { return driver } -async function getAssertionFor(driver, credentialId) { +async function getAssertionFor (driver, credentialId) { return await driver.executeAsyncScript(GET_CREDENTIAL, credentialId) } -function extractRawIdFrom(response) { +function extractRawIdFrom (response) { return response.credential.rawId } -function extractIdFrom(response) { +function extractIdFrom (response) { return response.credential.id } @@ -96,7 +96,7 @@ function extractIdFrom(response) { * @param array2 Second array to be checked for equality * @returns true if equal, otherwise false. */ -function arraysEqual(array1, array2) { +function arraysEqual (array1, array2) { return ( array1.length == array2.length && array1.every((item) => array2.includes(item)) && @@ -150,7 +150,7 @@ suite(function (env) { }) describe('VirtualAuthenticator Test Suit 2', function () { - ignore(browsers(Browser.SAFARI, Browser.FIREFOX)).it( + ignore(browsers(Browser.SAFARI)).it( 'should test create authenticator', async function () { /** @@ -170,7 +170,7 @@ suite(function (env) { } ) - ignore(browsers(Browser.SAFARI, Browser.FIREFOX)).it( + ignore(browsers(Browser.SAFARI)).it( 'should test remove authenticator', async function () { let options = new virtualAuthenticatorOptions() @@ -321,8 +321,9 @@ suite(function (env) { * Register a resident credential. */ let response1 = await driver.executeAsyncScript( - 'registerCredential({authenticatorSelection: {requireResidentKey: true}})' + - ' .then(arguments[arguments.length - 1]);' + 'registerCredential({authenticatorSelection: {requireResidentKey: true}})' + + + ' .then(arguments[arguments.length - 1]);' ) assert(response1['status'] === 'OK') @@ -442,12 +443,12 @@ suite(function (env) { */ let response = await driver.executeAsyncScript( 'getCredential([{' + - ' "type": "public-key",' + - ' "id": Int8Array.from(arguments[0]),' + - '}, {' + - ' "type": "public-key",' + - ' "id": Int8Array.from(arguments[1]),' + - '}]).then(arguments[arguments.length - 1]);', + ' "type": "public-key",' + + ' "id": Int8Array.from(arguments[0]),' + + '}, {' + + ' "type": "public-key",' + + ' "id": Int8Array.from(arguments[1]),' + + '}]).then(arguments[arguments.length - 1]);', rawId1, rawId2 ) @@ -464,8 +465,9 @@ suite(function (env) { * Register a credential requiring UV. */ let response = await driver.executeAsyncScript( - "registerCredential({authenticatorSelection: {userVerification: 'required'}})" + - ' .then(arguments[arguments.length - 1]);' + 'registerCredential({authenticatorSelection: {userVerification: \'required\'}})' + + + ' .then(arguments[arguments.length - 1]);' ) assert(response['status'] === 'OK') let rawId = extractRawIdFrom(response) diff --git a/py/BUILD.bazel b/py/BUILD.bazel index be60118206e8d7..986fbc747149a2 100644 --- a/py/BUILD.bazel +++ b/py/BUILD.bazel @@ -10,6 +10,22 @@ load("//py:defs.bzl", "generate_devtools", "py_test_suite") load("//py/private:browsers.bzl", "BROWSERS") load("//py/private:import.bzl", "py_import") +alias( + name = "twine", + actual = requirement("twine"), +) + +genrule( + name = "selenium-release", + srcs = [ + ":selenium-wheel", + ":selenium-sdist", + ], + outs = ["pypi_upload_complete.txt"], + cmd = "(twine upload $(location :selenium-wheel) $(location :selenium-sdist) && touch $@)", + tools = [":twine"], +) + compile_pip_requirements( # base name for generated targets, typically "requirements" name = "requirements", @@ -20,13 +36,13 @@ compile_pip_requirements( ], ) -SE_VERSION = "4.16.0" +SE_VERSION = "4.17.2" BROWSER_VERSIONS = [ "v85", "v119", "v120", - "v118", + "v121", ] TEST_DEPS = [ @@ -154,6 +170,7 @@ py_library( imports = ["."], visibility = ["//visibility:public"], deps = [ + requirement("typing_extensions"), requirement("trio"), requirement("trio_websocket"), requirement("urllib3"), @@ -241,6 +258,7 @@ py_wheel( "trio~=0.17", "trio-websocket~=0.9", "certifi>=2021.10.8", + "typing_extensions>=4.9.0", ], strip_path_prefixes = [ "py/", @@ -560,7 +578,7 @@ py_test_suite( ]), args = [ "--instafail", - "--driver=WPEWebKit", + "--driver=wpewebkit", "--browser-binary=MiniBrowser", "--browser-args=--automation --headless", ], diff --git a/py/CHANGES b/py/CHANGES index 96f6774659ef9a..edb05c297e29ab 100644 --- a/py/CHANGES +++ b/py/CHANGES @@ -1,3 +1,31 @@ +Selenium 4.17.2 +* py] Correct typing_extension dependency for wheel generation + +Selenium 4.17.1 +* Fix typo in setup.py (#13487) + +Selenium 4.17.0 +* Add page load strategy enum (#13258) +* Use correct file name when bumping versions (#13282) +* Filter which bidi logs are recorded based on event type (#12951) +* Add python to Selenium Manager input for tracking (see #13288) +* Sleep depending on the number of attempts to check if the service has started (#13321) +* Use subprocess.DEVNULL instead of open(os.devnull) to avoid leaking a file handle (#13329) +* Remove all references to firefox-bin +* Check if architecture/platform combination is supported for Selenium Manager (#13381) +* Remove extension connection class and other usages of webdriver.xpi +* remove deprecated verbose argument from edge service +* remove deprecated desired_capabilities property from webdriver +* remove deprecated application cache support +* truncate large strings when logging requests +* Update WPEWebKit support code (#13278) +* [py] Fix WPEWebKit python support code +* Do not change profile preferences of an existing directory by default (#13477) +* Deprecate firefox profile methods that are not supported (#13477) +* deprecate FirefoxBinary class (#13476) +* Fix type error in mypy (#13482) +* Add CDP for Chrome 121 and remove 118 + Selenium 4.16.0 * Fix inadvertent code change in mutation_event * Fix bug in using SE_MANAGER_PATH diff --git a/py/conftest.py b/py/conftest.py index 0443b11e110308..562325b561a919 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -148,7 +148,8 @@ def fin(): options = get_options(driver_class, request.config) if driver_class == "Edge": options = get_options(driver_class, request.config) - if driver_class == "WPEWebKit": + if driver_class.lower() == "wpewebkit": + driver_class = "WPEWebKit" options = get_options(driver_class, request.config) if driver_path is not None: kwargs["service"] = get_service(driver_class, driver_path) diff --git a/py/docs/requirements.txt b/py/docs/requirements.txt index 8c3fe5b3995c54..9bf9a82104a489 100644 --- a/py/docs/requirements.txt +++ b/py/docs/requirements.txt @@ -1,2 +1,2 @@ -Jinja2==3.1.2 +Jinja2==3.1.3 Sphinx==1.8.2 diff --git a/py/docs/source/conf.py b/py/docs/source/conf.py index 936b95db407f6a..43517b5beedab4 100644 --- a/py/docs/source/conf.py +++ b/py/docs/source/conf.py @@ -56,9 +56,9 @@ # built documents. # # The short X.Y version. -version = '4.15' +version = '4.17' # The full version, including alpha/beta/rc tags. -release = '4.16.0' +release = '4.17.2' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/py/requirements.txt b/py/requirements.txt index 05889cb7bf3643..a3715e9bb9b777 100644 --- a/py/requirements.txt +++ b/py/requirements.txt @@ -2,7 +2,7 @@ async-generator==1.10 attrs==23.1.0 certifi==2023.7.22 cffi==1.16.0 -cryptography==41.0.3 +cryptography==41.0.4 dataclasses==0.6 debugpy==1.8.0 h11==0.14.0 @@ -24,11 +24,13 @@ pytest==7.4.2 pytest-instafail==0.5.0 pytest-mock==3.12.0 pytest-trio==0.8.0 -sniffio==1.2.0 +sniffio==1.3.0 sortedcontainers==2.4.0 toml==0.10.2 -trio>=0.20.0 +trio>=0.20.2 trio-websocket==0.9.2 +twine==4.0.2 +typing_extensions==4.9.0 urllib3[socks]==2.0.7 wsproto==1.2.0 zipp==3.17.0 diff --git a/py/requirements_lock.txt b/py/requirements_lock.txt index 47ef407676e7e2..b7742aeb127d2e 100644 --- a/py/requirements_lock.txt +++ b/py/requirements_lock.txt @@ -17,12 +17,13 @@ attrs==23.1.0 \ # via # -r py/requirements.txt # outcome - # pytest # trio certifi==2023.7.22 \ --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ --hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9 - # via -r py/requirements.txt + # via + # -r py/requirements.txt + # requests cffi==1.16.0 \ --hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \ --hash=sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a \ @@ -79,30 +80,122 @@ cffi==1.16.0 \ # via # -r py/requirements.txt # cryptography -cryptography==41.0.3 \ - --hash=sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306 \ - --hash=sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84 \ - --hash=sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47 \ - --hash=sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d \ - --hash=sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116 \ - --hash=sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207 \ - --hash=sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81 \ - --hash=sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087 \ - --hash=sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd \ - --hash=sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507 \ - --hash=sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858 \ - --hash=sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae \ - --hash=sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34 \ - --hash=sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906 \ - --hash=sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd \ - --hash=sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922 \ - --hash=sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7 \ - --hash=sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4 \ - --hash=sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574 \ - --hash=sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1 \ - --hash=sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c \ - --hash=sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e \ - --hash=sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de +charset-normalizer==3.3.2 \ + --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ + --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ + --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \ + --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \ + --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \ + --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \ + --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \ + --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \ + --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \ + --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \ + --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \ + --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \ + --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \ + --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \ + --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \ + --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \ + --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \ + --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \ + --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \ + --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \ + --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \ + --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \ + --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \ + --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \ + --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \ + --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \ + --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \ + --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \ + --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \ + --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \ + --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \ + --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \ + --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \ + --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \ + --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \ + --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \ + --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \ + --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \ + --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \ + --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \ + --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \ + --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \ + --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \ + --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \ + --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \ + --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \ + --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \ + --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \ + --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \ + --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \ + --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \ + --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \ + --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \ + --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \ + --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \ + --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \ + --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \ + --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \ + --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \ + --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \ + --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \ + --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \ + --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \ + --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \ + --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \ + --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \ + --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \ + --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \ + --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \ + --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \ + --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \ + --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \ + --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \ + --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \ + --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \ + --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \ + --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \ + --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \ + --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \ + --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \ + --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \ + --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \ + --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \ + --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \ + --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \ + --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \ + --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \ + --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \ + --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ + --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 + # via requests +cryptography==41.0.4 \ + --hash=sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67 \ + --hash=sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311 \ + --hash=sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8 \ + --hash=sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13 \ + --hash=sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143 \ + --hash=sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f \ + --hash=sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829 \ + --hash=sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd \ + --hash=sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397 \ + --hash=sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac \ + --hash=sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d \ + --hash=sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a \ + --hash=sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839 \ + --hash=sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e \ + --hash=sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6 \ + --hash=sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9 \ + --hash=sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860 \ + --hash=sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca \ + --hash=sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91 \ + --hash=sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d \ + --hash=sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714 \ + --hash=sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb \ + --hash=sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f # via # -r py/requirements.txt # pyopenssl @@ -130,6 +223,10 @@ debugpy==1.8.0 \ --hash=sha256:ef54404365fae8d45cf450d0544ee40cefbcb9cb85ea7afe89a963c27028261e \ --hash=sha256:ef9ab7df0b9a42ed9c878afd3eaaff471fce3fa73df96022e1f5c9f8f8c87ada # via -r py/requirements.txt +docutils==0.20.1 \ + --hash=sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6 \ + --hash=sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b + # via readme-renderer exceptiongroup==1.1.1 \ --hash=sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e \ --hash=sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785 @@ -147,11 +244,19 @@ idna==3.4 \ --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 # via # -r py/requirements.txt + # requests # trio importlib-metadata==6.8.0 \ --hash=sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb \ --hash=sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743 - # via -r py/requirements.txt + # via + # -r py/requirements.txt + # keyring + # twine +importlib-resources==6.1.1 \ + --hash=sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a \ + --hash=sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6 + # via keyring inflection==0.5.1 \ --hash=sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417 \ --hash=sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2 @@ -162,10 +267,28 @@ iniconfig==2.0.0 \ # via # -r py/requirements.txt # pytest +jaraco-classes==3.3.0 \ + --hash=sha256:10afa92b6743f25c0cf5f37c6bb6e18e2c5bb84a16527ccfc0040ea377e7aaeb \ + --hash=sha256:c063dd08e89217cee02c8d5e5ec560f2c8ce6cdc2fcdc2e68f7b2e5547ed3621 + # via keyring +keyring==24.3.0 \ + --hash=sha256:4446d35d636e6a10b8bce7caa66913dd9eca5fd222ca03a3d42c38608ac30836 \ + --hash=sha256:e730ecffd309658a08ee82535a3b5ec4b4c8669a9be11efb66249d8e0aeb9a25 + # via twine +markdown-it-py==3.0.0 \ + --hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \ + --hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb + # via rich +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py more-itertools==10.1.0 \ --hash=sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a \ --hash=sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6 - # via -r py/requirements.txt + # via + # -r py/requirements.txt + # jaraco-classes multidict==6.0.2 \ --hash=sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60 \ --hash=sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c \ @@ -227,6 +350,24 @@ multidict==6.0.2 \ --hash=sha256:feba80698173761cddd814fa22e88b0661e98cb810f9f986c54aa34d281e4937 \ --hash=sha256:feea820722e69451743a3d56ad74948b68bf456984d63c1a92e8347b7b88452d # via -r py/requirements.txt +nh3==0.2.15 \ + --hash=sha256:0d02d0ff79dfd8208ed25a39c12cbda092388fff7f1662466e27d97ad011b770 \ + --hash=sha256:3277481293b868b2715907310c7be0f1b9d10491d5adf9fce11756a97e97eddf \ + --hash=sha256:3b803a5875e7234907f7d64777dfde2b93db992376f3d6d7af7f3bc347deb305 \ + --hash=sha256:427fecbb1031db085eaac9931362adf4a796428ef0163070c484b5a768e71601 \ + --hash=sha256:5f0d77272ce6d34db6c87b4f894f037d55183d9518f948bba236fe81e2bb4e28 \ + --hash=sha256:60684857cfa8fdbb74daa867e5cad3f0c9789415aba660614fe16cd66cbb9ec7 \ + --hash=sha256:6f42f99f0cf6312e470b6c09e04da31f9abaadcd3eb591d7d1a88ea931dca7f3 \ + --hash=sha256:86e447a63ca0b16318deb62498db4f76fc60699ce0a1231262880b38b6cff911 \ + --hash=sha256:8d595df02413aa38586c24811237e95937ef18304e108b7e92c890a06793e3bf \ + --hash=sha256:9c0d415f6b7f2338f93035bba5c0d8c1b464e538bfbb1d598acd47d7969284f0 \ + --hash=sha256:a5167a6403d19c515217b6bcaaa9be420974a6ac30e0da9e84d4fc67a5d474c5 \ + --hash=sha256:ac19c0d68cd42ecd7ead91a3a032fdfff23d29302dbb1311e641a130dfefba97 \ + --hash=sha256:b1e97221cedaf15a54f5243f2c5894bb12ca951ae4ddfd02a9d4ea9df9e1a29d \ + --hash=sha256:bc2d086fb540d0fa52ce35afaded4ea526b8fc4d3339f783db55c95de40ef02e \ + --hash=sha256:d1e30ff2d8d58fb2a14961f7aac1bbb1c51f9bdd7da727be35c63826060b0bf3 \ + --hash=sha256:f3b53ba93bb7725acab1e030bc2ecd012a817040fd7851b332f86e2f9bb98dc6 + # via readme-renderer outcome==1.3.0 \ --hash=sha256:588ef4dc10b64e8df160d8d1310c44e1927129a66d6d2ef86845cef512c5f24c \ --hash=sha256:7b688fd82db72f4b0bc9e883a00359d4d4179cd97d27f09c9644d0c842ba7786 @@ -240,6 +381,10 @@ packaging==23.2 \ # via # -r py/requirements.txt # pytest +pkginfo==1.9.6 \ + --hash=sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546 \ + --hash=sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046 + # via twine pluggy==1.3.0 \ --hash=sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12 \ --hash=sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7 @@ -256,6 +401,12 @@ pycparser==2.21 \ # via # -r py/requirements.txt # cffi +pygments==2.17.2 \ + --hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \ + --hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367 + # via + # readme-renderer + # rich pyopenssl==22.0.0 \ --hash=sha256:660b1b1425aac4a1bea1d94168a85d99f0b3144c869dd4390d27629d0087f1bf \ --hash=sha256:ea252b38c87425b64116f808355e8da644ef9b07e429398bfece610f893ee2e0 @@ -263,9 +414,7 @@ pyopenssl==22.0.0 \ pyparsing==3.1.1 \ --hash=sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb \ --hash=sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db - # via - # -r py/requirements.txt - # packaging + # via -r py/requirements.txt pysocks==1.7.1 \ --hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \ --hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \ @@ -293,9 +442,31 @@ pytest-trio==0.8.0 \ --hash=sha256:8363db6336a79e6c53375a2123a41ddbeccc4aa93f93788651641789a56fb52e \ --hash=sha256:e6a7e7351ae3e8ec3f4564d30ee77d1ec66e1df611226e5618dbb32f9545c841 # via -r py/requirements.txt -sniffio==1.2.0 \ - --hash=sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663 \ - --hash=sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de +readme-renderer==42.0 \ + --hash=sha256:13d039515c1f24de668e2c93f2e877b9dbe6c6c32328b90a40a49d8b2b85f36d \ + --hash=sha256:2d55489f83be4992fe4454939d1a051c33edbab778e82761d060c9fc6b308cd1 + # via twine +requests==2.31.0 \ + --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ + --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 + # via + # requests-toolbelt + # twine +requests-toolbelt==1.0.0 \ + --hash=sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6 \ + --hash=sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06 + # via twine +rfc3986==2.0.0 \ + --hash=sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd \ + --hash=sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c + # via twine +rich==13.7.0 \ + --hash=sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa \ + --hash=sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235 + # via twine +sniffio==1.3.0 \ + --hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \ + --hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384 # via # -r py/requirements.txt # trio @@ -324,10 +495,23 @@ trio-websocket==0.9.2 \ --hash=sha256:5b558f6e83cc20a37c3b61202476c5295d1addf57bd65543364e0337e37ed2bc \ --hash=sha256:a3d34de8fac26023eee701ed1e7bf4da9a8326b61a62934ec9e53b64970fd8fe # via -r py/requirements.txt +twine==4.0.2 \ + --hash=sha256:929bc3c280033347a00f847236564d1c52a3e61b1ac2516c97c48f3ceab756d8 \ + --hash=sha256:9e102ef5fdd5a20661eb88fad46338806c3bd32cf1db729603fe3697b1bc83c8 + # via -r py/requirements.txt +typing-extensions==4.9.0 \ + --hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \ + --hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd + # via + # -r py/requirements.txt + # rich urllib3[socks]==2.0.7 \ --hash=sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84 \ --hash=sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e - # via -r py/requirements.txt + # via + # -r py/requirements.txt + # requests + # twine wsproto==1.2.0 \ --hash=sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065 \ --hash=sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736 @@ -340,3 +524,4 @@ zipp==3.17.0 \ # via # -r py/requirements.txt # importlib-metadata + # importlib-resources diff --git a/py/selenium/__init__.py b/py/selenium/__init__.py index 1a7cf3e7656325..46a5f545f76553 100644 --- a/py/selenium/__init__.py +++ b/py/selenium/__init__.py @@ -16,4 +16,4 @@ # under the License. -__version__ = "4.16.0" +__version__ = "4.17.2" diff --git a/py/selenium/webdriver/__init__.py b/py/selenium/webdriver/__init__.py index f4044c50c76752..711d8aa9ccbf30 100644 --- a/py/selenium/webdriver/__init__.py +++ b/py/selenium/webdriver/__init__.py @@ -44,7 +44,7 @@ from .wpewebkit.service import Service as WPEWebKitService # noqa from .wpewebkit.webdriver import WebDriver as WPEWebKit # noqa -__version__ = "4.16.0" +__version__ = "4.17.2" # We need an explicit __all__ because the above won't otherwise be exported. __all__ = [ diff --git a/py/selenium/webdriver/common/desired_capabilities.py b/py/selenium/webdriver/common/desired_capabilities.py index cd5fd21aa3f46d..1d78019165f9d8 100644 --- a/py/selenium/webdriver/common/desired_capabilities.py +++ b/py/selenium/webdriver/common/desired_capabilities.py @@ -93,12 +93,8 @@ class DesiredCapabilities: WEBKITGTK = { "browserName": "MiniBrowser", - "version": "", - "platform": "ANY", } WPEWEBKIT = { "browserName": "MiniBrowser", - "version": "", - "platform": "ANY", } diff --git a/py/selenium/webdriver/common/options.py b/py/selenium/webdriver/common/options.py index 5952aa7376095e..ea2bdde227e767 100644 --- a/py/selenium/webdriver/common/options.py +++ b/py/selenium/webdriver/common/options.py @@ -418,7 +418,7 @@ def arguments(self): """:Returns: A list of arguments needed for the browser.""" return self._arguments - def add_argument(self, argument): + def add_argument(self, argument) -> None: """Adds an argument to the list. :Args: diff --git a/py/selenium/webdriver/firefox/firefox_binary.py b/py/selenium/webdriver/firefox/firefox_binary.py index e9f060ce50aa8d..d4cea3368858e2 100644 --- a/py/selenium/webdriver/firefox/firefox_binary.py +++ b/py/selenium/webdriver/firefox/firefox_binary.py @@ -23,10 +23,13 @@ from subprocess import STDOUT from subprocess import Popen +from typing_extensions import deprecated + from selenium.common.exceptions import WebDriverException from selenium.webdriver.common import utils +@deprecated("Use binary_location property in Firefox Options to set location") class FirefoxBinary: NO_FOCUS_LIBRARY_NAME = "x_ignore_nofocus.so" diff --git a/py/selenium/webdriver/firefox/firefox_profile.py b/py/selenium/webdriver/firefox/firefox_profile.py index 8dac84e930f87e..14c80b577a9b55 100644 --- a/py/selenium/webdriver/firefox/firefox_profile.py +++ b/py/selenium/webdriver/firefox/firefox_profile.py @@ -28,18 +28,19 @@ from io import BytesIO from xml.dom import minidom +from typing_extensions import deprecated + from selenium.common.exceptions import WebDriverException WEBDRIVER_PREFERENCES = "webdriver_prefs.json" -EXTENSION_NAME = "fxdriver@googlecode.com" +@deprecated("Addons must be added after starting the session") class AddonFormatError(Exception): """Exception for not well-formed add-on manifest files.""" class FirefoxProfile: - ANONYMOUS_PROFILE_NAME = "WEBDRIVER_ANONYMOUS_PROFILE" DEFAULT_PREFERENCES = None def __init__(self, profile_directory=None): @@ -52,61 +53,60 @@ def __init__(self, profile_directory=None): This defaults to None and will create a new directory when object is created. """ - if not FirefoxProfile.DEFAULT_PREFERENCES: - with open( - os.path.join(os.path.dirname(__file__), WEBDRIVER_PREFERENCES), encoding="utf-8" - ) as default_prefs: - FirefoxProfile.DEFAULT_PREFERENCES = json.load(default_prefs) - - self.default_preferences = copy.deepcopy(FirefoxProfile.DEFAULT_PREFERENCES["mutable"]) - self.profile_dir = profile_directory - self.tempfolder = None - if not self.profile_dir: - self.profile_dir = self._create_tempfolder() - else: - self.tempfolder = tempfile.mkdtemp() - newprof = os.path.join(self.tempfolder, "webdriver-py-profilecopy") + self._desired_preferences = {} + if profile_directory: + newprof = os.path.join(tempfile.mkdtemp(), "webdriver-py-profilecopy") shutil.copytree( - self.profile_dir, newprof, ignore=shutil.ignore_patterns("parent.lock", "lock", ".parentlock") + profile_directory, newprof, ignore=shutil.ignore_patterns("parent.lock", "lock", ".parentlock") ) - self.profile_dir = newprof - os.chmod(self.profile_dir, 0o755) - self._read_existing_userjs(os.path.join(self.profile_dir, "user.js")) - self.extensionsDir = os.path.join(self.profile_dir, "extensions") - self.userPrefs = os.path.join(self.profile_dir, "user.js") - if os.path.isfile(self.userPrefs): - os.chmod(self.userPrefs, 0o644) + self._profile_dir = newprof + os.chmod(self._profile_dir, 0o755) + else: + self._profile_dir = tempfile.mkdtemp() + if not FirefoxProfile.DEFAULT_PREFERENCES: + with open( + os.path.join(os.path.dirname(__file__), WEBDRIVER_PREFERENCES), encoding="utf-8" + ) as default_prefs: + FirefoxProfile.DEFAULT_PREFERENCES = json.load(default_prefs) + + self._desired_preferences = copy.deepcopy(FirefoxProfile.DEFAULT_PREFERENCES["mutable"]) + for key, value in FirefoxProfile.DEFAULT_PREFERENCES["frozen"].items(): + self._desired_preferences[key] = value # Public Methods def set_preference(self, key, value): """Sets the preference that we want in the profile.""" - self.default_preferences[key] = value + self._desired_preferences[key] = value - def add_extension(self, extension): + @deprecated("Addons must be added after starting the session") + def add_extension(self, extension=None): self._install_extension(extension) def update_preferences(self): - for key, value in FirefoxProfile.DEFAULT_PREFERENCES["frozen"].items(): - # Do not update key that is being set by the user using - # set_preference as users are unaware of the freeze properties - # and it leads to an inconsistent behavior - if key not in self.default_preferences: - self.default_preferences[key] = value - self._write_user_prefs(self.default_preferences) + """Writes the desired user prefs to disk.""" + user_prefs = os.path.join(self._profile_dir, "user.js") + if os.path.isfile(user_prefs): + os.chmod(user_prefs, 0o644) + self._read_existing_userjs(user_prefs) + with open(user_prefs, "w", encoding="utf-8") as f: + for key, value in self._desired_preferences.items(): + f.write(f'user_pref("{key}", {json.dumps(value)});\n') # Properties @property def path(self): """Gets the profile directory that is currently being used.""" - return self.profile_dir + return self._profile_dir @property + @deprecated("The port is stored in the Service class") def port(self): """Gets the port that WebDriver is working on.""" return self._port @port.setter + @deprecated("The port is stored in the Service class") def port(self, port) -> None: """Sets the port that WebDriver will be running on.""" if not isinstance(port, int): @@ -121,20 +121,24 @@ def port(self, port) -> None: self.set_preference("webdriver_firefox_port", self._port) @property + @deprecated("Allowing untrusted certs is toggled in the Options class") def accept_untrusted_certs(self): - return self.default_preferences["webdriver_accept_untrusted_certs"] + return self._desired_preferences["webdriver_accept_untrusted_certs"] @accept_untrusted_certs.setter + @deprecated("Allowing untrusted certs is toggled in the Options class") def accept_untrusted_certs(self, value) -> None: if not isinstance(value, bool): raise WebDriverException("Please pass in a Boolean to this call") self.set_preference("webdriver_accept_untrusted_certs", value) @property + @deprecated("Allowing untrusted certs is toggled in the Options class") def assume_untrusted_cert_issuer(self): - return self.default_preferences["webdriver_assume_untrusted_issuer"] + return self._desired_preferences["webdriver_assume_untrusted_issuer"] @assume_untrusted_cert_issuer.setter + @deprecated("Allowing untrusted certs is toggled in the Options class") def assume_untrusted_cert_issuer(self, value) -> None: if not isinstance(value, bool): raise WebDriverException("Please pass in a Boolean to this call") @@ -143,9 +147,10 @@ def assume_untrusted_cert_issuer(self, value) -> None: @property def encoded(self) -> str: - """A zipped, base64 encoded string of profile directory for use with - remote WebDriver JSON wire protocol.""" - self.update_preferences() + """Updates preferences and creates a zipped, base64 encoded string of + profile directory.""" + if self._desired_preferences: + self.update_preferences() fp = BytesIO() with zipfile.ZipFile(fp, "w", zipfile.ZIP_DEFLATED) as zipped: path_root = len(self.path) + 1 # account for trailing slash @@ -155,32 +160,21 @@ def encoded(self) -> str: zipped.write(filename, filename[path_root:]) return base64.b64encode(fp.getvalue()).decode("UTF-8") - def _create_tempfolder(self): - """Creates a temp folder to store User.js and the extension.""" - return tempfile.mkdtemp() - - def _write_user_prefs(self, user_prefs): - """Writes the current user prefs dictionary to disk.""" - with open(self.userPrefs, "w", encoding="utf-8") as f: - for key, value in user_prefs.items(): - f.write(f'user_pref("{key}", {json.dumps(value)});\n') - def _read_existing_userjs(self, userjs): + """Reads existing preferences and adds them to desired preference + dictionary.""" pref_pattern = re.compile(r'user_pref\("(.*)",\s(.*)\)') - try: - with open(userjs, encoding="utf-8") as f: - for usr in f: - matches = pref_pattern.search(usr) - try: - self.default_preferences[matches.group(1)] = json.loads(matches.group(2)) - except Exception: - warnings.warn( - f"(skipping) failed to json.loads existing preference: {matches.group(1) + matches.group(2)}" - ) - except Exception: - # The profile given hasn't had any changes made, i.e no users.js - pass + with open(userjs, encoding="utf-8") as f: + for usr in f: + matches = pref_pattern.search(usr) + try: + self._desired_preferences[matches.group(1)] = json.loads(matches.group(2)) + except Exception: + warnings.warn( + f"(skipping) failed to json.loads existing preference: {matches.group(1) + matches.group(2)}" + ) + @deprecated("Addons must be added after starting the session") def _install_extension(self, addon, unpack=True): """Installs addon from a filepath, url or directory of addons in the profile. @@ -212,11 +206,12 @@ def _install_extension(self, addon, unpack=True): assert addon_id, f"The addon id could not be found: {addon}" # copy the addon to the profile - addon_path = os.path.join(self.extensionsDir, addon_id) + extensions_dir = os.path.join(self._profile_dir, "extensions") + addon_path = os.path.join(extensions_dir, addon_id) if not unpack and not addon_details["unpack"] and xpifile: - if not os.path.exists(self.extensionsDir): - os.makedirs(self.extensionsDir) - os.chmod(self.extensionsDir, 0o755) + if not os.path.exists(extensions_dir): + os.makedirs(extensions_dir) + os.chmod(extensions_dir, 0o755) shutil.copy(xpifile, addon_path + ".xpi") else: if not os.path.exists(addon_path): @@ -226,6 +221,7 @@ def _install_extension(self, addon, unpack=True): if tmpdir: shutil.rmtree(tmpdir) + @deprecated("Addons must be added after starting the session") def _addon_details(self, addon_path): """Returns a dictionary of details about the addon. diff --git a/py/selenium/webdriver/firefox/options.py b/py/selenium/webdriver/firefox/options.py index 8da25f81976d9e..1cb3a2bdd08a49 100644 --- a/py/selenium/webdriver/firefox/options.py +++ b/py/selenium/webdriver/firefox/options.py @@ -14,9 +14,10 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import typing from typing import Union +from typing_extensions import deprecated + from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.common.options import ArgOptions from selenium.webdriver.firefox.firefox_binary import FirefoxBinary @@ -38,35 +39,37 @@ class Options(ArgOptions): def __init__(self) -> None: super().__init__() - self._binary: typing.Optional[FirefoxBinary] = None + self._binary_location = "" self._preferences: dict = {} self._profile = None self.log = Log() @property + @deprecated("use binary_location instead") def binary(self) -> FirefoxBinary: """Returns the FirefoxBinary instance.""" - return self._binary + return FirefoxBinary(self._binary_location) @binary.setter + @deprecated("use binary_location instead") def binary(self, new_binary: Union[str, FirefoxBinary]) -> None: """Sets location of the browser binary, either by string or ``FirefoxBinary`` instance.""" - if not isinstance(new_binary, FirefoxBinary): - new_binary = FirefoxBinary(new_binary) - self._binary = new_binary + if isinstance(new_binary, FirefoxBinary): + new_binary = new_binary._start_cmd + self.binary_location = new_binary @property def binary_location(self) -> str: """:Returns: The location of the binary.""" - return self.binary._start_cmd + return self._binary_location @binary_location.setter # noqa def binary_location(self, value: str) -> None: """Sets the location of the browser binary by string.""" if not isinstance(value, str): raise TypeError(self.BINARY_LOCATION_ERROR) - self.binary = value + self._binary_location = value @property def preferences(self) -> dict: @@ -102,8 +105,8 @@ def to_capabilities(self) -> dict: caps = self._caps opts = {} - if self._binary: - opts["binary"] = self._binary._start_cmd + if self._binary_location: + opts["binary"] = self._binary_location if self._preferences: opts["prefs"] = self._preferences if self._profile: diff --git a/py/selenium/webdriver/remote/remote_connection.py b/py/selenium/webdriver/remote/remote_connection.py index 7cfd9eb4c466c3..eab43d4693a6c4 100644 --- a/py/selenium/webdriver/remote/remote_connection.py +++ b/py/selenium/webdriver/remote/remote_connection.py @@ -297,6 +297,8 @@ def execute(self, command, params): del params[word] data = utils.dump_json(params) url = f"{self._url}{path}" + trimmed = self._trim_large_entries(params) + LOGGER.debug("%s %s %s", command_info[0], url, str(trimmed)) return self._request(command_info[0], url, body=data) def _request(self, method, url, body=None): @@ -310,7 +312,6 @@ def _request(self, method, url, body=None): :Returns: A dictionary with the server's parsed JSON response. """ - LOGGER.debug("%s %s %s", method, url, body) parsed_url = parse.urlparse(url) headers = self.get_remote_connection_headers(parsed_url, self.keep_alive) response = None @@ -360,3 +361,21 @@ def close(self): """Clean up resources when finished with the remote_connection.""" if hasattr(self, "_conn"): self._conn.clear() + + def _trim_large_entries(self, input_dict, max_length=100): + """Truncate string values in a dictionary if they exceed max_length. + + :param dict: Dictionary with potentially large values + :param max_length: Maximum allowed length of string values + :return: Dictionary with truncated string values + """ + output_dictionary = {} + for key, value in input_dict.items(): + if isinstance(value, dict): + output_dictionary[key] = self._trim_large_entries(value, max_length) + elif isinstance(value, str) and len(value) > max_length: + output_dictionary[key] = value[:max_length] + "..." + else: + output_dictionary[key] = value + + return output_dictionary diff --git a/py/selenium/webdriver/wpewebkit/options.py b/py/selenium/webdriver/wpewebkit/options.py index 3b4f3d8680dc1d..e1bb66c162a392 100644 --- a/py/selenium/webdriver/wpewebkit/options.py +++ b/py/selenium/webdriver/wpewebkit/options.py @@ -14,6 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +import typing from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.common.options import ArgOptions @@ -25,7 +26,6 @@ class Options(ArgOptions): def __init__(self) -> None: super().__init__() self._binary_location = "" - self._caps = DesiredCapabilities.WPEWEBKIT.copy() @property def binary_location(self) -> str: @@ -58,3 +58,7 @@ def to_capabilities(self): caps[Options.KEY] = browser_options return caps + + @property + def default_capabilities(self) -> typing.Dict[str, str]: + return DesiredCapabilities.WPEWEBKIT.copy() diff --git a/py/selenium/webdriver/wpewebkit/service.py b/py/selenium/webdriver/wpewebkit/service.py index 38dca67144edc0..26e8747bae803a 100644 --- a/py/selenium/webdriver/wpewebkit/service.py +++ b/py/selenium/webdriver/wpewebkit/service.py @@ -14,21 +14,22 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +import shutil import typing from selenium.webdriver.common import service -DEFAULT_EXECUTABLE_PATH = "WPEWebDriver" +DEFAULT_EXECUTABLE_PATH = shutil.which("WPEWebDriver") class Service(service.Service): """A Service class that is responsible for the starting and stopping of `WPEWebDriver`. - :param executable_path: install path of the WPEWebDriver executable, defaults to `WPEWebDriver`. + :param executable_path: install path of the WPEWebDriver executable, defaults to the first `WPEWebDriver` in `$PATH`. :param port: Port for the service to run on, defaults to 0 where the operating system will decide. :param service_args: (Optional) List of args to be passed to the subprocess when launching the executable. - :param log_path: (Optional) File path for the file to be opened and passed as the subprocess stdout/stderr handler. + :param log_output: (Optional) File path for the file to be opened and passed as the subprocess stdout/stderr handler. :param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`. """ @@ -36,17 +37,16 @@ def __init__( self, executable_path: str = DEFAULT_EXECUTABLE_PATH, port: int = 0, - log_path: typing.Optional[str] = None, + log_output: typing.Optional[str] = None, service_args: typing.Optional[typing.List[str]] = None, env: typing.Optional[typing.Mapping[str, str]] = None, **kwargs, ): self.service_args = service_args or [] - log_file = open(log_path, "wb") if log_path else None super().__init__( executable_path=executable_path, port=port, - log_file=log_file, + log_output=log_output, env=env, **kwargs, ) # type: ignore diff --git a/py/selenium/webdriver/wpewebkit/webdriver.py b/py/selenium/webdriver/wpewebkit/webdriver.py index fe98ba6907c638..0e69489fb56891 100644 --- a/py/selenium/webdriver/wpewebkit/webdriver.py +++ b/py/selenium/webdriver/wpewebkit/webdriver.py @@ -17,12 +17,10 @@ import http.client as http_client -from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.common.driver_finder import DriverFinder from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from .options import Options -from .service import DEFAULT_EXECUTABLE_PATH from .service import Service @@ -31,35 +29,25 @@ class WebDriver(RemoteWebDriver): def __init__( self, - executable_path=DEFAULT_EXECUTABLE_PATH, - port=0, options=None, - desired_capabilities=DesiredCapabilities.WPEWEBKIT, - service_log_path=None, + service: Service = None, ): """Creates a new instance of the WPEWebKit driver. Starts the service and then creates new instance of WPEWebKit Driver. :Args: - - executable_path : path to the executable. If the default is used it assumes the executable is in the $PATH. - - port : port you would like the service to run, if left as 0, a free port will be found. - - options : an instance of WPEWebKitOptions - - desired_capabilities : Dictionary object with desired capabilities - - service_log_path : Path to write service stdout and stderr output. + - options : an instance of ``WPEWebKitOptions`` + - service : Service object for handling the browser driver if you need to pass extra details """ - if options: - capabilities = options.to_capabilities() - capabilities.update(desired_capabilities) - desired_capabilities = capabilities - else: + if not options: options = Options() - self.service = Service(executable_path, port=port, log_path=service_log_path) + self.service = service if service else Service() self.service.path = DriverFinder.get_path(self.service, options) self.service.start() - super().__init__(command_executor=self.service.service_url, desired_capabilities=desired_capabilities) + super().__init__(command_executor=self.service.service_url, options=options) self._is_remote = False def quit(self): diff --git a/py/setup.py b/py/setup.py index a2b0e49afb8cec..24ec88ad9f1343 100755 --- a/py/setup.py +++ b/py/setup.py @@ -27,7 +27,7 @@ setup_args = { 'cmdclass': {'install': install}, 'name': 'selenium', - 'version': "4.16.0", + 'version': "4.17.2", 'license': 'Apache 2.0', 'description': 'Python bindings for Selenium', 'long_description': open(join(abspath(dirname(__file__)), "README.rst")).read(), @@ -49,7 +49,10 @@ 'Topic :: Software Development :: Libraries', 'Programming Language :: Python', 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9'], + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12'], 'package_dir': { 'selenium': 'selenium', 'selenium.common': 'selenium/common', @@ -69,6 +72,7 @@ 'selenium.webdriver.support', ], 'include_package_data': True, 'install_requires': [ + "typing_extensions~= 4.9", "urllib3[socks]>=1.26,<3", "trio~=0.17", "trio-websocket~=0.9", diff --git a/py/test/unit/selenium/webdriver/firefox/firefox_options_tests.py b/py/test/unit/selenium/webdriver/firefox/firefox_options_tests.py index 9db5f7166fb5ce..a4a5ecbfbb09a4 100644 --- a/py/test/unit/selenium/webdriver/firefox/firefox_options_tests.py +++ b/py/test/unit/selenium/webdriver/firefox/firefox_options_tests.py @@ -34,12 +34,12 @@ def options(): def test_set_binary_with_firefox_binary(options): binary = FirefoxBinary("foo") options.binary = binary - assert options._binary == binary + assert options.binary_location == "foo" def test_set_binary_with_path(options): options.binary = "/foo" - assert options._binary._start_cmd == "/foo" + assert options.binary_location == "/foo" def test_get_binary(options): @@ -49,11 +49,11 @@ def test_get_binary(options): def test_set_binary_location(options): options.binary_location = "/foo" - assert options._binary._start_cmd == "/foo" + assert options.binary_location == "/foo" def test_get_binary_location(options): - options._binary = FirefoxBinary("/foo") + options._binary_location = "/foo" assert options.binary_location == "/foo" @@ -131,7 +131,7 @@ def test_set_log_level(options): def test_creates_capabilities(options): profile = FirefoxProfile() options._arguments = ["foo"] - options._binary = FirefoxBinary("/bar") + options._binary_location = "/bar" options._preferences = {"foo": "bar"} options.proxy = Proxy({"proxyType": ProxyType.MANUAL}) options._profile = profile @@ -142,7 +142,7 @@ def test_creates_capabilities(options): assert "foo" in opts["args"] assert opts["binary"] == "/bar" assert opts["prefs"]["foo"] == "bar" - assert opts["profile"] == profile.encoded + assert isinstance(opts["profile"], str) and opts["profile"] assert caps["proxy"]["proxyType"] == "manual" assert opts["log"]["level"] == "debug" diff --git a/py/test/unit/selenium/webdriver/wpewebkit/wpewebkit_options_tests.py b/py/test/unit/selenium/webdriver/wpewebkit/wpewebkit_options_tests.py index b43e01b8a3b5e4..af00b484ac8217 100644 --- a/py/test/unit/selenium/webdriver/wpewebkit/wpewebkit_options_tests.py +++ b/py/test/unit/selenium/webdriver/wpewebkit/wpewebkit_options_tests.py @@ -17,6 +17,7 @@ import pytest +from selenium.webdriver.common.options import PageLoadStrategy from selenium.webdriver.wpewebkit.options import Options @@ -25,6 +26,14 @@ def options(): return Options() +def test_starts_with_default_capabilities(options): + from selenium.webdriver import DesiredCapabilities + + caps = DesiredCapabilities.WPEWEBKIT.copy() + caps.update({"pageLoadStrategy": PageLoadStrategy.normal}) + assert options._caps == caps + + def test_set_binary_location(options): options.binary_location = "/foo/bar" assert options._binary_location == "/foo/bar" diff --git a/rake_tasks/bazel.rb b/rake_tasks/bazel.rb index 3c0edd5e358b42..cdd9148764c428 100644 --- a/rake_tasks/bazel.rb +++ b/rake_tasks/bazel.rb @@ -43,7 +43,7 @@ def self.execute(kind, args, target, &block) end end - raise "#{cmd.join(' ')} failed with exit code: #{cmd_exit_code}" if cmd_exit_code != 0 + raise "#{cmd.join(' ')} failed with exit code: #{cmd_exit_code}\nOutput: #{cmd_out}" if cmd_exit_code != 0 block&.call(cmd_out) return unless cmd_out =~ %r{\s+(bazel-bin/\S+)} diff --git a/rake_tasks/copyright.rb b/rake_tasks/copyright.rb deleted file mode 100644 index 10b1aeab6c1f54..00000000000000 --- a/rake_tasks/copyright.rb +++ /dev/null @@ -1,89 +0,0 @@ -# frozen_string_literal: true - -class Copyright - def initialize(comment_characters: '//', prefix: nil) - @comment_characters = comment_characters - @prefix = prefix - end - - def update(files) - files.each do |file| - lines = IO.readlines(file) - - index = -1 - lines.any? do |line| - done = true - if starts_with_comment_character?(line) || valid_copyright_notice_line?(line, index) - index += 1 - done = false - end - done - end - - if index == -1 - write_update_notice(file, lines, copyright_notice) - else - current = lines.shift(index + 1).join('') - if current != copyright_notice - write_update_notice(file, lines, copyright_notice) - end - end - end - end - - def starts_with_comment_character?(line) - line.index(@comment_characters)&.zero? - end - - def valid_copyright_notice_line?(line, index) - copyright_notice_lines[index + 1] && - line.index(copyright_notice_lines[index + 1])&.zero? - end - - def copyright_notice - copyright_notice_lines.join('') - end - - def copyright_notice_lines - @copyright_notice_lines ||= Array(@prefix) + commented_notice_lines - end - - def commented_notice_lines - notice_lines.map do |line| - "#{@comment_characters} #{line}".rstrip + "\n" - end - end - - def notice_lines - notice.split(/\n/) - end - - def write_update_notice(file, lines, notice) - puts "Adding notice to #{file}" - File.open(file, 'w') do |f| - f.write(notice + "\n") - lines.each { |line| f.write(line) } - end - end - - def notice - <<~eos - Licensed to the Software Freedom Conservancy (SFC) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The SFC licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - eos - end -end diff --git a/rb/CHANGES b/rb/CHANGES index 8555da61a11ad2..2f1d68def8897f 100644 --- a/rb/CHANGES +++ b/rb/CHANGES @@ -1,3 +1,14 @@ +4.17.0 (2024-01-22) +========================= + +* Logger defaults output to stderr instead of stdout +* Fully support Chrome 120+ old headless mode (#13271) +* Add ruby to Selenium Manager input for tracking (see #13288) +* Define default command_list (fixes #13307) +* Fix issues with incorrectly named edge browser +* Check for whether driver supports full page screenshots to error (#12799) +* Add CDP for Chrome 121 and remove 118 + 4.16.0 (2023-12-06) ========================= diff --git a/rb/Gemfile.lock b/rb/Gemfile.lock index c1f94afc83b55a..36708379c9b3eb 100644 --- a/rb/Gemfile.lock +++ b/rb/Gemfile.lock @@ -1,9 +1,10 @@ PATH remote: . specs: - selenium-devtools (0.120.0) + selenium-devtools (0.121.0) selenium-webdriver (~> 4.2) - selenium-webdriver (4.17.0.nightly) + selenium-webdriver (4.18.0.nightly) + base64 (~> 0.2) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) @@ -11,8 +12,8 @@ PATH GEM remote: https://rubygems.org/ specs: - abbrev (0.1.1) - activesupport (7.1.2) + abbrev (0.1.2) + activesupport (7.1.3) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) @@ -22,46 +23,49 @@ GEM minitest (>= 5.1) mutex_m tzinfo (~> 2.0) - addressable (2.8.5) + addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) base64 (0.2.0) - bigdecimal (3.1.4) - concurrent-ruby (1.2.2) + bigdecimal (3.1.6) + concurrent-ruby (1.2.3) connection_pool (2.4.1) crack (0.4.5) rexml csv (3.2.8) - debug (1.8.0) - irb (>= 1.5.0) - reline (>= 0.3.1) + debug (1.9.1) + irb (~> 1.10) + reline (>= 0.3.8) diff-lcs (1.5.0) drb (2.2.0) ruby2_keywords ffi (1.16.3) ffi (1.16.3-x64-mingw32) fileutils (1.7.2) - hashdiff (1.0.1) + git (1.19.1) + addressable (~> 2.8) + rchardet (~> 1.8) + hashdiff (1.1.0) i18n (1.14.1) concurrent-ruby (~> 1.0) - io-console (0.6.0) - irb (1.9.0) + io-console (0.7.2) + irb (1.11.1) rdoc - reline (>= 0.3.8) - json (2.6.3) - json (2.6.3-java) + reline (>= 0.4.2) + json (2.7.1) + json (2.7.1-java) language_server-protocol (3.17.0.3) listen (3.8.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) logger (1.6.0) - minitest (5.20.0) + minitest (5.21.2) mutex_m (0.2.0) - parallel (1.23.0) - parser (3.2.2.4) + parallel (1.24.0) + parser (3.3.0.5) ast (~> 2.4.1) racc - psych (5.1.1.1) + psych (5.1.2) stringio public_suffix (5.0.4) racc (1.7.3) @@ -72,12 +76,13 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) - rbs (3.3.2) + rbs (3.4.2) abbrev - rdoc (6.6.0) + rchardet (1.8.0) + rdoc (6.6.2) psych (>= 4.0.0) - regexp_parser (2.8.2) - reline (0.4.0) + regexp_parser (2.9.0) + reline (0.4.2) io-console (~> 0.5) rexml (3.2.6) rspec (3.12.0) @@ -93,34 +98,34 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-support (3.12.1) - rubocop (1.57.2) + rubocop (1.60.2) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 3.2.2.4) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.28.1, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) rubocop-ast (1.30.0) parser (>= 3.2.1.0) - rubocop-capybara (2.19.0) + rubocop-capybara (2.20.0) + rubocop (~> 1.41) + rubocop-factory_bot (2.25.1) rubocop (~> 1.41) - rubocop-factory_bot (2.24.0) - rubocop (~> 1.33) - rubocop-performance (1.19.1) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) - rubocop-rspec (2.25.0) + rubocop-performance (1.20.2) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) + rubocop-rspec (2.26.1) rubocop (~> 1.40) rubocop-capybara (~> 2.17) rubocop-factory_bot (~> 2.22) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) rubyzip (2.3.2) - securerandom (0.3.0) + securerandom (0.3.1) steep (1.5.3) activesupport (>= 5.1) concurrent-ruby (>= 1.1.10) @@ -136,8 +141,8 @@ GEM securerandom (>= 0.1) strscan (>= 1.0.0) terminal-table (>= 2, < 4) - stringio (3.0.9) - strscan (3.0.7) + stringio (3.1.0) + strscan (3.0.9) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) tzinfo (2.0.6) @@ -161,10 +166,11 @@ PLATFORMS DEPENDENCIES debug (~> 1.7) + git (~> 1.19) rack (~> 2.0) rake (~> 13.0) rspec (~> 3.0) - rubocop (~> 1.42) + rubocop (~> 1.60, >= 1.60.2) rubocop-performance (~> 1.15) rubocop-rspec (~> 2.16) selenium-devtools! diff --git a/rb/lib/selenium/devtools/BUILD.bazel b/rb/lib/selenium/devtools/BUILD.bazel index faa5a251c367e4..c94bb6ee38fda7 100644 --- a/rb/lib/selenium/devtools/BUILD.bazel +++ b/rb/lib/selenium/devtools/BUILD.bazel @@ -7,7 +7,7 @@ CDP_VERSIONS = [ "v85", "v119", "v120", - "v118", + "v121", ] rb_library( diff --git a/rb/lib/selenium/devtools/version.rb b/rb/lib/selenium/devtools/version.rb index 0942bc8334c6f9..a87c1bab56f74a 100644 --- a/rb/lib/selenium/devtools/version.rb +++ b/rb/lib/selenium/devtools/version.rb @@ -19,6 +19,6 @@ module Selenium module DevTools - VERSION = '0.120.0' + VERSION = '0.121.0' end # DevTools end # Selenium diff --git a/rb/lib/selenium/webdriver/common/takes_screenshot.rb b/rb/lib/selenium/webdriver/common/takes_screenshot.rb index ffac7a83c23676..965445ac26a2cf 100644 --- a/rb/lib/selenium/webdriver/common/takes_screenshot.rb +++ b/rb/lib/selenium/webdriver/common/takes_screenshot.rb @@ -49,6 +49,10 @@ def save_screenshot(png_path, full_page: false) # @api public def screenshot_as(format, full_page: false) + if full_page && !respond_to?(:save_full_page_screenshot) + raise Error::UnsupportedOperationError, "Full Page Screenshots are not supported for #{inspect}" + end + case format when :base64 full_page ? full_screenshot : screenshot @@ -57,8 +61,6 @@ def screenshot_as(format, full_page: false) else raise Error::UnsupportedOperationError, "unsupported format: #{format.inspect}" end - rescue NameError - raise Error::UnsupportedOperationError, "Full Page Screenshots are not supported for #{inspect}" end end # TakesScreenshot end # WebDriver diff --git a/rb/lib/selenium/webdriver/version.rb b/rb/lib/selenium/webdriver/version.rb index 48a40fe27cf1e4..0fdff5de07409f 100644 --- a/rb/lib/selenium/webdriver/version.rb +++ b/rb/lib/selenium/webdriver/version.rb @@ -19,6 +19,6 @@ module Selenium module WebDriver - VERSION = '4.17.0.nightly' + VERSION = '4.18.0.nightly' end # WebDriver end # Selenium diff --git a/rb/selenium-webdriver.gemspec b/rb/selenium-webdriver.gemspec index 08aae414350149..b82b6061d45583 100644 --- a/rb/selenium-webdriver.gemspec +++ b/rb/selenium-webdriver.gemspec @@ -47,14 +47,16 @@ Gem::Specification.new do |s| s.bindir = 'bin' s.require_paths = ['lib'] + s.add_runtime_dependency 'base64', ['~> 0.2'] s.add_runtime_dependency 'rexml', ['~> 3.2', '>= 3.2.5'] s.add_runtime_dependency 'rubyzip', ['>= 1.2.2', '< 3.0'] s.add_runtime_dependency 'websocket', ['~> 1.0'] + s.add_development_dependency 'git', ['~> 1.19'] s.add_development_dependency 'rack', ['~> 2.0'] s.add_development_dependency 'rake', ['~> 13.0'] s.add_development_dependency 'rspec', ['~> 3.0'] - s.add_development_dependency 'rubocop', ['~> 1.42'] + s.add_development_dependency 'rubocop', ['~> 1.60', '>=1.60.2'] s.add_development_dependency 'rubocop-performance', ['~> 1.15'] s.add_development_dependency 'rubocop-rspec', ['~> 2.16'] s.add_development_dependency 'webmock', ['~> 3.5'] diff --git a/rb/spec/integration/selenium/webdriver/takes_screenshot_spec.rb b/rb/spec/integration/selenium/webdriver/takes_screenshot_spec.rb index 884cde1440b91e..3cbc87ac970d2a 100644 --- a/rb/spec/integration/selenium/webdriver/takes_screenshot_spec.rb +++ b/rb/spec/integration/selenium/webdriver/takes_screenshot_spec.rb @@ -110,7 +110,8 @@ def save_screenshot_and_assert(source, path) expect(height).to be > viewport_height end - it 'does not take full page screenshot', except: {browser: :firefox} do + it 'does not take full page screenshot', only: {browser: %i[chrome edge safari safari_preview], + reason: 'these browsers do not implement this feature'} do expect { driver.save_screenshot path, full_page: true }.to raise_exception(Error::UnsupportedOperationError, /Full Page Screenshots are not supported/) diff --git a/rb/spec/unit/selenium/server_spec.rb b/rb/spec/unit/selenium/server_spec.rb index 8f131ce5abebf2..98ac3789dbfe01 100644 --- a/rb/spec/unit/selenium/server_spec.rb +++ b/rb/spec/unit/selenium/server_spec.rb @@ -206,7 +206,7 @@ module Selenium it 'sets options after instantiation' do allow(File).to receive(:exist?).with('selenium_server_deploy.jar').and_return(true) - server = described_class.new('selenium_server_deploy.jar') + server = described_class.new('selenium_server_deploy.jar', port: port) expect(server.port).to eq(port) expect(server.timeout).to eq(30) expect(server.background).to be false diff --git a/rb/spec/unit/selenium/webdriver/wait_spec.rb b/rb/spec/unit/selenium/webdriver/wait_spec.rb index ec91617f80210f..e7887698e98dfb 100644 --- a/rb/spec/unit/selenium/webdriver/wait_spec.rb +++ b/rb/spec/unit/selenium/webdriver/wait_spec.rb @@ -51,7 +51,7 @@ def wait(*args) expect(wait.until(&block)).to be true end - it 'will use the message from any NoSuchElementError raised while waiting' do + it 'uses the message from any NoSuchElementError raised while waiting' do block = -> { raise Error::NoSuchElementError, 'foo' } expect { diff --git a/rust/BUILD.bazel b/rust/BUILD.bazel index 6f9cf023f6b9bb..64def296fbbfda 100644 --- a/rust/BUILD.bazel +++ b/rust/BUILD.bazel @@ -77,7 +77,7 @@ rust_binary( name = "selenium-manager", srcs = ["src/main.rs"], edition = "2021", - version = "0.4.17-nightly", + version = "0.4.18-nightly", visibility = ["//visibility:public"], deps = [ ":selenium_manager", diff --git a/rust/CHANGELOG.md b/rust/CHANGELOG.md index 9cd210e179329e..c63b7b25c7a55f 100644 --- a/rust/CHANGELOG.md +++ b/rust/CHANGELOG.md @@ -1,3 +1,10 @@ +0.4.17 +====== + +* Use latest browser from cache when browser path is not discovered (#13283) +* Throw a descriptive message when error parsing JSON from response (#13291) +* Tracking Selenium Manager usage through Plausible (#11211) (#13173) + 0.4.16 ====== * Use online mapping to discover proper geckodriver version (#11671) (#13133) diff --git a/rust/Cargo.Bazel.lock b/rust/Cargo.Bazel.lock index 7a7c0b579f347a..5956f0ee963436 100644 --- a/rust/Cargo.Bazel.lock +++ b/rust/Cargo.Bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "1d06eec2c22227cf3d1a8ccec8ff414f3719faa35aff22345fb8cad5427e9bc0", + "checksum": "6c1f6097515f112b7db700377b70f1722cd000d2c54e9eac67a835a659bea64a", "crates": { "addr2line 0.19.0": { "name": "addr2line", @@ -8089,9 +8089,9 @@ }, "license": "Apache-2.0/ISC/MIT" }, - "selenium-manager 0.4.17-nightly": { + "selenium-manager 0.4.18-nightly": { "name": "selenium-manager", - "version": "0.4.17-nightly", + "version": "0.4.18-nightly", "repository": null, "targets": [ { @@ -8216,7 +8216,7 @@ "selects": {} }, "edition": "2021", - "version": "0.4.17-nightly" + "version": "0.4.18-nightly" }, "license": "Apache-2.0" }, @@ -13625,7 +13625,7 @@ }, "binary_crates": [], "workspace_members": { - "selenium-manager 0.4.17-nightly": "rust" + "selenium-manager 0.4.18-nightly": "rust" }, "conditions": { "aarch64-apple-darwin": [ diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 74fe2c414fb4b3..84126cdf131468 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1505,7 +1505,7 @@ dependencies = [ [[package]] name = "selenium-manager" -version = "0.4.17-nightly" +version = "0.4.18-nightly" dependencies = [ "anyhow", "assert_cmd", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index d6f71c693634b1..8ab871640e8524 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "selenium-manager" -version = "0.4.17-nightly" # don't forget to update rust/BUILD.bazel +version = "0.4.18-nightly" # don't forget to update rust/BUILD.bazel edition = "2021" authors = ["Selenium &2 bazel run @rules_rust//:rustfmt + +section "Copyright" +bazel run //scripts:update_copyright diff --git a/scripts/update_cdp.py b/scripts/update_cdp.py index 495c382527dcf0..a43a9bca2963fd 100755 --- a/scripts/update_cdp.py +++ b/scripts/update_cdp.py @@ -103,22 +103,20 @@ def create_new_chrome_files(src_base, chrome_milestone): target_dir = root_dir / f"{src_base}/v{new_chrome(chrome_milestone)}" old_dir = root_dir / f"{src_base}/v{old_chrome(chrome_milestone)}" - # New target must not be already present - if not target_dir.is_dir(): - if old_dir.is_dir(): - shutil.rmtree(old_dir) + if old_dir.is_dir(): + shutil.rmtree(old_dir) - if source_dir.is_dir() and any(source_dir.iterdir()): - os.makedirs(target_dir, exist_ok=True) - for item in source_dir.iterdir(): - shutil.copy(item, target_dir) + if source_dir.is_dir() and any(source_dir.iterdir()): + os.makedirs(target_dir, exist_ok=True) + for item in source_dir.iterdir(): + shutil.copy(item, target_dir) - for file in target_dir.iterdir(): - replace_in_file(file, previous_chrome(chrome_milestone), new_chrome(chrome_milestone)) - new_filename = file.name.replace(previous_chrome(chrome_milestone), new_chrome(chrome_milestone)) - file.rename(target_dir / new_filename) + for file in target_dir.iterdir(): + replace_in_file(file, previous_chrome(chrome_milestone), new_chrome(chrome_milestone)) + new_filename = file.name.replace(previous_chrome(chrome_milestone), new_chrome(chrome_milestone)) + file.rename(target_dir / new_filename) - subprocess.run(["git", "add", str(target_dir / "*")], cwd=root_dir) + subprocess.run(["git", "add", str(target_dir / "*")], cwd=root_dir) def replace_in_file(file_path, old_string, new_string, is_regex=False): @@ -147,8 +145,7 @@ def update_dotnet(chrome_milestone): files = [ root_dir / "dotnet/selenium-dotnet-version.bzl", - root_dir / "dotnet/src/webdriver/WebDriver.csproj.prebuild.cmd", - root_dir / "dotnet/src/webdriver/WebDriver.csproj.prebuild.sh", + root_dir / "dotnet/src/webdriver/WebDriver.csproj", root_dir / "dotnet/src/webdriver/DevTools/DevToolsDomains.cs", ] for file in files: @@ -188,3 +185,5 @@ def update_js(chrome_milestone): update_ruby(chrome_milestone) update_python(chrome_milestone) update_js(chrome_milestone) + + print(f"adding CDP {new_chrome(chrome_milestone)} and removing {old_chrome(chrome_milestone)}") diff --git a/scripts/update_copyright.py b/scripts/update_copyright.py new file mode 100755 index 00000000000000..9ca241b65789b6 --- /dev/null +++ b/scripts/update_copyright.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python + +import glob +import os +from pathlib import Path + +class Copyright: + NOTICE = """Licensed to the Software Freedom Conservancy (SFC) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The SFC licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License.""" + + def __init__(self, comment_characters='//', prefix=None): + self._comment_characters = comment_characters + self._prefix = prefix or [] + + def update(self, files): + for file in files: + with open(file, 'r') as f: + lines = f.readlines() + + index = -1 + for i, line in enumerate(lines): + if line.startswith(self._comment_characters) or \ + self.valid_copyright_notice_line(line, index): + index += 1 + else: + break + + if index == -1: + self.write_update_notice(file, lines) + else: + current = ''.join(lines[:index + 1]) + if current != self.copyright_notice: + self.write_update_notice(file, lines[index + 1:]) + + def valid_copyright_notice_line(self, line, index): + return index + 1 < len(self.copyright_notice_lines) and \ + line.startswith(self.copyright_notice_lines[index + 1]) + + @property + def copyright_notice(self): + return ''.join(self.copyright_notice_lines) + + @property + def copyright_notice_lines(self): + return self._prefix + self.commented_notice_lines + + @property + def commented_notice_lines(self): + return [f"{self._comment_characters} {line}".rstrip() + "\n" for line in self.NOTICE.split('\n')] + + def write_update_notice(self, file, lines): + print(f"Adding notice to {file}") + with open(file, 'w') as f: + f.write(self.copyright_notice + "\n") + f.writelines(lines) + +ROOT = Path(os.path.realpath(__file__)).parent.parent + +JS_EXCLUSIONS = [ + f"{ROOT}/javascript/atoms/test/jquery.min.js", + f"{ROOT}/javascript/jsunit/**/*.js", + f"{ROOT}/javascript/node/selenium-webdriver/node_modules/**/*.js", + f"{ROOT}/javascript/selenium-core/lib/**/*.js", + f"{ROOT}/javascript/selenium-core/scripts/ui-element.js", + f"{ROOT}/javascript/selenium-core/scripts/ui-map-sample.js", + f"{ROOT}/javascript/selenium-core/scripts/user-extensions.js", + f"{ROOT}/javascript/selenium-core/scripts/xmlextras.js", + f"{ROOT}/javascript/selenium-core/xpath/**/*.js", + f"{ROOT}/javascript/grid-ui/node_modules/**/*.js" +] + +PY_EXCLUSIONS = [ + f"{ROOT}/py/selenium/webdriver/common/bidi/cdp.py", + f"{ROOT}/py/generate.py", + f"{ROOT}/py/selenium/webdriver/common/devtools/**/*", + f"{ROOT}/py/venv/**/*" +] + + +def update_files(file_pattern, exclusions, comment_characters='//', prefix=None): + included = set(glob.glob(file_pattern, recursive=True)) + excluded = set() + for pattern in exclusions: + excluded.update(glob.glob(pattern, recursive=True)) + files = included - excluded + + copyright = Copyright(comment_characters, prefix) + copyright.update(files) + + +if __name__ == "__main__": + update_files(f"{ROOT}/javascript/**/*.js", JS_EXCLUSIONS) + update_files(f"{ROOT}/javascript/**/*.tsx", []) + update_files(f"{ROOT}/py/**/*.py", PY_EXCLUSIONS, comment_characters="#") + update_files(f"{ROOT}/rb/**/*.rb", [], comment_characters="#", prefix=["# frozen_string_literal: true\n", "\n"]) + update_files(f"{ROOT}/java/**/*.java", []) + update_files(f"{ROOT}/rust/**/*.rs", [])