Merge branch 'master' into 4951-request-vm
[arvados.git] / apps / workbench / test / integration_helper.rb
1 require 'test_helper'
2 require 'capybara/rails'
3 require 'capybara/poltergeist'
4 require 'uri'
5 require 'yaml'
6
7 POLTERGEIST_OPTS = {
8   window_size: [1200, 800],
9   phantomjs_options: ['--ignore-ssl-errors=true'],
10   inspector: true,
11 }
12
13 Capybara.register_driver :poltergeist do |app|
14   Capybara::Poltergeist::Driver.new app, POLTERGEIST_OPTS
15 end
16
17 Capybara.register_driver :poltergeist_without_file_api do |app|
18   js = File.expand_path '../support/remove_file_api.js', __FILE__
19   Capybara::Poltergeist::Driver.new app, POLTERGEIST_OPTS.merge(extensions: [js])
20 end
21
22 module WaitForAjax
23   Capybara.default_wait_time = 5
24   def wait_for_ajax
25     Timeout.timeout(Capybara.default_wait_time) do
26       loop until finished_all_ajax_requests?
27     end
28   end
29
30   def finished_all_ajax_requests?
31     page.evaluate_script('jQuery.active').zero?
32   end
33 end
34
35 module AssertDomEvent
36   # Yield the supplied block, then wait for an event to arrive at a
37   # DOM element.
38   def assert_triggers_dom_event events, target='body'
39     magic = 'received-dom-event-' + rand(2**30).to_s(36)
40     page.evaluate_script <<eos
41       $('#{target}').one('#{events}', function() {
42         $('body').addClass('#{magic}');
43       });
44 eos
45     yield
46     assert_selector "body.#{magic}"
47     page.evaluate_script "$('body').removeClass('#{magic}');";
48   end
49 end
50
51 module HeadlessHelper
52   class HeadlessSingleton
53     def self.get
54       @headless ||= Headless.new reuse: false
55     end
56   end
57
58   Capybara.default_driver = :rack_test
59
60   def self.included base
61     base.class_eval do
62       setup do
63         Capybara.use_default_driver
64         @headless = false
65       end
66
67       teardown do
68         if @headless
69           @headless.stop
70           @headless = false
71         end
72       end
73     end
74   end
75
76   def need_selenium reason=nil
77     Capybara.current_driver = :selenium
78     unless ENV['ARVADOS_TEST_HEADFUL'] or @headless
79       @headless = HeadlessSingleton.get
80       @headless.start
81     end
82   end
83
84   def need_javascript reason=nil
85     unless Capybara.current_driver == :selenium
86       Capybara.current_driver = :poltergeist
87     end
88   end
89 end
90
91 class ActionDispatch::IntegrationTest
92   # Make the Capybara DSL available in all integration tests
93   include Capybara::DSL
94   include ApiFixtureLoader
95   include WaitForAjax
96   include AssertDomEvent
97   include HeadlessHelper
98
99   @@API_AUTHS = self.api_fixture('api_client_authorizations')
100
101   def page_with_token(token, path='/')
102     # Generate a page path with an embedded API token.
103     # Typical usage: visit page_with_token('token_name', page)
104     # The token can be specified by the name of an api_client_authorizations
105     # fixture, or passed as a raw string.
106     api_token = ((@@API_AUTHS.include? token) ?
107                  @@API_AUTHS[token]['api_token'] : token)
108     path_parts = path.partition("#")
109     sep = (path_parts.first.include? '?') ? '&' : '?'
110     q_string = URI.encode_www_form('api_token' => api_token)
111     path_parts.insert(1, "#{sep}#{q_string}")
112     path_parts.join("")
113   end
114
115   # Find a page element, but return false instead of raising an
116   # exception if not found. Use this with assertions to explain that
117   # the error signifies a failed test rather than an unexpected error
118   # during a testing procedure.
119   def find? *args
120     begin
121       find *args
122     rescue Capybara::ElementNotFound
123       false
124     end
125   end
126
127   @@screenshot_count = 1
128   def screenshot
129     image_file = "./tmp/workbench-fail-#{@@screenshot_count}.png"
130     begin
131       page.save_screenshot image_file
132     rescue Capybara::NotSupportedByDriverError
133       # C'est la vie.
134     else
135       puts "Saved #{image_file}"
136       @@screenshot_count += 1
137     end
138   end
139
140   teardown do
141     if not passed?
142       screenshot
143     end
144     if Capybara.current_driver == :selenium
145       page.execute_script("window.localStorage.clear()")
146     end
147     Capybara.reset_sessions!
148   end
149 end