hyper-spec 1.0.alpha1.5 → 1.0.alpha1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c17257af4d7b13916648e6ba8a495f1ca0b2f5a300e8ea96e7490c47cd696691
4
- data.tar.gz: 6a823c91fd6d46c1c086296316af229b993761bee436e4b3940371b0ae4ecd03
3
+ metadata.gz: 443b8fc1d67013a7ffa37d43b8b5076d8b5375d83b247dc2f36b348d97da2ed8
4
+ data.tar.gz: 5c5264998e05d454a97bab490f9db4be02a5956e8b08fc47c8cc2c9292daf40a
5
5
  SHA512:
6
- metadata.gz: b7eb46d260a9025424755c1248500f8ab7b79956385149507b7518a40d1e38848dfdfac9eb19fd8661b6022d37aa6d627d21483e90251d52044cadad07b5533a
7
- data.tar.gz: 20b3e256b12ad4c3ef08b0ac371b2bb8ce3b6dc4a7498e4a249e15e32243f339780eaaabf5e952c6c5b64180846bf2eea71a93c98d6ea599c1f64b447d0da1c0
6
+ metadata.gz: 35cf7981c3612173408aa541cb06db31d8367c0ab5dc8f3d5354785a941d02f6902c21e8f8ae39a5284d9152e05621bad06af9a1e342ef12b7a349f0e74079b6
7
+ data.tar.gz: bc5cf881fc4e20b85bb15a68559c4d2b7adc5de0687cde7ca38653392f9bdde6c52e4dc0650ca6f9ca0dfc7eee7e8e1b6f78ee17007b77bbd7a07353c7a23826
data/bin/console CHANGED
File without changes
data/bin/setup CHANGED
File without changes
data/hyper-spec.gemspec CHANGED
@@ -24,30 +24,33 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
24
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
25
  spec.require_paths = ['lib']
26
26
 
27
+ spec.add_dependency 'actionview'
27
28
  spec.add_dependency 'capybara'
28
29
  spec.add_dependency 'chromedriver-helper', '1.2.0'
29
- spec.add_dependency 'libv8', '~> 6.7.0'
30
+ spec.add_dependency 'filecache'
31
+ # spec.add_dependency 'libv8', '~> 7.3.492.27.1'
30
32
  spec.add_dependency 'method_source'
31
- spec.add_dependency 'mini_racer', '~> 0.2.4'
32
- spec.add_dependency 'opal', '>= 0.11.0', '< 0.12.0'
33
- spec.add_dependency 'parser', '>= 2.3.3.1'
34
- spec.add_dependency 'pry'
35
- spec.add_dependency 'rspec-rails'
33
+ spec.add_dependency 'opal', ENV['OPAL_VERSION'] || '>= 0.11.0', '< 2.0'
34
+ spec.add_dependency 'parser', '>= 2.3.3.1' # on rails-6 this is now >= 2.3
35
+ spec.add_dependency 'rspec'
36
36
  spec.add_dependency 'selenium-webdriver'
37
37
  spec.add_dependency 'timecop', '~> 0.8.1'
38
38
  spec.add_dependency 'uglifier'
39
- spec.add_dependency 'unparser', '>= 0.4.2' # 0.4 is incompatible
39
+ spec.add_dependency 'unparser', '>= 0.4.2'
40
40
  spec.add_dependency 'webdrivers'
41
41
 
42
- spec.add_development_dependency 'bundler', ['>= 1.17.3', '< 2.1']
42
+ spec.add_development_dependency 'bundler'
43
43
  spec.add_development_dependency 'hyper-component', HyperSpec::VERSION
44
+ spec.add_development_dependency 'mini_racer'
44
45
  spec.add_development_dependency 'opal-browser', '~> 0.2.0'
45
- spec.add_development_dependency 'opal-rails', '~> 0.9.4'
46
+ spec.add_development_dependency 'opal-rails', '>= 0.9.4'
46
47
  spec.add_development_dependency 'pry-rescue'
48
+ spec.add_development_dependency 'pry-stack_explorer'
47
49
  spec.add_development_dependency 'puma'
