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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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