hyper-spec 1.0.alpha1.3 → 1.0.alpha1.8
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 +4 -4
- data/.gitignore +4 -0
- data/bin/console +0 -0
- data/bin/setup +0 -0
- data/hyper-spec.gemspec +17 -20
- data/lib/hyper-spec.rb +170 -28
- data/lib/hyper-spec/controller_helpers.rb +164 -0
- data/lib/hyper-spec/expectations.rb +64 -0
- data/lib/hyper-spec/helpers.rb +225 -0
- data/lib/hyper-spec/internal/client_execution.rb +94 -0
- data/lib/hyper-spec/internal/component_mount.rb +140 -0
- data/lib/hyper-spec/internal/controller.rb +70 -0
- data/lib/hyper-spec/internal/copy_locals.rb +103 -0
- data/lib/hyper-spec/internal/patches.rb +86 -0
- data/lib/hyper-spec/internal/rails_controller_helpers.rb +50 -0
- data/lib/hyper-spec/{time_cop.rb → internal/time_cop.rb} +14 -2
- data/lib/hyper-spec/internal/window_sizing.rb +73 -0
- data/lib/hyper-spec/rack.rb +67 -0
- data/lib/hyper-spec/version.rb +1 -1
- data/lib/hyper-spec/wait_for_ajax.rb +1 -1
- data/multi_level_how_it_works.md +49 -0
- metadata +100 -69
- data/Gemfile.lock +0 -373
- data/lib/hyper-spec/component_test_helpers.rb +0 -362
- data/lib/hyper-spec/unparser_patch.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70e0d39ed642bc1a7d8215db2edcc4798d3229f0530d3a6c1a3355c452158630
|
4
|
+
data.tar.gz: cbc96bac1e4e5378537364bea704afe27afecceab369920c281569622b59cbad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef7ed137034bf28dfcd5af3a72914ab8aa81734ef53006d0ce6287d767bca067b6417e5c86f699be4460dba3e7ba62b690d370f463690557e164647b604c8070
|
7
|
+
data.tar.gz: dfbc57840b6ee1560080181e83d8cc391eafe18084613b48facfc7a566df815d4fbab8c29987a895df77bf8219a54323dec85393db1f8bbecb436152969e7a3c
|
data/.gitignore
CHANGED
data/bin/console
CHANGED
File without changes
|
data/bin/setup
CHANGED
File without changes
|
data/hyper-spec.gemspec
CHANGED
@@ -6,54 +6,51 @@ require 'hyper-spec/version'
|
|
6
6
|
Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
7
7
|
spec.name = 'hyper-spec'
|
8
8
|
spec.version = HyperSpec::VERSION
|
9
|
-
spec.authors = ['Mitch VanDuyn', '
|
9
|
+
spec.authors = ['Mitch VanDuyn', 'AdamCreekroad', 'Jan Biedermann']
|
10
10
|
spec.email = ['mitch@catprint.com', 'jan@kursator.com']
|
11
|
-
spec.summary = 'Drive your
|
12
|
-
spec.description = 'A
|
11
|
+
spec.summary = 'Drive your Opal and Hyperstack client and server specs from RSpec and Capybara'
|
12
|
+
spec.description = 'A Hyperstack application consists of isomorphic React Components, '\
|
13
13
|
'Active Record Models, Stores, Operations and Policiespec. '\
|
14
14
|
'Test them all from Rspec, regardless if the code runs on the client or server.'
|
15
|
-
spec.homepage = 'http://
|
15
|
+
spec.homepage = 'http://hyperstack.org'
|
16
16
|
spec.license = 'MIT'
|
17
|
-
# spec.metadata = {
|
18
|
-
# "homepage_uri" => 'http://ruby-hyperloop.org',
|
19
|
-
# "source_code_uri" => 'https://github.com/ruby-hyperloop/hyper-component'
|
20
|
-
# }
|
21
|
-
|
22
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(gemfiles|spec)/}) }
|
23
18
|
spec.bindir = 'exe'
|
24
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
20
|
spec.require_paths = ['lib']
|
26
21
|
|
22
|
+
spec.add_dependency 'actionview'
|
27
23
|
spec.add_dependency 'capybara'
|
28
24
|
spec.add_dependency 'chromedriver-helper', '1.2.0'
|
29
|
-
spec.add_dependency '
|
25
|
+
spec.add_dependency 'filecache'
|
30
26
|
spec.add_dependency 'method_source'
|
31
|
-
spec.add_dependency '
|
32
|
-
spec.add_dependency '
|
33
|
-
spec.add_dependency '
|
34
|
-
spec.add_dependency 'pry'
|
35
|
-
spec.add_dependency 'rspec-rails'
|
27
|
+
spec.add_dependency 'opal', ENV['OPAL_VERSION'] || '>= 0.11.0', '< 2.0'
|
28
|
+
spec.add_dependency 'parser'
|
29
|
+
spec.add_dependency 'rspec'
|
36
30
|
spec.add_dependency 'selenium-webdriver'
|
37
31
|
spec.add_dependency 'timecop', '~> 0.8.1'
|
38
32
|
spec.add_dependency 'uglifier'
|
39
|
-
spec.add_dependency 'unparser', '>= 0.2'
|
33
|
+
spec.add_dependency 'unparser', '>= 0.4.2'
|
40
34
|
spec.add_dependency 'webdrivers'
|
41
35
|
|
42
|
-
spec.add_development_dependency 'bundler'
|
36
|
+
spec.add_development_dependency 'bundler'
|
43
37
|
spec.add_development_dependency 'hyper-component', HyperSpec::VERSION
|
38
|
+
spec.add_development_dependency 'mini_racer'
|
44
39
|
spec.add_development_dependency 'opal-browser', '~> 0.2.0'
|
45
|
-
spec.add_development_dependency 'opal-rails', '
|
40
|
+
spec.add_development_dependency 'opal-rails', '>= 0.9.4'
|
46
41
|
spec.add_development_dependency 'pry-rescue'
|
42
|
+
spec.add_development_dependency 'pry-stack_explorer'
|
47
43
|
spec.add_development_dependency 'puma'
|
48
|
-
spec.add_development_dependency 'rails', '>=
|
44
|
+
spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
|
49
45
|
spec.add_development_dependency 'rake'
|
50
46
|
spec.add_development_dependency 'react-rails', '>= 2.3.0', '< 2.5.0'
|
47
|
+
spec.add_development_dependency 'rspec-rails'
|
51
48
|
spec.add_development_dependency 'rspec-collection_matchers'
|
52
49
|
spec.add_development_dependency 'rspec-expectations'
|
53
50
|
spec.add_development_dependency 'rspec-its'
|
54
51
|
spec.add_development_dependency 'rspec-mocks'
|
55
52
|
spec.add_development_dependency 'rspec-steps', '~> 2.1.1'
|
56
|
-
spec.add_development_dependency 'rubocop'
|
53
|
+
spec.add_development_dependency 'rubocop' #, '~> 0.51.0'
|
57
54
|
spec.add_development_dependency 'shoulda'
|
58
55
|
spec.add_development_dependency 'shoulda-matchers'
|
59
56
|
spec.add_development_dependency 'spring-commands-rspec'
|
data/lib/hyper-spec.rb
CHANGED
@@ -1,14 +1,144 @@
|
|
1
|
-
|
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
|
-
|
8
|
-
|
32
|
+
|
33
|
+
|
34
|
+
begin
|
35
|
+
require 'pry'
|
36
|
+
rescue LoadError
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# opt-in to most recent AST format:
|
41
|
+
Parser::Builders::Default.emit_lambda = true
|
42
|
+
Parser::Builders::Default.emit_procarg0 = true
|
43
|
+
(Parser::Builders::Default.emit_encoding = true) rescue nil
|
44
|
+
(Parser::Builders::Default.emit_index = true) rescue nil
|
45
|
+
(Parser::Builders::Default.emit_arg_inside_procarg0 = true) rescue nil
|
46
|
+
(Parser::Builders::Default.emit_forward_arg = true) rescue nil
|
47
|
+
(Parser::Builders::Default.emit_kwargs = true) rescue nil
|
48
|
+
(Parser::Builders::Default.emit_match_pattern = true) rescue nil
|
49
|
+
|
50
|
+
# not available in parser 2.3
|
51
|
+
if Parser::Builders::Default.respond_to? :emit_arg_inside_procarg0
|
52
|
+
Parser::Builders::Default.emit_arg_inside_procarg0 = true
|
53
|
+
end
|
54
|
+
|
55
|
+
module HyperSpec
|
56
|
+
if defined? Pry
|
57
|
+
# add a before eval hook to pry so we can capture the source
|
58
|
+
class << self
|
59
|
+
attr_accessor :current_pry_code_block
|
60
|
+
Pry.hooks.add_hook(:before_eval, 'hyper_spec_code_capture') do |code|
|
61
|
+
HyperSpec.current_pry_code_block = code
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.reset_between_examples
|
67
|
+
@reset_between_examples ||= []
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.reset_between_examples?
|
71
|
+
RSpec.configuration.reset_between_examples
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.reset_sessions!
|
75
|
+
Capybara.old_reset_sessions!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# TODO: figure out why we need this patch - its because we are on an old version
|
80
|
+
# of Selenium Webdriver, but why?
|
81
|
+
require 'selenium-webdriver'
|
82
|
+
|
83
|
+
module Selenium
|
84
|
+
module WebDriver
|
85
|
+
module Chrome
|
86
|
+
module Bridge
|
87
|
+
COMMANDS = remove_const(:COMMANDS).dup
|
88
|
+
COMMANDS[:get_log] = [:post, 'session/:session_id/log']
|
89
|
+
COMMANDS.freeze
|
90
|
+
|
91
|
+
def log(type)
|
92
|
+
data = execute :get_log, {}, type: type.to_s
|
93
|
+
|
94
|
+
Array(data).map do |l|
|
95
|
+
begin
|
96
|
+
LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
|
97
|
+
rescue KeyError
|
98
|
+
next
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
module Capybara
|
108
|
+
class << self
|
109
|
+
alias old_reset_sessions! reset_sessions!
|
110
|
+
def reset_sessions!
|
111
|
+
old_reset_sessions! if HyperSpec.reset_between_examples?
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
RSpec.configure do |config|
|
117
|
+
config.add_setting :reset_between_examples, default: true
|
118
|
+
config.before(:all, no_reset: true) do
|
119
|
+
HyperSpec.reset_between_examples << RSpec.configuration.reset_between_examples
|
120
|
+
RSpec.configuration.reset_between_examples = false
|
121
|
+
end
|
122
|
+
config.before(:all, no_reset: false) do
|
123
|
+
HyperSpec.reset_between_examples << RSpec.configuration.reset_between_examples
|
124
|
+
RSpec.configuration.reset_between_examples = true
|
125
|
+
end
|
126
|
+
config.after(:all) do
|
127
|
+
HyperSpec.reset_sessions! unless HyperSpec.reset_between_examples?
|
128
|
+
# If rspecs step is used first in a file, it will NOT call config.before(:all) causing the
|
129
|
+
# reset_between_examples stack to be mismatched, so we check, if its already empty we
|
130
|
+
# just leave.
|
131
|
+
next if HyperSpec.reset_between_examples.empty?
|
132
|
+
|
133
|
+
RSpec.configuration.reset_between_examples = HyperSpec.reset_between_examples.pop
|
134
|
+
end
|
135
|
+
config.before(:each) do |example|
|
136
|
+
insure_page_loaded(true) if example.metadata[:js] && !HyperSpec.reset_between_examples?
|
137
|
+
end
|
138
|
+
end
|
9
139
|
|
10
140
|
RSpec.configure do |config|
|
11
|
-
config.include HyperSpec::
|
141
|
+
config.include HyperSpec::Helpers
|
12
142
|
config.include HyperSpec::WaitForAjax
|
13
143
|
config.include Capybara::DSL
|
14
144
|
|
@@ -17,17 +147,21 @@ RSpec.configure do |config|
|
|
17
147
|
config.add_setting :debugger_width, default: nil
|
18
148
|
|
19
149
|
config.before(:each) do
|
20
|
-
Hyperstack
|
21
|
-
|
22
|
-
|
150
|
+
if defined?(Hyperstack)
|
151
|
+
Hyperstack.class_eval do
|
152
|
+
def self.on_server?
|
153
|
+
true
|
154
|
+
end
|
23
155
|
end
|
24
|
-
end
|
156
|
+
end
|
25
157
|
# for compatibility with HyperMesh
|
26
|
-
HyperMesh
|
27
|
-
|
28
|
-
|
158
|
+
if defined?(HyperMesh)
|
159
|
+
HyperMesh.class_eval do
|
160
|
+
def self.on_server?
|
161
|
+
true
|
162
|
+
end
|
29
163
|
end
|
30
|
-
end
|
164
|
+
end
|
31
165
|
end
|
32
166
|
|
33
167
|
config.before(:each, js: true) do
|
@@ -43,42 +177,51 @@ RSpec.configure do |config|
|
|
43
177
|
PusherFake::Channel.reset if defined? PusherFake
|
44
178
|
end
|
45
179
|
end
|
46
|
-
|
47
180
|
end
|
48
181
|
|
49
182
|
# Capybara config
|
50
|
-
RSpec.configure do |
|
183
|
+
RSpec.configure do |config|
|
184
|
+
config.before(:each) do |example|
|
185
|
+
HyperSpec::Internal::Controller.current_example = example
|
186
|
+
HyperSpec::Internal::Controller.description_displayed = false
|
187
|
+
end
|
188
|
+
|
189
|
+
config.add_setting :wait_for_initialization_time
|
190
|
+
config.wait_for_initialization_time = 3
|
191
|
+
|
51
192
|
Capybara.default_max_wait_time = 10
|
52
193
|
|
53
194
|
Capybara.register_driver :chrome do |app|
|
54
195
|
options = {}
|
55
196
|
options.merge!(
|
56
|
-
|
57
|
-
|
58
|
-
)
|
59
|
-
# this does not seem to work properly. Don't document this feature yet.
|
197
|
+
w3c: false,
|
198
|
+
args: %w[auto-open-devtools-for-tabs]
|
199
|
+
)
|
60
200
|
options['mobileEmulation'] = { 'deviceName' => ENV['DEVICE'].tr('-', ' ') } if ENV['DEVICE']
|
61
|
-
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
|
201
|
+
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
|
202
|
+
chromeOptions: options, 'goog:loggingPrefs' => { browser: 'ALL' }
|
203
|
+
)
|
62
204
|
Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities)
|
63
205
|
end
|
64
206
|
|
207
|
+
Capybara.register_driver :firefox do |app|
|
208
|
+
Capybara::Selenium::Driver.new(app, browser: :firefox)
|
209
|
+
end
|
210
|
+
|
65
211
|
Capybara.register_driver :chrome_headless_docker_travis do |app|
|
66
212
|
options = ::Selenium::WebDriver::Chrome::Options.new
|
67
213
|
options.add_argument('--headless')
|
68
214
|
options.add_argument('--no-sandbox')
|
69
215
|
options.add_argument('--disable-dev-shm-usage')
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
Capybara.register_driver :firefox do |app|
|
74
|
-
Capybara::Selenium::Driver.new(app, browser: :firefox)
|
216
|
+
Selenium::WebDriver::Chrome::Service.driver_path = '/usr/lib/chromium-browser/chromedriver'
|
217
|
+
Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
|
75
218
|
end
|
76
219
|
|
77
220
|
Capybara.register_driver :firefox_headless do |app|
|
78
221
|
options = Selenium::WebDriver::Firefox::Options.new
|
79
222
|
options.headless!
|
80
223
|
Capybara::Selenium::Driver.new(app, browser: :firefox, options: options)
|
81
|
-
end
|
224
|
+
end if defined?(Selenium::WebDriver::Firefox)
|
82
225
|
|
83
226
|
Capybara.register_driver :selenium_with_firebug do |app|
|
84
227
|
profile = Selenium::WebDriver::Firefox::Profile.new
|
@@ -86,7 +229,7 @@ RSpec.configure do |_config|
|
|
86
229
|
profile.enable_firebug
|
87
230
|
options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
|
88
231
|
Capybara::Selenium::Driver.new(app, browser: :firefox, options: options)
|
89
|
-
end
|
232
|
+
end if defined?(Selenium::WebDriver::Firefox)
|
90
233
|
|
91
234
|
Capybara.register_driver :safari do |app|
|
92
235
|
Capybara::Selenium::Driver.new(app, browser: :safari)
|
@@ -103,5 +246,4 @@ RSpec.configure do |_config|
|
|
103
246
|
when 'travis' then :chrome_headless_docker_travis
|
104
247
|
else :selenium_chrome_headless
|
105
248
|
end
|
106
|
-
|
107
249
|
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
|