48
- spec.add_development_dependency 'rails', '>= 4.0.0'
50
+ spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
49
51
  spec.add_development_dependency 'rake'
50
52
  spec.add_development_dependency 'react-rails', '>= 2.3.0', '< 2.5.0'
53
+ spec.add_development_dependency 'rspec-rails'
51
54
  spec.add_development_dependency 'rspec-collection_matchers'
52
55
  spec.add_development_dependency 'rspec-expectations'
53
56
  spec.add_development_dependency 'rspec-its'
data/lib/hyper-spec.rb CHANGED
@@ -1,14 +1,136 @@
1
- require 'capybara/rspec'
1
+ # hyper-spec
2
+ require 'action_view'
2
3
  require 'opal'
4
+ require 'unparser'
5
+ require 'method_source'
6
+ require 'filecache'
7
+
8
+ require 'capybara/rspec'
9
+ require 'hyper-spec/internal/client_execution'
10
+ require 'hyper-spec/internal/component_mount'
11
+ require 'hyper-spec/internal/controller'
12
+ require 'hyper-spec/internal/copy_locals'
13
+ require 'hyper-spec/internal/patches'
14
+ require 'hyper-spec/internal/rails_controller_helpers'
15
+ require 'hyper-spec/internal/time_cop.rb'
16
+ require 'hyper-spec/internal/window_sizing'
17
+
18
+ require 'hyper-spec/controller_helpers'
19
+
20
+ require 'hyper-spec/wait_for_ajax'
21
+
22
+ require 'hyper-spec/helpers'
23
+ require 'hyper-spec/expectations'
24
+
25
+ require 'parser/current'
26
+ if defined?(Selenium::WebDriver::Firefox)
27
+ require 'selenium/web_driver/firefox/profile'
28
+ end
3
29
  require 'selenium-webdriver'
4
30
 
5
- require 'hyper-spec/component_test_helpers'
6
31
  require 'hyper-spec/version'
7
- require 'hyper-spec/wait_for_ajax'
8
- require 'selenium/web_driver/firefox/profile'
32
+
33
+
34
+ begin
35
+ require 'pry'
36
+ rescue LoadError
37
+ nil
38
+ end
39
+
40
+ Parser::Builders::Default.emit_procarg0 = true
41
+
42
+ # not available in parser 2.3
43
+ if Parser::Builders::Default.respond_to? :emit_arg_inside_procarg0
44
+ Parser::Builders::Default.emit_arg_inside_procarg0 = true
45
+ end
46
+
47
+ module HyperSpec
48
+ if defined? Pry
49
+ # add a before eval hook to pry so we can capture the source
50
+ class << self
51
+ attr_accessor :current_pry_code_block
52
+ Pry.hooks.add_hook(:before_eval, 'hyper_spec_code_capture') do |code|
53
+ HyperSpec.current_pry_code_block = code
54
+ end
55
+ end
56
+ end
57
+
58
+ def self.reset_between_examples
59
+ @reset_between_examples ||= []
60
+ end
61
+
62
+ def self.reset_between_examples?
63
+ RSpec.configuration.reset_between_examples
64
+ end
65
+
66
+ def self.reset_sessions!
67
+ Capybara.old_reset_sessions!
68
+ end
69
+ end
70
+
71
+ # TODO: figure out why we need this patch - its because we are on an old version
72
+ # of Selenium Webdriver, but why?
73
+ require 'selenium-webdriver'
74
+
75
+ module Selenium
76
+ module WebDriver
77
+ module Chrome
78
+ module Bridge
79
+ COMMANDS = remove_const(:COMMANDS).dup
80
+ COMMANDS[:get_log] = [:post, 'session/:session_id/log']
81
+ COMMANDS.freeze
82
+
83
+ def log(type)
84
+ data = execute :get_log, {}, type: type.to_s
85
+
86
+ Array(data).map do |l|
87
+ begin
88
+ LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
89
+ rescue KeyError
90
+ next
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ module Capybara
100
+ class << self
101
+ alias old_reset_sessions! reset_sessions!
102
+ def reset_sessions!
103
+ old_reset_sessions! if HyperSpec.reset_between_examples?
104
+ end
105
+ end
106
+ end
107
+
108
+ RSpec.configure do |config|
109
+ config.add_setting :reset_between_examples, default: true
110
+ config.before(:all, no_reset: true) do
111
+ HyperSpec.reset_between_examples << RSpec.configuration.reset_between_examples
112
+ RSpec.configuration.reset_between_examples = false
113
+ end
114
+ config.before(:all, no_reset: false) do
115
+ HyperSpec.reset_between_examples << RSpec.configuration.reset_between_examples
116
+ RSpec.configuration.reset_between_examples = true
117
+ end
118
+ config.after(:all) do
119
+ HyperSpec.reset_sessions! unless HyperSpec.reset_between_examples?
120
+ # If rspecs step is used first in a file, it will NOT call config.before(:all) causing the
121
+ # reset_between_examples stack to be mismatched, so we check, if its already empty we
122
+ # just leave.
123
+ next if HyperSpec.reset_between_examples.empty?
124
+
125
+ RSpec.configuration.reset_between_examples = HyperSpec.reset_between_examples.pop
126
+ end
127
+ config.before(:each) do |example|
128
+ insure_page_loaded(true) if example.metadata[:js] && !HyperSpec.reset_between_examples?
129
+ end
130
+ end
9
131
 
