# -*- mode: ruby -*- $LOAD_PATH.unshift File.expand_path('.') require 'rake' require 'net/telnet' require 'stringio' require 'fileutils' require 'open-uri' include Rake::DSL Rake.application.instance_variable_set(:@name, 'go') orig_verbose = verbose verbose(false) # The CrazyFun build grammar. There's no magic here, just ruby require 'rake_tasks/crazy_fun/main' require 'rake_tasks/selenium_rake/detonating_handler' require 'rake_tasks/selenium_rake/crazy_fun' # The CrazyFun builders - Most of these are either partially or fully obsolete # Note the order here is important - The top 2 are used in inheritance chains require 'rake_tasks/crazy_fun/mappings/file_copy_hack' require 'rake_tasks/crazy_fun/mappings/tasks' require 'rake_tasks/crazy_fun/mappings/rake_mappings' # Location of all new (non-CrazyFun) methods require 'rake_tasks/selenium_rake/browsers' require 'rake_tasks/selenium_rake/checks' require 'rake_tasks/selenium_rake/cpp_formatter' require 'rake_tasks/selenium_rake/ie_generator' require 'rake_tasks/selenium_rake/java_formatter' require 'rake_tasks/selenium_rake/type_definitions_generator' # Our modifications to the Rake / Bazel libraries require 'rake/task' require 'rake_tasks/rake/task' require 'rake_tasks/rake/dsl' 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 ? true : false $DEBUG = true if ENV['debug'] == 'true' verbose($DEBUG) def release_version '4.15' end def version "#{release_version}.0-SNAPSHOT" end # The build system used by webdriver is layered on top of rake, and we call it # "crazy fun" for no readily apparent reason. # First off, create a new CrazyFun object. crazy_fun = SeleniumRake::CrazyFun.new # Secondly, we add the handlers, which are responsible for turning a build # rule into a (series of) rake tasks. For example if we're looking at a file # in subdirectory "subdir" contains the line: # # java_library(:name => "example", :srcs => ["foo.java"]) # # we would generate a rake target of "//subdir:example" which would generate # a Java JAR at "build/subdir/example.jar". # # If crazy fun doesn't know how to handle a particular output type ("java_library" # in the example above) then it will throw an exception, stopping the build CrazyFun::Mappings::RakeMappings.new.add_all(crazy_fun) # Finally, find every file named "build.desc" in the project, and generate # rake tasks from them. These tasks are normal rake tasks, and can be invoked # from rake. # FIXME: the rules for the targets were removed and build files won't load # crazy_fun.create_tasks(Dir['**/build.desc']) # If it looks like a bazel target, build it with bazel rule /\/\/.*/ do |task| task.out = Bazel.execute('build', %w[], task.name) end # Spoof tasks to get CI working with bazel task '//java/test/org/openqa/selenium/environment/webserver:webserver:uber' => [ '//java/test/org/openqa/selenium/environment:webserver' ] # Java targets required for release. These should all be java_export targets. # Generated from: bazel query 'kind(maven_publish, set(//java/... //third_party/...))' | sort JAVA_RELEASE_TARGETS = %w[ //java/src/org/openqa/selenium/chrome:chrome.publish //java/src/org/openqa/selenium/chromium:chromium.publish //java/src/org/openqa/selenium/devtools/v116:v116.publish //java/src/org/openqa/selenium/devtools/v117:v117.publish //java/src/org/openqa/selenium/devtools/v118:v118.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 //java/src/org/openqa/selenium/grid/sessionmap/jdbc:jdbc.publish //java/src/org/openqa/selenium/grid/sessionmap/redis:redis.publish //java/src/org/openqa/selenium/grid:bom-dependencies.publish //java/src/org/openqa/selenium/grid:bom.publish //java/src/org/openqa/selenium/grid:grid.publish //java/src/org/openqa/selenium/ie:ie.publish //java/src/org/openqa/selenium/json:json.publish //java/src/org/openqa/selenium/manager:manager.publish //java/src/org/openqa/selenium/os:os.publish //java/src/org/openqa/selenium/remote/http:http.publish //java/src/org/openqa/selenium/remote:remote.publish //java/src/org/openqa/selenium/safari:safari.publish //java/src/org/openqa/selenium/support:support.publish //java/src/org/openqa/selenium:client-combined.publish //java/src/org/openqa/selenium:core.publish ] # Notice that because we're using rake, anything you can do in a normal rake # build can also be done here. For example, here we set the default task task default: [:grid] task all: [ :"selenium-java", '//java/test/org/openqa/selenium/environment:webserver' ] task all_zip: [:'prep-release-zip'] task tests: [ '//java/test/org/openqa/selenium/htmlunit:htmlunit', '//java/test/org/openqa/selenium/firefox:test-synthesized', '//java/test/org/openqa/selenium/ie:ie', '//java/test/org/openqa/selenium/chrome:chrome', '//java/test/org/openqa/selenium/edge:edge', '//java/test/org/openqa/selenium/support:small-tests', '//java/test/org/openqa/selenium/support:large-tests', '//java/test/org/openqa/selenium/remote:small-tests', '//java/test/org/openqa/selenium/remote/server/log:test', '//java/test/org/openqa/selenium/remote/server:small-tests' ] task chrome: ['//java/src/org/openqa/selenium/chrome'] task grid: [:'selenium-server-standalone'] task ie: ['//java/src/org/openqa/selenium/ie'] task firefox: ['//java/src/org/openqa/selenium/firefox'] task remote: %i[remote_server remote_client] task remote_client: ['//java/src/org/openqa/selenium/remote'] task remote_server: ['//java/src/org/openqa/selenium/remote/server'] task safari: ['//java/src/org/openqa/selenium/safari'] task selenium: ['//java/src/org/openqa/selenium:core'] task support: [ '//java/src/org/openqa/selenium/support' ] desc 'Build the standalone server' task 'selenium-server-standalone' => '//java/src/org/openqa/selenium/grid:executable-grid' task test_javascript: [ '//javascript/atoms:test-chrome:run', '//javascript/webdriver:test-chrome:run', '//javascript/selenium-atoms:test-chrome:run', '//javascript/selenium-core:test-chrome:run' ] task test_chrome: ['//java/test/org/openqa/selenium/chrome:chrome:run'] task test_edge: ['//java/test/org/openqa/selenium/edge:edge:run'] task test_chrome_atoms: [ '//javascript/atoms:test-chrome:run', '//javascript/chrome-driver:test-chrome:run', '//javascript/webdriver:test-chrome:run' ] task test_htmlunit: [ '//java/test/org/openqa/selenium/htmlunit:htmlunit:run' ] task test_grid: [ '//java/test/org/openqa/grid/common:common:run', '//java/test/org/openqa/grid:grid:run', '//java/test/org/openqa/grid/e2e:e2e:run', '//java/test/org/openqa/selenium/remote:remote-driver-grid-tests:run' ] task test_ie: [ '//cpp/iedriverserver:win32', '//cpp/iedriverserver:x64', '//java/test/org/openqa/selenium/ie:ie:run' ] task test_jobbie: [:test_ie] task test_firefox: ['//java/test/org/openqa/selenium/firefox:marionette:run'] task test_remote_server: [ '//java/test/org/openqa/selenium/remote/server:small-tests:run', '//java/test/org/openqa/selenium/remote/server/log:test:run' ] task test_remote: [ '//java/test/org/openqa/selenium/json:small-tests:run', '//java/test/org/openqa/selenium/remote:common-tests:run', '//java/test/org/openqa/selenium/remote:client-tests:run', '//java/test/org/openqa/selenium/remote:remote-driver-tests:run', :test_remote_server ] task test_safari: ['//java/test/org/openqa/selenium/safari:safari:run'] task test_support: [ '//java/test/org/openqa/selenium/support:small-tests:run', '//java/test/org/openqa/selenium/support:large-tests:run' ] task test_java_webdriver: %i[ test_htmlunit test_firefox test_remote_server ] task test_java_webdriver: [:test_ie] if SeleniumRake::Checks.windows? task test_java_webdriver: [:test_chrome] if SeleniumRake::Checks.chrome? task test_java_webdriver: [:test_edge] if SeleniumRake::Checks.edge? task test_java: [ '//java/test/org/openqa/selenium/atoms:test:run', :test_java_small_tests, :test_support, :test_java_webdriver, :test_selenium, 'test_grid' ] task test_java_small_tests: [ '//java/test/org/openqa/selenium:small-tests:run', '//java/test/org/openqa/selenium/json:small-tests:run', '//java/test/org/openqa/selenium/support:small-tests:run', '//java/test/org/openqa/selenium/remote:common-tests:run', '//java/test/org/openqa/selenium/remote:client-tests:run', '//java/test/org/openqa/grid/selenium/node:node:run', '//java/test/org/openqa/grid/selenium/proxy:proxy:run', '//java/test/org/openqa/selenium/remote/server:small-tests:run', '//java/test/org/openqa/selenium/remote/server/log:test:run' ] task test_py: [:py_prep_for_install_release, 'py:marionette_test'] task test: %i[test_javascript test_java] task test: [:test_py] if SeleniumRake::Checks.python? task build: %i[all firefox remote selenium tests] desc 'Clean build artifacts.' task :clean do rm_rf 'build/' rm_rf 'java/build/' rm_rf 'dist/' end # Create a new IEGenerator instance ie_generator = SeleniumRake::IEGenerator.new # Generate a C++ Header file for mapping between magic numbers and #defines # in the C++ code. ie_generator.generate_type_mapping( name: 'ie_result_type_cpp', src: 'cpp/iedriver/result_types.txt', type: 'cpp', out: 'cpp/iedriver/IEReturnTypes.h' ) task javadocs: %i[//java/src/org/openqa/selenium/grid:all-javadocs] do rm_rf 'build/javadoc' mkdir_p 'build/javadoc' # Temporary hack, bazel is not outputting where things are so we need to do it manually. # This will only work on Posix based OSes Rake::Task['//java/src/org/openqa/selenium/grid:all-javadocs'] out = 'bazel-bin/java/src/org/openqa/selenium/grid/all-javadocs.jar' cmd = %{cd build/javadoc && jar xf "../../#{out}" 2>&1} if SeleniumRake::Checks.windows? cmd = cmd.gsub(/\//, '\\').gsub(/:/, ';') end ok = system(cmd) ok or raise "could not unpack javadocs" File.open('build/javadoc/stylesheet.css', 'a') { |file| file.write(<<~EOF /* Custom selenium-specific styling */ .blink { animation: 2s cubic-bezier(0.5, 0, 0.85, 0.85) infinite blink; } @keyframes blink { 50% { opacity: 0; } } EOF ) } end file 'cpp/iedriver/sizzle.h' => ['//third_party/js/sizzle:sizzle:header'] do cp 'build/third_party/js/sizzle/sizzle.h', 'cpp/iedriver/sizzle.h' end task sizzle_header: ['cpp/iedriver/sizzle.h'] task ios_driver: [ '//javascript/atoms/fragments:get_visible_text:ios', '//javascript/atoms/fragments:click:ios', '//javascript/atoms/fragments:back:ios', '//javascript/atoms/fragments:forward:ios', '//javascript/atoms/fragments:submit:ios', '//javascript/atoms/fragments:xpath:ios', '//javascript/atoms/fragments:xpaths:ios', '//javascript/atoms/fragments:type:ios', '//javascript/atoms/fragments:get_attribute:ios', '//javascript/atoms/fragments:clear:ios', '//javascript/atoms/fragments:is_selected:ios', '//javascript/atoms/fragments:is_enabled:ios', '//javascript/atoms/fragments:is_shown:ios', '//javascript/atoms/fragments:stringify:ios', '//javascript/atoms/fragments:link_text:ios', '//javascript/atoms/fragments:link_texts:ios', '//javascript/atoms/fragments:partial_link_text:ios', '//javascript/atoms/fragments:partial_link_texts:ios', '//javascript/atoms/fragments:get_interactable_size:ios', '//javascript/atoms/fragments:scroll_into_view:ios', '//javascript/atoms/fragments:get_effective_style:ios', '//javascript/atoms/fragments:get_element_size:ios', '//javascript/webdriver/atoms/fragments:get_location_in_view:ios' ] task 'prep-release-zip': [ '//java/src/org/openqa/selenium:client-zip', '//java/src/org/openqa/selenium/grid:server-zip', '//java/src/org/openqa/selenium/grid:executable-grid', ] do [ "build/dist/selenium-server-#{version}.zip", "build/dist/selenium-java-#{version}.zip", "build/dist/selenium-server-#{version}.jar" ].each do |f| rm_f(f) if File.exists?(f) end mkdir_p 'build/dist' File.delete cp "bazel-bin/java/src/org/openqa/selenium/grid/server-zip.zip", "build/dist/selenium-server-#{version}.zip", preserve: false chmod 0666, "build/dist/selenium-server-#{version}.zip" cp "bazel-bin/java/src/org/openqa/selenium/client-zip.zip", "build/dist/selenium-java-#{version}.zip", preserve: false chmod 0666, "build/dist/selenium-java-#{version}.zip" cp "bazel-bin/java/src/org/openqa/selenium/grid/selenium", "build/dist/selenium-server-#{version}.jar", preserve: false chmod 0666, "build/dist/selenium-server-#{version}.jar" end task 'release-java': %i[prep-release-zip publish-maven] def read_m2_user_pass # First check env vars, then the settings.xml config inside .m2 user = nil pass = nil if ENV['SEL_M2_USER'] && ENV['SEL_M2_PASS'] puts 'Fetching m2 user and pass from environment variables.' user = ENV['SEL_M2_USER'] pass = ENV['SEL_M2_PASS'] return [user, pass] end settings = File.read(ENV['HOME'] + '/.m2/settings.xml') found_section = false settings.each_line do |line| if !found_section found_section = line.include? 'sonatype-nexus-staging' else if (user.nil?) && line.include?('') user = line.split('')[1].split('') pass = line.split('')[1].split(' '//java/src/org/openqa/selenium:client-combined' namespace :safari do desc 'Build the SafariDriver java client' task build: [ '//java/src/org/openqa/selenium/safari' ] end task :authors do puts 'Generating AUTHORS file' sh "(git log --use-mailmap --format='%aN <%aE>' ; cat .OLD_AUTHORS) | sort -uf > AUTHORS" end namespace :copyright do 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']) 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']) end end namespace :side do task atoms: [ '//javascript/atoms/fragments:find-element' ] do # TODO: move directly to IDE's directory once the repositories are merged baseDir = 'build/javascript/atoms' mkdir_p baseDir [ Rake::Task['//javascript/atoms/fragments:find-element'].out ].each do |atom| name = File.basename(atom) puts "Generating #{atom} as #{name}" File.open(File.join(baseDir, name), 'w') do |f| f << "// GENERATED CODE - DO NOT EDIT\n" f << 'module.exports = ' f << IO.read(atom).strip f << ";\n" end end end end namespace :node do atom_list = %w[ //javascript/atoms/fragments:find-elements //javascript/atoms/fragments:is-displayed //javascript/webdriver/atoms:get-attribute ] task atoms: atom_list do baseDir = 'javascript/node/selenium-webdriver/lib/atoms' mkdir_p baseDir puts 'rake outs are below' p rake_outs = [ Rake::Task['//javascript/atoms/fragments:is-displayed'].out, Rake::Task['//javascript/webdriver/atoms:get-attribute'].out, Rake::Task['//javascript/atoms/fragments:find-elements'].out ] rake_outs.each do |atom| puts "atom is #{atom}\n" name = File.basename(atom) puts "Generating #{atom} as #{name}" File.open(File.join(baseDir, name), 'w') do |f| f << "// GENERATED CODE - DO NOT EDIT\n" f << 'module.exports = ' f << IO.read(atom).strip f << ";\n" end end end task :build do sh 'bazel build //javascript/node/selenium-webdriver' end task 'dry-run': [ 'node:build' ] do sh 'bazel run javascript/node/selenium-webdriver:selenium-webdriver.pack' end task deploy: [ 'node:build' ] do sh 'bazel run javascript/node/selenium-webdriver:selenium-webdriver.publish' end task :docs do sh 'node javascript/node/gendocs.js' end end namespace :py do task prep: [ '//javascript/atoms/fragments:is-displayed', '//javascript/webdriver/atoms:get-attribute', '//third_party/js/selenium:webdriver_xpi' ] do py_home = 'py/' remote_py_home = py_home + 'selenium/webdriver/remote/' firefox_py_home = py_home + 'selenium/webdriver/firefox/' if SeleniumRake::Checks.windows? remote_py_home = remote_py_home.gsub(/\//, '\\') firefox_py_home = firefox_py_home .gsub(/\//, '\\') end cp Rake::Task['//javascript/atoms/fragments:is-displayed'].out, remote_py_home + 'isDisplayed.js', verbose: true cp Rake::Task['//javascript/webdriver/atoms:get-attribute'].out, remote_py_home + 'getAttribute.js', verbose: true cp Rake::Task['//third_party/js/selenium:webdriver_xpi'].out, firefox_py_home, verbose: true cp 'third_party/js/selenium/webdriver.json', firefox_py_home + 'webdriver_prefs.json', verbose: true cp 'LICENSE', py_home + 'LICENSE', verbose: true end bazel :unit do Bazel.execute('test', [], '//py:unit') end task docs: :prep do sh 'tox -c py/tox.ini -e docs', verbose: true end task install: :prep do Dir.chdir('py') do sh py_exe + ' setup.py install', verbose: true end end %w[chrome ff marionette ie edge remote_firefox safari].each do |browser| browser_data = SeleniumRake::Browsers::BROWSERS[browser] deps = browser_data[:deps] || [] deps += [:prep] driver = browser_data[:driver] task "#{browser}_test" => deps do tox_test driver end end end at_exit do if File.exist?('.git') && !SeleniumRake::Checks.windows? system 'sh', '.git-fixfiles' end end