From 0f0c27cb90efe958502b4e773fe649e1b0572dad Mon Sep 17 00:00:00 2001 From: Alessandro Rodi Date: Thu, 18 Jun 2020 17:11:06 +0200 Subject: [PATCH] Add chrome with Downloads capabilties --- .semaphore/master-deploy.yml | 19 +++++++++ .semaphore/semaphore.yml | 32 ++++++++++++++ Gemfile.lock | 56 +++++++++++++++++++++++++ README.md | 34 +++++++++++++-- lib/so_many_devices.rb | 17 ++++++-- lib/so_many_devices/downloads_helper.rb | 37 ++++++++++++++++ lib/so_many_devices/version.rb | 2 +- so_many_devices.gemspec | 2 + spec/downloads_helper_spec.rb | 11 +++++ spec/so_many_devices_spec.rb | 11 +++-- 10 files changed, 211 insertions(+), 10 deletions(-) create mode 100644 .semaphore/master-deploy.yml create mode 100644 .semaphore/semaphore.yml create mode 100644 Gemfile.lock create mode 100644 lib/so_many_devices/downloads_helper.rb create mode 100644 spec/downloads_helper_spec.rb diff --git a/.semaphore/master-deploy.yml b/.semaphore/master-deploy.yml new file mode 100644 index 0000000..e1211c8 --- /dev/null +++ b/.semaphore/master-deploy.yml @@ -0,0 +1,19 @@ +version: v1.0 +name: master-deploy +agent: + machine: + type: e1-standard-2 + os_image: ubuntu1804 + +blocks: + - name: master-deploy + task: + secrets: + - name: rubygems-deploy + jobs: + - name: master-deploy + commands: + - checkout --use-cache + - gem build so_many_devices + - chmod 0600 ~/.gem/credentials + - gem push renuo-cli-*.gem diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml new file mode 100644 index 0000000..a90712a --- /dev/null +++ b/.semaphore/semaphore.yml @@ -0,0 +1,32 @@ +version: "v1.0" +name: so_many_devices +agent: + machine: + type: e1-standard-2 + os_image: ubuntu1804 +auto_cancel: + running: + when: "true" + +blocks: + - name: tests + execution_time_limit: + minutes: 10 + dependencies: [] + task: + secrets: + - name: so_many_devices + env_vars: + - name: RAILS_ENV + value: test + jobs: + - name: tests + commands: + - checkout --use-cache + - cache restore + - bundle install -j 4 --path vendor/bundle + - cache store + - bundle exec rspec +promotions: + - name: master + pipeline_file: master-deploy.yml diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..f119f5f --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,56 @@ +PATH + remote: . + specs: + so_many_devices (0.1.0) + capybara (>= 3.0) + +GEM + remote: https://rubygems.org/ + specs: + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + capybara (3.32.1) + addressable + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (~> 1.5) + xpath (~> 3.2) + diff-lcs (1.3) + mini_mime (1.0.2) + mini_portile2 (2.4.0) + nokogiri (1.10.9) + mini_portile2 (~> 2.4.0) + public_suffix (4.0.4) + rack (2.2.2) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rake (12.3.3) + regexp_parser (1.7.0) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-core (3.9.2) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-support (3.9.3) + xpath (3.2.0) + nokogiri (~> 1.8) + +PLATFORMS + ruby + +DEPENDENCIES + rake (~> 12.0) + rspec (~> 3.0) + so_many_devices! + +BUNDLED WITH + 2.1.4 diff --git a/README.md b/README.md index 050beb3..4d3b724 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ In your `rails_helper.rb` you can configure your preferred device for tests: ```ruby config.before(:each, type: :system, js: true) do - driven_by :iphone_6_7_8 + driven_by :iphone_6_7_8 end ``` @@ -37,7 +37,7 @@ You can always use the headless version of each device by appending `_headless` ```ruby config.before(:each, type: :system, js: true) do - driven_by :iphone_6_7_8_headless + driven_by :iphone_6_7_8_headless end ``` @@ -45,7 +45,7 @@ We use it to run our system tests on so many devices! Here is our standard confi ```ruby config.before(:each, type: :system, js: true) do - driven_by ENV['SELENIUM_DRIVER'].to_sym + driven_by ENV['SELENIUM_DRIVER'].to_sym end ``` @@ -62,6 +62,34 @@ of course, your tests need to run on so many devices! Check [the YML file containing all the devices](./lib/so_many_devices/so_many_devices.yml). So many! +## Chrome with downloads capabilities + +We provide also an instance of Chrome already configured with +Downloads capabilities and a `SoManyDevices::DownloadsHelper` that you can use in your project. + +Use the following: + +```ruby +config.before(:each, type: :system, js: true) do + driven_by :selenium_chrome_with_download_headless # or non-headless version +end + +config.include SoManyDevices::DownloadsHelper, type: :system +``` + +and in your test (just an example...): + +```ruby +it 'can download a file', :js do + visit funny_page_path + click_link 'Download PDF' + wait_for_download + expect(downloads.length).to eq(1) + expect(download).to match(/.*\.pdf/) +end +``` + + ## Development After checking out the repo, run `bin/setup` to install dependencies. diff --git a/lib/so_many_devices.rb b/lib/so_many_devices.rb index 5da72a3..b50fd38 100644 --- a/lib/so_many_devices.rb +++ b/lib/so_many_devices.rb @@ -1,8 +1,10 @@ require "so_many_devices/version" +require "so_many_devices/downloads_helper" +require 'yaml' +require 'capybara' module SoManyDevices - class Error < StandardError; - end + class Error < StandardError; end devices = YAML::load_file(File.join(__dir__, 'so_many_devices.yml')) @@ -11,7 +13,7 @@ class Error < StandardError; headless_args = ['--headless', '--disable-site-isolation-trials'] headless_args << '--disable-gpu' if Gem.win_platform? - [[device_name.to_sym, standard_args], ["#{device_name}_headless".to_sym, headless_args]].each do |device_name, args| + [[device_name, standard_args], ["#{device_name}_headless", headless_args]].each do |device_name, args| Capybara.register_driver device_name.to_sym do |app| capabilities = Selenium::WebDriver::Remote::Capabilities.chrome( 'goog:chromeOptions' => { args: args, mobileEmulation: options } @@ -19,5 +21,14 @@ class Error < StandardError; Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities) end end + + [[:selenium_chrome_with_download, standard_args], [:selenium_chrome_with_download_headless, headless_args]].each do |device_name, args| + Capybara.register_driver device_name do | app | + browser_options = ::Selenium::WebDriver::Chrome::Options.new(args: args) + browser_options.add_preference(:download, prompt_for_download: false, default_directory: SoManyDevices::DownloadsHelper::PATH.to_s) + browser_options.add_preference(:browser, set_download_behavior: { behavior: 'allow' }) + Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options) + end + end end end diff --git a/lib/so_many_devices/downloads_helper.rb b/lib/so_many_devices/downloads_helper.rb new file mode 100644 index 0000000..60470df --- /dev/null +++ b/lib/so_many_devices/downloads_helper.rb @@ -0,0 +1,37 @@ +module SoManyDevices + module DownloadsHelper + TIMEOUT = 10 + PATH = "#{Dir.pwd}/tmp/downloads/" + + def downloads + Dir["#{PATH}/*"] + end + + def download + downloads.first + end + + def download_content + wait_for_download + File.read(download) + end + + def wait_for_download + Timeout.timeout(TIMEOUT) do + sleep 0.1 until downloaded? + end + end + + def downloaded? + !downloading? && downloads.any? + end + + def downloading? + downloads.grep(/\.crdownload$/).any? + end + + def clear_downloads + FileUtils.rm_f(downloads) + end + end +end diff --git a/lib/so_many_devices/version.rb b/lib/so_many_devices/version.rb index 8e60aa5..33a3572 100644 --- a/lib/so_many_devices/version.rb +++ b/lib/so_many_devices/version.rb @@ -1,3 +1,3 @@ module SoManyDevices - VERSION = "0.1.0" + VERSION = "0.2.0" end diff --git a/so_many_devices.gemspec b/so_many_devices.gemspec index d5bbe61..8cf8f81 100644 --- a/so_many_devices.gemspec +++ b/so_many_devices.gemspec @@ -24,4 +24,6 @@ Gem::Specification.new do |spec| spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] + + spec.add_dependency 'capybara', '>= 3.0' end diff --git a/spec/downloads_helper_spec.rb b/spec/downloads_helper_spec.rb new file mode 100644 index 0000000..332536d --- /dev/null +++ b/spec/downloads_helper_spec.rb @@ -0,0 +1,11 @@ +RSpec.describe SoManyDevices::DownloadsHelper do + include SoManyDevices::DownloadsHelper + + it 'points to a tmp path' do + FileUtils.mkdir_p(described_class::PATH) + expect(described_class::PATH).to end_with('tmp/downloads') + expect(downloads).to eq([]) + FileUtils.touch("#{described_class::PATH}/example.txt") + expect(downloads).to eq(['example.txt']) + end +end diff --git a/spec/so_many_devices_spec.rb b/spec/so_many_devices_spec.rb index c29c394..dde0ec8 100644 --- a/spec/so_many_devices_spec.rb +++ b/spec/so_many_devices_spec.rb @@ -1,9 +1,14 @@ RSpec.describe SoManyDevices do - it "has a version number" do + it 'has a version number' do expect(SoManyDevices::VERSION).not_to be nil end - it "does something useful" do - expect(false).to eq(true) + it 'defines a list of devices' do + devices = YAML::load_file(File.join(__dir__, '../lib/so_many_devices.yml')) + already_available_devices = 5 + chrome_with_download_devices = 2 + expect(Capybara.drivers.length).to eq((devices.keys.length * 2) + + already_available_devices + + chrome_with_download_devices) end end