10
132
  RSpec.configure do |config|
11
- config.include HyperSpec::ComponentTestHelpers
133
+ config.include HyperSpec::Helpers
12
134
  config.include HyperSpec::WaitForAjax
13
135
  config.include Capybara::DSL
14
136
 
@@ -17,17 +139,21 @@ RSpec.configure do |config|
17
139
  config.add_setting :debugger_width, default: nil
18
140
 
19
141
  config.before(:each) do
20
- Hyperstack.class_eval do
21
- def self.on_server?
22
- true
142
+ if defined?(Hyperstack)
143
+ Hyperstack.class_eval do
144
+ def self.on_server?
145
+ true
146
+ end
23
147
  end
24
- end if defined?(Hyperstack)
148
+ end
25
149
  # for compatibility with HyperMesh
26
- HyperMesh.class_eval do
27
- def self.on_server?
28
- true
150
+ if defined?(HyperMesh)
151
+ HyperMesh.class_eval do
152
+ def self.on_server?
153
+ true
154
+ end
29
155
  end
30
- end if defined?(HyperMesh)
156
+ end
31
157
  end
32
158
 
33
159
  config.before(:each, js: true) do
@@ -43,42 +169,51 @@ RSpec.configure do |config|
43
169
  PusherFake::Channel.reset if defined? PusherFake
44
170
  end
45
171
  end
46
-
47
172
  end
48
173
 
49
174
  # Capybara config
50
- RSpec.configure do |_config|
175
+ RSpec.configure do |config|
176
+ config.before(:each) do |example|
177
+ HyperSpec::Internal::Controller.current_example = example
178
+ HyperSpec::Internal::Controller.description_displayed = false
179
+ end
180
+
181
+ config.add_setting :wait_for_initialization_time
182
+ config.wait_for_initialization_time = 3
183
+
51
184
  Capybara.default_max_wait_time = 10
52
185
 
53
186
  Capybara.register_driver :chrome do |app|
54
187
  options = {}
55
188
  options.merge!(
56
- args: %w[auto-open-devtools-for-tabs],
57
- prefs: { 'devtools.open_docked' => false, "devtools.currentDockState" => "undocked", devtools: {currentDockState: :undocked} }
58
- ) unless ENV['NO_DEBUGGER']
59
- # this does not seem to work properly. Don't document this feature yet.
189
+ w3c: false,
190
+ args: %w[auto-open-devtools-for-tabs]
191
+ )
60
192
  options['mobileEmulation'] = { 'deviceName' => ENV['DEVICE'].tr('-', ' ') } if ENV['DEVICE']
61
- capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(chromeOptions: options)
193
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
194
+ chromeOptions: options, 'goog:loggingPrefs' => { browser: 'ALL' }
195
+ )
62
196
  Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities)
63
197
  end
64
198
 
199
+ Capybara.register_driver :firefox do |app|
200
+ Capybara::Selenium::Driver.new(app, browser: :firefox)
201
+ end
202
+
65
203
  Capybara.register_driver :chrome_headless_docker_travis do |app|
66
204
  options = ::Selenium::WebDriver::Chrome::Options.new
67
205
  options.add_argument('--headless')
68
206
  options.add_argument('--no-sandbox')
69
207
  options.add_argument('--disable-dev-shm-usage')
70
- Capybara::Selenium::Driver.new(app, browser: :chrome, :driver_path => "/usr/lib/chromium-browser/chromedriver", options: options)
71
- end
72
-
73
- Capybara.register_driver :firefox do |app|
74
- Capybara::Selenium::Driver.new(app, browser: :firefox)
208
+ Selenium::WebDriver::Chrome::Service.driver_path = '/usr/lib/chromium-browser/chromedriver'
209
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
75
210
  end
76
211
 
77
212
  Capybara.register_driver :firefox_headless do |app|
78
213
  options = Selenium::WebDriver::Firefox::Options.new
79
214
  options.headless!
80
215
  Capybara::Selenium::Driver.new(app, browser: :firefox, options: options)
81
- end
216
+ end if defined?(Selenium::WebDriver::Firefox)
82
217
 
83
218
  Capybara.register_driver :selenium_with_firebug do |app|
84
219
  profile = Selenium::WebDriver::Firefox::Profile.new
@@ -86,7 +221,7 @@ RSpec.configure do |_config|
86
221
  profile.enable_firebug
87
222
  options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
88
223
  Capybara::Selenium::Driver.new(app, browser: :firefox, options: options)
89
- end
224
+ end if defined?(Selenium::WebDriver::Firefox)
90
225
 
91
226
  Capybara.register_driver :safari do |app|
92
227
  Capybara::Selenium::Driver.new(app, browser: :safari)
@@ -103,5 +238,4 @@ RSpec.configure do |_config|
103
238
  when 'travis' then :chrome_headless_docker_travis
104
239
  else :selenium_chrome_headless
105
240
  end
106
-
107
241
  end
@@ -0,0 +1,164 @@
1
+ module HyperSpec
2
+ # Defines a series of methods that will build a test page
3
+ # This module is typically included into the HyperSpecTestController class.
4
+ module ControllerHelpers
5
+ # These methods are dependent on the stack being used. See the
6
+ # RailsControllerHelpers module and rack.rb for two implementations.
7
+ # Each method should append the appropriate code to the @page array
8
+
9
+ # return an empty 204 status either by setting headers or
10
+ # returning and appropriate response for rack.
11
+ def ping!
12
+ raise 'must implement'
13
+ end
14
+
15
+ def json!
16
+ # this can be a no-op but if json is not included by the application,
17
+ # hyper-spec will fail, with an error complaining about to_json
18
+ end
19
+
20
+ # return a script or style_sheet tag pointing to some asset.
21
+ # typically you be pointing to a path on the server or using
22
+ # sprockets to deliver the file.
23
+
24
+ def require!(_file_)
25
+ raise 'must implement'
26
+ end
27
+
28
+ def style_sheet!(_file_)
29
+ raise 'must implement'
30
+ end
31
+
32
+ # deliver the page. The @page variable will contain the html ready to go,
33
+ # any additional options that are passed through from the spec will be
34
+ # in the @render_params variable. For example layout: 'my_special_layout'
35
+
36
+ def deliver!
37
+ raise 'must implement'
38
+ end
39
+
40
+ # generate a react_render top level block. This will only be called if
41
+ # you use the mount directive in your specs, so it is optional.
42
+
43
+ def mount_component!
44
+ raise 'mount_component not implemented in HyperSpecTestController'
45
+ end
46
+
47
+ # by default the route back to the controller will be the controller name, less the
48
+ # word Controller, and underscored. If you want some other name redefine this
49
+ # method in the HyperSpecController class.
50
+
51
+ def self.included(base)
52
+ def base.route_root
53
+ # Implement underscore without using rails underscore, so we don't have a
54
+ # dependency on ActiveSupport
55
+ name.gsub(/Controller$/, '')
56
+ .gsub(/::/, '/')
57
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
58
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
59
+ .tr('-', '_')
60
+ .downcase
61
+ end
62
+ end
63
+
64
+ # The remainder of the methods should work for most implementations.
65
+
66
+ # helper method checking the render_on parameter
67
+
68
+ def on_client?
69
+ @render_on != :server_only
70
+ end
71
+
72
+ # The controllers behavior is kept as an array of values in the Controller cache
73
+ # under a unique id for each test run. Grab the parameters and move them to instance vars
74
+
75
+ # If this is just a ping! Then we can just exit with nil.
76
+
77
+ def initialize!
78
+ return if params[:id] == 'ping'
79
+
80
+ key = "/#{self.class.route_root}/#{params[:id]}"
81
+ test_params = Internal::Controller.cache_read(key)
82
+
83
+ @component_name = test_params[0]
84
+ @component_params = test_params[1]
85
+ @html_block = test_params[2]
86
+ @render_params = test_params[3]
87
+ @render_on = @render_params.delete(:render_on) || :client_only
88
+ @_mock_time = @render_params.delete(:mock_time)
89
+ @style_sheet = @render_params.delete(:style_sheet)
90
+ @javascript = @render_params.delete(:javascript)
91
+ @code = @render_params.delete(:code)
92
+
93
+ @page = ['<body>']
94
+ end
95
+
96
+ # add any html code generated by the insert_html directive
97
+
98
+ def html_block!
99
+ @page << @html_block
100
+ end
101
+
102
+ # patch behavior of the HyperComponent TopLevelRailsComponent class
103
+ # so that things like events are passed back to the test harness
104
+ TOP_LEVEL_COMPONENT_PATCH =
105
+ Opal.compile(File.read(File.expand_path('../sources/top_level_rails_component.rb', __dir__)))
106
+
107
+ # patch time cop and lolex so they stay in sync across the client and server
108
+ TIME_COP_CLIENT_PATCH =
109
+ Opal.compile(File.read(File.expand_path('../hyper-spec/internal/time_cop.rb', __dir__))) +
110
+ "\n#{File.read(File.expand_path('../sources/lolex.js', __dir__))}"
111
+
112
+ def client_code!
113
+ if @component_name
114
+ @page << "<script type='text/javascript'>\n#{TOP_LEVEL_COMPONENT_PATCH}\n</script>"
115
+ end
116
+ @page << "<script type='text/javascript'>\n#{@code}\n</script>" if @code
117
+ end
118
+
119
+ def time_cop_patch!
120
+ @page << "<script type='text/javascript'>\n#{TIME_COP_CLIENT_PATCH}\n</script>"
121
+ end
122
+
123
+ # Add the go_function to the client console. This is used to stop a hyper-spec pause directive.
124
+
125
+ def go_function!
126
+ @page << "<script type='text/javascript'>go = function() "\
127
+ '{window.hyper_spec_waiting_for_go = false}</script>'
128
+ end
129
+
130
+ # First lines displayed on the console will be the name of the spec
131
+
132
+ def example_title!
133
+ title = Internal::Controller.current_example_description!
134
+ @page << "<script type='text/javascript'>console.log('%c#{title}',"\
135
+ "'color:green; font-weight:bold; font-size: 200%')</script>"
136
+ end
137
+
138
+ # generate each piece of the page, and then deliver it
139
+
140
+ def style_sheet_file
141
+ @style_sheet || (!@render_params[:layout] && 'application')
142
+ end
143
+
144
+ def application_file
145
+ @javascript || (on_client? && !@render_params[:layout] && 'application')
146
+ end
147
+
148
+ def test
149
+ return ping! unless initialize!
150
+
151
+ html_block!
152
+ example_title! if Internal::Controller.current_example
153
+ go_function! if on_client?
154
+ style_sheet!(style_sheet_file) if style_sheet_file
155
+ application!(application_file) if application_file
156
+ json!
157
+ time_cop_patch! if on_client? || Lolex.initialized?
158
+ client_code! if on_client?
159
+ mount_component! if @component_name
160
+ @page = @page.join("\n") + "\n</body>\n"
161
+ deliver!
162
+ end
163
+ end
164
+ end