hyper-spec 0.99.6 → 1.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +5 -3
- data/Gemfile.lock +55 -39
- data/hyper-spec.gemspec +3 -3
- data/lib/hyper-spec.rb +2 -2
- data/lib/hyper-spec/component_test_helpers.rb +9 -7
- data/lib/hyper-spec/unparser_patch.rb +10 -0
- data/lib/hyper-spec/version.rb +1 -1
- data/lib/hyper-spec/wait_for_ajax.rb +3 -3
- data/lib/sources/top_level_rails_component.rb +103 -0
- metadata +18 -17
- data/README.md +0 -380
- data/lib/react/top_level_rails_component.rb +0 -94
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 523c4494f6f9732ca638af2a5a23032de81f96bcf5a33a39486ed974383af29d
|
4
|
+
data.tar.gz: ac17621809222fefefb33f9d94223356355d3f359810cd9786d5fe9530d69a24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ebb2bd81b35cc40fcdcc97c24c2365f2e98642523c700d708f56bdbe9cffad5c77202cac4513d4148db30c02a3d28fc170bdff11eb2c077442d08fda4bacede
|
7
|
+
data.tar.gz: aeba618aedf112659516f2130f1cd5be18fa840b2ca066114a9f8e7956e5ee16047ce3a21a3369c8d7cdf7461d787138b0c7fb5cb43a3c48ef1435aaa6520ec7
|
data/Gemfile
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
|
-
gem 'hyper-component',
|
3
|
-
gem 'hyper-store',
|
4
|
-
gem '
|
2
|
+
gem 'hyper-component', path: '../hyper-component'
|
3
|
+
gem 'hyper-store', path: '../hyper-store'
|
4
|
+
gem 'hyper-state', path: '../hyper-state'
|
5
|
+
gem 'hyperstack-config', path: '../hyperstack-config'
|
6
|
+
#gem 'unparser', path: '../../../unparser'
|
5
7
|
gemspec
|
data/Gemfile.lock
CHANGED
@@ -1,41 +1,51 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ../hyper-component
|
3
3
|
specs:
|
4
|
-
hyper-component (0.
|
5
|
-
hyper-
|
6
|
-
|
7
|
-
libv8 (~> 6.
|
8
|
-
mini_racer (~> 0.
|
4
|
+
hyper-component (0.1)
|
5
|
+
hyper-state (= 0.1)
|
6
|
+
hyperstack-config (= 0.1)
|
7
|
+
libv8 (~> 6.3.0)
|
8
|
+
mini_racer (~> 0.1.15)
|
9
9
|
opal (>= 0.11.0, < 0.12.0)
|
10
10
|
opal-activesupport (~> 0.3.1)
|
11
11
|
react-rails (>= 2.4.0, < 2.5.0)
|
12
12
|
|
13
|
+
PATH
|
14
|
+
remote: ../hyper-state
|
15
|
+
specs:
|
16
|
+
hyper-state (0.1)
|
17
|
+
hyperstack-config (= 0.1)
|
18
|
+
opal (>= 0.11.0, < 0.12.0)
|
19
|
+
|
13
20
|
PATH
|
14
21
|
remote: ../hyper-store
|
15
22
|
specs:
|
16
|
-
hyper-store (0.
|
17
|
-
|
23
|
+
hyper-store (0.1)
|
24
|
+
hyper-state (= 0.1)
|
25
|
+
hyperstack-config (= 0.1)
|
18
26
|
opal (>= 0.11.0, < 0.12.0)
|
19
27
|
|
20
28
|
PATH
|
21
|
-
remote: ../
|
29
|
+
remote: ../hyperstack-config
|
22
30
|
specs:
|
23
|
-
|
24
|
-
libv8 (~> 6.
|
25
|
-
|
31
|
+
hyperstack-config (0.1)
|
32
|
+
libv8 (~> 6.3.0)
|
33
|
+
listen (~> 3.0)
|
34
|
+
mini_racer (~> 0.1.15)
|
26
35
|
opal (>= 0.11.0, < 0.12.0)
|
27
36
|
opal-browser (~> 0.2.0)
|
28
37
|
uglifier
|
38
|
+
websocket
|
29
39
|
|
30
40
|
PATH
|
31
41
|
remote: .
|
32
42
|
specs:
|
33
|
-
hyper-spec (0.
|
43
|
+
hyper-spec (0.1)
|
34
44
|
capybara
|
35
45
|
chromedriver-helper (= 1.2.0)
|
36
|
-
libv8 (~> 6.
|
46
|
+
libv8 (~> 6.3.0)
|
37
47
|
method_source
|
38
|
-
mini_racer (~> 0.
|
48
|
+
mini_racer (~> 0.1.15)
|
39
49
|
opal (>= 0.11.0, < 0.12.0)
|
40
50
|
parser (>= 2.3.3.1)
|
41
51
|
pry
|
@@ -43,7 +53,7 @@ PATH
|
|
43
53
|
selenium-webdriver
|
44
54
|
timecop (~> 0.8.1)
|
45
55
|
uglifier
|
46
|
-
unparser
|
56
|
+
unparser
|
47
57
|
webdrivers
|
48
58
|
|
49
59
|
GEM
|
@@ -94,7 +104,7 @@ GEM
|
|
94
104
|
adamantium (0.2.0)
|
95
105
|
ice_nine (~> 0.11.0)
|
96
106
|
memoizable (~> 0.4.0)
|
97
|
-
addressable (2.
|
107
|
+
addressable (2.5.2)
|
98
108
|
public_suffix (>= 2.0.2, < 4.0)
|
99
109
|
archive-zip (0.11.0)
|
100
110
|
io-like (~> 0.3.0)
|
@@ -105,14 +115,13 @@ GEM
|
|
105
115
|
babel-source (>= 4.0, < 6)
|
106
116
|
execjs (~> 2.0)
|
107
117
|
builder (3.2.3)
|
108
|
-
capybara (3.
|
118
|
+
capybara (3.9.0)
|
109
119
|
addressable
|
110
120
|
mini_mime (>= 0.1.3)
|
111
121
|
nokogiri (~> 1.8)
|
112
122
|
rack (>= 1.6.0)
|
113
123
|
rack-test (>= 0.6.3)
|
114
|
-
|
115
|
-
xpath (~> 3.2)
|
124
|
+
xpath (~> 3.1)
|
116
125
|
childprocess (0.9.0)
|
117
126
|
ffi (~> 1.0, >= 1.0.11)
|
118
127
|
chromedriver-helper (1.2.0)
|
@@ -129,11 +138,11 @@ GEM
|
|
129
138
|
equalizer (0.0.11)
|
130
139
|
erubi (1.7.1)
|
131
140
|
execjs (2.7.0)
|
132
|
-
ffi (1.
|
141
|
+
ffi (1.9.25)
|
133
142
|
globalid (0.4.1)
|
134
143
|
activesupport (>= 4.2.0)
|
135
144
|
hike (1.2.3)
|
136
|
-
i18n (1.1.
|
145
|
+
i18n (1.1.1)
|
137
146
|
concurrent-ruby (~> 1.0)
|
138
147
|
ice_nine (0.11.2)
|
139
148
|
interception (0.5)
|
@@ -142,13 +151,17 @@ GEM
|
|
142
151
|
rails-dom-testing (>= 1, < 3)
|
143
152
|
railties (>= 4.2.0)
|
144
153
|
thor (>= 0.14, < 2.0)
|
145
|
-
libv8 (6.
|
154
|
+
libv8 (6.3.292.48.1)
|
155
|
+
listen (3.1.5)
|
156
|
+
rb-fsevent (~> 0.9, >= 0.9.4)
|
157
|
+
rb-inotify (~> 0.9, >= 0.9.7)
|
158
|
+
ruby_dep (~> 1.2)
|
146
159
|
loofah (2.2.2)
|
147
160
|
crass (~> 1.0.2)
|
148
161
|
nokogiri (>= 1.5.9)
|
149
|
-
mail (2.7.
|
162
|
+
mail (2.7.1)
|
150
163
|
mini_mime (>= 0.1.1)
|
151
|
-
marcel (0.3.
|
164
|
+
marcel (0.3.3)
|
152
165
|
mimemagic (~> 0.3.2)
|
153
166
|
memoizable (0.4.2)
|
154
167
|
thread_safe (~> 0.3, >= 0.3.1)
|
@@ -156,12 +169,11 @@ GEM
|
|
156
169
|
mimemagic (0.3.2)
|
157
170
|
mini_mime (1.0.1)
|
158
171
|
mini_portile2 (2.3.0)
|
159
|
-
mini_racer (0.
|
160
|
-
libv8 (
|
172
|
+
mini_racer (0.1.15)
|
173
|
+
libv8 (~> 6.3)
|
161
174
|
minitest (5.11.3)
|
162
|
-
net_http_ssl_fix (0.0.10)
|
163
175
|
nio4r (2.3.1)
|
164
|
-
nokogiri (1.8.
|
176
|
+
nokogiri (1.8.5)
|
165
177
|
mini_portile2 (~> 2.3.0)
|
166
178
|
opal (0.11.3)
|
167
179
|
ast (>= 2.3.0)
|
@@ -200,7 +212,7 @@ GEM
|
|
200
212
|
interception (>= 0.5)
|
201
213
|
pry
|
202
214
|
public_suffix (3.0.3)
|
203
|
-
puma (3.
|
215
|
+
puma (3.12.0)
|
204
216
|
rack (2.0.5)
|
205
217
|
rack-test (1.1.0)
|
206
218
|
rack (>= 1.0, < 3)
|
@@ -231,13 +243,15 @@ GEM
|
|
231
243
|
rainbow (2.2.2)
|
232
244
|
rake
|
233
245
|
rake (12.3.1)
|
246
|
+
rb-fsevent (0.10.3)
|
247
|
+
rb-inotify (0.9.10)
|
248
|
+
ffi (>= 0.5.0, < 2)
|
234
249
|
react-rails (2.4.7)
|
235
250
|
babel-transpiler (>= 0.7.0)
|
236
251
|
connection_pool
|
237
252
|
execjs
|
238
253
|
railties (>= 3.2)
|
239
254
|
tilt
|
240
|
-
regexp_parser (1.3.0)
|
241
255
|
rspec (3.8.0)
|
242
256
|
rspec-core (~> 3.8.0)
|
243
257
|
rspec-expectations (~> 3.8.0)
|
@@ -246,7 +260,7 @@ GEM
|
|
246
260
|
rspec-expectations (>= 2.99.0.beta1)
|
247
261
|
rspec-core (3.8.0)
|
248
262
|
rspec-support (~> 3.8.0)
|
249
|
-
rspec-expectations (3.8.
|
263
|
+
rspec-expectations (3.8.2)
|
250
264
|
diff-lcs (>= 1.2.0, < 2.0)
|
251
265
|
rspec-support (~> 3.8.0)
|
252
266
|
rspec-its (1.2.0)
|
@@ -255,7 +269,7 @@ GEM
|
|
255
269
|
rspec-mocks (3.8.0)
|
256
270
|
diff-lcs (>= 1.2.0, < 2.0)
|
257
271
|
rspec-support (~> 3.8.0)
|
258
|
-
rspec-rails (3.8.
|
272
|
+
rspec-rails (3.8.1)
|
259
273
|
actionpack (>= 3.0)
|
260
274
|
activesupport (>= 3.0)
|
261
275
|
railties (>= 3.0)
|
@@ -274,8 +288,9 @@ GEM
|
|
274
288
|
ruby-progressbar (~> 1.7)
|
275
289
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
276
290
|
ruby-progressbar (1.10.0)
|
291
|
+
ruby_dep (1.5.0)
|
277
292
|
rubyzip (1.2.2)
|
278
|
-
selenium-webdriver (3.
|
293
|
+
selenium-webdriver (3.14.1)
|
279
294
|
childprocess (~> 0.5)
|
280
295
|
rubyzip (~> 1.2, >= 1.2.2)
|
281
296
|
shoulda (3.6.0)
|
@@ -302,10 +317,10 @@ GEM
|
|
302
317
|
timecop (0.8.1)
|
303
318
|
tzinfo (1.2.5)
|
304
319
|
thread_safe (~> 0.1)
|
305
|
-
uglifier (4.1.
|
320
|
+
uglifier (4.1.19)
|
306
321
|
execjs (>= 0.3.0, < 3)
|
307
322
|
unicode-display_width (1.4.0)
|
308
|
-
unparser (0.
|
323
|
+
unparser (0.2.8)
|
309
324
|
abstract_type (~> 0.0.7)
|
310
325
|
adamantium (~> 0.2.0)
|
311
326
|
concord (~> 0.1.5)
|
@@ -313,11 +328,11 @@ GEM
|
|
313
328
|
equalizer (~> 0.0.9)
|
314
329
|
parser (>= 2.3.1.2, < 2.6)
|
315
330
|
procto (~> 0.0.2)
|
316
|
-
webdrivers (3.
|
317
|
-
net_http_ssl_fix
|
331
|
+
webdrivers (3.4.3)
|
318
332
|
nokogiri (~> 1.6)
|
319
333
|
rubyzip (~> 1.0)
|
320
334
|
selenium-webdriver (~> 3.0)
|
335
|
+
websocket (1.2.8)
|
321
336
|
websocket-driver (0.7.0)
|
322
337
|
websocket-extensions (>= 0.1.0)
|
323
338
|
websocket-extensions (0.1.3)
|
@@ -331,8 +346,9 @@ DEPENDENCIES
|
|
331
346
|
bundler
|
332
347
|
hyper-component!
|
333
348
|
hyper-spec!
|
349
|
+
hyper-state!
|
334
350
|
hyper-store!
|
335
|
-
|
351
|
+
hyperstack-config!
|
336
352
|
opal-browser (~> 0.2.0)
|
337
353
|
opal-rails (~> 0.9.4)
|
338
354
|
pry-rescue
|
@@ -351,4 +367,4 @@ DEPENDENCIES
|
|
351
367
|
spring-commands-rspec
|
352
368
|
|
353
369
|
BUNDLED WITH
|
354
|
-
1.
|
370
|
+
1.16.1
|
data/hyper-spec.gemspec
CHANGED
@@ -26,9 +26,9 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
|
26
26
|
|
27
27
|
spec.add_dependency 'capybara'
|
28
28
|
spec.add_dependency 'chromedriver-helper', '1.2.0'
|
29
|
-
spec.add_dependency 'libv8', '~> 6.
|
29
|
+
spec.add_dependency 'libv8', '~> 6.3.0' # see https://github.com/discourse/mini_racer/issues/92
|
30
30
|
spec.add_dependency 'method_source'
|
31
|
-
spec.add_dependency 'mini_racer', '~> 0.
|
31
|
+
spec.add_dependency 'mini_racer', '~> 0.1.15'
|
32
32
|
spec.add_dependency 'opal', '>= 0.11.0', '< 0.12.0'
|
33
33
|
spec.add_dependency 'parser', '>= 2.3.3.1'
|
34
34
|
spec.add_dependency 'pry'
|
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
|
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'
|
39
|
+
spec.add_dependency 'unparser'
|
40
40
|
spec.add_dependency 'webdrivers'
|
41
41
|
|
42
42
|
spec.add_development_dependency 'bundler'
|
data/lib/hyper-spec.rb
CHANGED
@@ -17,11 +17,11 @@ RSpec.configure do |config|
|
|
17
17
|
config.add_setting :debugger_width, default: nil
|
18
18
|
|
19
19
|
config.before(:each) do
|
20
|
-
|
20
|
+
Hyperstack.class_eval do
|
21
21
|
def self.on_server?
|
22
22
|
true
|
23
23
|
end
|
24
|
-
end if defined?(
|
24
|
+
end if defined?(Hyperstack)
|
25
25
|
# for compatibility with HyperMesh
|
26
26
|
HyperMesh.class_eval do
|
27
27
|
def self.on_server?
|
@@ -1,13 +1,14 @@
|
|
1
1
|
# see component_test_helpers_spec.rb for examples
|
2
2
|
require 'parser/current'
|
3
3
|
require 'unparser'
|
4
|
+
require 'hyper-spec/unparser_patch'
|
4
5
|
require 'method_source'
|
5
6
|
require_relative '../../lib/hyper-spec/time_cop.rb'
|
6
7
|
|
7
8
|
module HyperSpec
|
8
9
|
module ComponentTestHelpers
|
9
10
|
TOP_LEVEL_COMPONENT_PATCH =
|
10
|
-
Opal.compile(File.read(File.expand_path('../../
|
11
|
+
Opal.compile(File.read(File.expand_path('../../sources/top_level_rails_component.rb', __FILE__)))
|
11
12
|
TIME_COP_CLIENT_PATCH =
|
12
13
|
Opal.compile(File.read(File.expand_path('../../hyper-spec/time_cop.rb', __FILE__))) +
|
13
14
|
"\n#{File.read(File.expand_path('../../sources/lolex.js', __FILE__))}"
|
@@ -24,11 +25,11 @@ module HyperSpec
|
|
24
25
|
|
25
26
|
def build_test_url_for(controller)
|
26
27
|
unless controller
|
27
|
-
unless defined?(::
|
28
|
-
Object.const_set('
|
28
|
+
unless defined?(::HyperstackTestController)
|
29
|
+
Object.const_set('HyperstackTestController', Class.new(::ActionController::Base))
|
29
30
|
end
|
30
31
|
|
31
|
-
controller = ::
|
32
|
+
controller = ::HyperstackTestController
|
32
33
|
end
|
33
34
|
|
34
35
|
route_root = controller.name.gsub(/Controller$/, '').underscore
|
@@ -216,7 +217,8 @@ module HyperSpec
|
|
216
217
|
}
|
217
218
|
end
|
218
219
|
end
|
219
|
-
class
|
220
|
+
class Hyperstack::Internal::Component::TestDummy
|
221
|
+
include Hyperstack::Component
|
220
222
|
def render; end
|
221
223
|
end
|
222
224
|
#{@client_code}
|
@@ -225,7 +227,7 @@ module HyperSpec
|
|
225
227
|
opts[:code] = Opal.compile(block_with_helpers)
|
226
228
|
end
|
227
229
|
|
228
|
-
component_name ||= '
|
230
|
+
component_name ||= 'Hyperstack::Internal::Component::TestDummy'
|
229
231
|
::Rails.cache.write(test_url, [component_name, params, opts])
|
230
232
|
test_code_key = "hyper_spec_prerender_test_code.js"
|
231
233
|
@@original_server_render_files ||= ::Rails.configuration.react.server_renderer_options[:files]
|
@@ -249,7 +251,7 @@ module HyperSpec
|
|
249
251
|
[:callback_history_for, :last_callback_for, :clear_callback_history_for,
|
250
252
|
:event_history_for, :last_event_for, :clear_event_history_for].each do |method|
|
251
253
|
define_method(method) do |event_name|
|
252
|
-
evaluate_ruby("
|
254
|
+
evaluate_ruby("Hyperstack::Internal::Component::TopLevelRailsComponent.#{method}('#{event_name}')")
|
253
255
|
end
|
254
256
|
end
|
255
257
|
|
data/lib/hyper-spec/version.rb
CHANGED
@@ -12,9 +12,9 @@ module HyperSpec
|
|
12
12
|
def running?
|
13
13
|
jscode = <<-CODE
|
14
14
|
(function() {
|
15
|
-
if (typeof Opal !== "undefined" && Opal.
|
15
|
+
if (typeof Opal !== "undefined" && Opal.Hyperstack !== undefined) {
|
16
16
|
try {
|
17
|
-
return Opal.
|
17
|
+
return Opal.Hyperstack.$const_get("HTTP")["$active?"]();
|
18
18
|
} catch(err) {
|
19
19
|
if (typeof jQuery !== "undefined" && jQuery.active !== undefined) {
|
20
20
|
return (jQuery.active > 0);
|
@@ -39,7 +39,7 @@ module HyperSpec
|
|
39
39
|
rescue Capybara::NotSupportedByDriverError
|
40
40
|
true
|
41
41
|
rescue Exception => e
|
42
|
-
e.message == 'either jQuery or
|
42
|
+
e.message == 'either jQuery or Hyperstack::HTTP is not defined'
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Hyperstack
|
2
|
+
module Internal
|
3
|
+
module Component
|
4
|
+
class TopLevelRailsComponent
|
5
|
+
|
6
|
+
# original class declares these params:
|
7
|
+
# param :component_name
|
8
|
+
# param :controller
|
9
|
+
# param :render_params
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :event_history
|
13
|
+
|
14
|
+
def callback_history_for(proc_name)
|
15
|
+
event_history[proc_name]
|
16
|
+
end
|
17
|
+
|
18
|
+
def last_callback_for(proc_name)
|
19
|
+
event_history[proc_name].last
|
20
|
+
end
|
21
|
+
|
22
|
+
def clear_callback_history_for(proc_name)
|
23
|
+
event_history[proc_name] = []
|
24
|
+
end
|
25
|
+
|
26
|
+
def event_history_for(event_name)
|
27
|
+
event_history["on_#{event_name}"]
|
28
|
+
end
|
29
|
+
|
30
|
+
def last_event_for(event_name)
|
31
|
+
event_history["on_#{event_name}"].last
|
32
|
+
end
|
33
|
+
|
34
|
+
def clear_event_history_for(event_name)
|
35
|
+
event_history["on_#{event_name}"] = []
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def component
|
40
|
+
return @component if @component
|
41
|
+
paths_searched = []
|
42
|
+
component = nil
|
43
|
+
if @ComponentName.start_with?('::')
|
44
|
+
# if absolute path of component is given, look it up and fail if not found
|
45
|
+
paths_searched << @ComponentName
|
46
|
+
component = begin
|
47
|
+
Object.const_get(@ComponentName)
|
48
|
+
rescue NameError
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
else
|
52
|
+
# if relative path is given, look it up like this
|
53
|
+
# 1) we check each path + controller-name + component-name
|
54
|
+
# 2) if we can't find it there we check each path + component-name
|
55
|
+
# if we can't find it we just try const_get
|
56
|
+
# so (assuming controller name is Home)
|
57
|
+
# ::Foo::Bar will only resolve to some component named ::Foo::Bar
|
58
|
+
# but Foo::Bar will check (in this order) ::Home::Foo::Bar, ::Components::Home::Foo::Bar, ::Foo::Bar, ::Components::Foo::Bar
|
59
|
+
self.class.search_path.each do |scope|
|
60
|
+
paths_searched << "#{scope.name}::#{@Controller}::#{@ComponentName}"
|
61
|
+
component = begin
|
62
|
+
scope.const_get(@Controller, false).const_get(@ComponentName, false)
|
63
|
+
rescue NameError
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
break if component != nil
|
67
|
+
end
|
68
|
+
unless component
|
69
|
+
self.class.search_path.each do |scope|
|
70
|
+
paths_searched << "#{scope.name}::#{@ComponentName}"
|
71
|
+
component = begin
|
72
|
+
scope.const_get(@ComponentName, false)
|
73
|
+
rescue NameError
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
break if component != nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
@component = component
|
81
|
+
return @component if @component && @component.method_defined?(:render)
|
82
|
+
raise "Could not find component class '#{@ComponentName}' for @Controller '#{@Controller}' in any component directory. Tried [#{paths_searched.join(", ")}]"
|
83
|
+
end
|
84
|
+
|
85
|
+
before_mount do
|
86
|
+
TopLevelRailsComponent.event_history = Hash.new { |h, k| h[k] = [] }
|
87
|
+
component.validator.rules.each do |name, rules|
|
88
|
+
next unless rules[:type] == Proc
|
89
|
+
|
90
|
+
TopLevelRailsComponent.event_history[name] = []
|
91
|
+
@RenderParams[name] = lambda do |*args|
|
92
|
+
TopLevelRailsComponent.event_history[name] << args
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def render
|
98
|
+
Hyperstack::Internal::Component::RenderingContext.render(component, @RenderParams)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyper-spec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.alpha1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mitch VanDuyn
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2018-11-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: capybara
|
@@ -46,14 +46,14 @@ dependencies:
|
|
46
46
|
requirements:
|
47
47
|
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 6.
|
49
|
+
version: 6.3.0
|
50
50
|
type: :runtime
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
54
|
- - "~>"
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: 6.
|
56
|
+
version: 6.3.0
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
58
|
name: method_source
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
@@ -74,14 +74,14 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - "~>"
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 0.
|
77
|
+
version: 0.1.15
|
78
78
|
type: :runtime
|
79
79
|
prerelease: false
|
80
80
|
version_requirements: !ruby/object:Gem::Requirement
|
81
81
|
requirements:
|
82
82
|
- - "~>"
|
83
83
|
- !ruby/object:Gem::Version
|
84
|
-
version: 0.
|
84
|
+
version: 0.1.15
|
85
85
|
- !ruby/object:Gem::Dependency
|
86
86
|
name: opal
|
87
87
|
requirement: !ruby/object:Gem::Requirement
|
@@ -190,16 +190,16 @@ dependencies:
|
|
190
190
|
name: unparser
|
191
191
|
requirement: !ruby/object:Gem::Requirement
|
192
192
|
requirements:
|
193
|
-
- - "
|
193
|
+
- - ">="
|
194
194
|
- !ruby/object:Gem::Version
|
195
|
-
version: 0
|
195
|
+
version: '0'
|
196
196
|
type: :runtime
|
197
197
|
prerelease: false
|
198
198
|
version_requirements: !ruby/object:Gem::Requirement
|
199
199
|
requirements:
|
200
|
-
- - "
|
200
|
+
- - ">="
|
201
201
|
- !ruby/object:Gem::Version
|
202
|
-
version: 0
|
202
|
+
version: '0'
|
203
203
|
- !ruby/object:Gem::Dependency
|
204
204
|
name: webdrivers
|
205
205
|
requirement: !ruby/object:Gem::Requirement
|
@@ -234,14 +234,14 @@ dependencies:
|
|
234
234
|
requirements:
|
235
235
|
- - '='
|
236
236
|
- !ruby/object:Gem::Version
|
237
|
-
version: 0.
|
237
|
+
version: 1.0.alpha1
|
238
238
|
type: :development
|
239
239
|
prerelease: false
|
240
240
|
version_requirements: !ruby/object:Gem::Requirement
|
241
241
|
requirements:
|
242
242
|
- - '='
|
243
243
|
- !ruby/object:Gem::Version
|
244
|
-
version: 0.
|
244
|
+
version: 1.0.alpha1
|
245
245
|
- !ruby/object:Gem::Dependency
|
246
246
|
name: opal-browser
|
247
247
|
requirement: !ruby/object:Gem::Requirement
|
@@ -486,7 +486,6 @@ files:
|
|
486
486
|
- ".travis.yml"
|
487
487
|
- Gemfile
|
488
488
|
- Gemfile.lock
|
489
|
-
- README.md
|
490
489
|
- Rakefile
|
491
490
|
- bin/console
|
492
491
|
- bin/setup
|
@@ -496,11 +495,12 @@ files:
|
|
496
495
|
- lib/hyper-spec.rb
|
497
496
|
- lib/hyper-spec/component_test_helpers.rb
|
498
497
|
- lib/hyper-spec/time_cop.rb
|
498
|
+
- lib/hyper-spec/unparser_patch.rb
|
499
499
|
- lib/hyper-spec/version.rb
|
500
500
|
- lib/hyper-spec/wait_for_ajax.rb
|
501
|
-
- lib/react/top_level_rails_component.rb
|
502
501
|
- lib/selenium/web_driver/firefox/profile.rb
|
503
502
|
- lib/sources/lolex.js
|
503
|
+
- lib/sources/top_level_rails_component.rb
|
504
504
|
homepage: http://ruby-hyperloop.org
|
505
505
|
licenses:
|
506
506
|
- MIT
|
@@ -516,11 +516,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
516
516
|
version: '0'
|
517
517
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
518
518
|
requirements:
|
519
|
-
- - "
|
519
|
+
- - ">"
|
520
520
|
- !ruby/object:Gem::Version
|
521
|
-
version:
|
521
|
+
version: 1.3.1
|
522
522
|
requirements: []
|
523
|
-
|
523
|
+
rubyforge_project:
|
524
|
+
rubygems_version: 2.7.8
|
524
525
|
signing_key:
|
525
526
|
specification_version: 4
|
526
527
|
summary: Drive your Hyperloop client and server specs from RSpec and Capybara
|
data/README.md
DELETED
@@ -1,380 +0,0 @@
|
|
1
|
-
# HyperSpec
|
2
|
-
|
3
|
-
[![Build Status](https://travis-ci.org/ruby-hyperloop/hyper-spec.svg?branch=master)](https://travis-ci.org/ruby-hyperloop/hyper-spec)
|
4
|
-
|
5
|
-
With HyperSpec you can run *isomorphic* specs for all your Hyperloop code using RSpec. Everything runs as standard RSpec test specs.
|
6
|
-
|
7
|
-
For example if you have a component like this:
|
8
|
-
|
9
|
-
```ruby
|
10
|
-
class SayHello < React::Component::Base
|
11
|
-
param :name
|
12
|
-
render(DIV) do
|
13
|
-
"Hello there #{params.name}"
|
14
|
-
end
|
15
|
-
end
|
16
|
-
```
|
17
|
-
|
18
|
-
Your test spec would look like this:
|
19
|
-
|
20
|
-
```ruby
|
21
|
-
describe 'SayHello', js: true do
|
22
|
-
it 'has the correct content' do
|
23
|
-
mount "SayHello", name: 'Fred'
|
24
|
-
expect(page).to have_content('Hello there Fred')
|
25
|
-
end
|
26
|
-
end
|
27
|
-
```
|
28
|
-
|
29
|
-
The `mount` method will setup a blank client window, and *mount* the named component in the window, passing any parameters.
|
30
|
-
|
31
|
-
Notice that the spec will need a client environment so we must set `js: true`.
|
32
|
-
|
33
|
-
The `mount` method can also take a block which will be recompiled and set to the client before mounting the component. You can place any client side code in the mount block including the definition of components.
|
34
|
-
|
35
|
-
```ruby
|
36
|
-
describe "the mount's code block", js: true do
|
37
|
-
it 'will be recompiled on the client' do
|
38
|
-
mount 'ShowOff' do
|
39
|
-
class ShowOff < React::Component::Base
|
40
|
-
render(DIV) { 'Now how cool is that???' }
|
41
|
-
end
|
42
|
-
end
|
43
|
-
expect(page).to have_content('Now how cool is that???' )
|
44
|
-
end
|
45
|
-
end
|
46
|
-
```
|
47
|
-
|
48
|
-
## Why?
|
49
|
-
|
50
|
-
Hyperloop wants to make the server-client divide as transparent to the developer as practical. Given this, it makes sense that the testing should also be done with as little concern for client versus server.
|
51
|
-
|
52
|
-
HyperSpec allows you to directly use tools like FactoryBot (or Hyperloop Operations) to setup some test data, then run a spec to make sure that a component correctly displays, or modifies that data. You can use Timecop to manipulate time and keep in sync between the server and client. This makes testing easier and more realistic without writing a lot of redundant code.
|
53
|
-
|
54
|
-
|
55
|
-
## Installation
|
56
|
-
|
57
|
-
Add this line to your application's Gemfile in the test section:
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
gem 'hyper-spec'
|
61
|
-
```
|
62
|
-
|
63
|
-
Execute:
|
64
|
-
|
65
|
-
$ bundle install
|
66
|
-
|
67
|
-
and then in your spec_helper.rb file
|
68
|
-
|
69
|
-
```ruby
|
70
|
-
require 'hyper-spec'
|
71
|
-
```
|
72
|
-
|
73
|
-
You will also need to install selenium, poltergeist and firefox version **46.0.1** (ff latest still does not play well with selenium).
|
74
|
-
|
75
|
-
Sadly at this time the selenium chrome driver does not play nicely with Opal, so you can't use Chrome. We are working on getting rid of the whole selenium business. Stay tuned.
|
76
|
-
|
77
|
-
## Environment Variables
|
78
|
-
|
79
|
-
You can set `DRIVER` to `ff` to run the client in Firefox and see what is going on. By default tests will run in poltergeist which is quicker, but harder to debug problems.
|
80
|
-
|
81
|
-
```
|
82
|
-
DRIVER=ff bundle exec rspec
|
83
|
-
```
|
84
|
-
|
85
|
-
## Spec Helpers
|
86
|
-
|
87
|
-
HyperSpec adds the following spec helpers to your test environment
|
88
|
-
|
89
|
-
+ `mount`
|
90
|
-
+ `client_option` and `client_options`
|
91
|
-
+ `on_client`
|
92
|
-
+ `isomorphic`
|
93
|
-
+ `evaluate_ruby`
|
94
|
-
+ `expect_evaluate_ruby`
|
95
|
-
+ `expect_promise`
|
96
|
-
+ call back and event history methods
|
97
|
-
+ `pause`
|
98
|
-
+ `attributes_on_client`
|
99
|
-
+ `size_window`
|
100
|
-
+ `add_class`
|
101
|
-
|
102
|
-
#### The `mount` Method
|
103
|
-
|
104
|
-
`mount` takes the name of a component, prepares an empty test window, and mounts the named component in the window.
|
105
|
-
You may give a block to `mount` which will be recompiled on the client, and run *before* mounting. This means that the component
|
106
|
-
mounted may be actually defined in the block, which is useful for setting up top level wrapper components, which will invoke your component under test. You can also modify existing components for white box testing, or local fixture data, constants, etc.
|
107
|
-
|
108
|
-
`mount` may also be given a hash of the parameters to be passed to the component.
|
109
|
-
|
110
|
-
```ruby
|
111
|
-
mount 'Display', test: 123 do
|
112
|
-
class Display < React::Component::Base
|
113
|
-
param :test
|
114
|
-
render(DIV) { params.test.to_s }
|
115
|
-
end
|
116
|
-
end
|
117
|
-
```
|
118
|
-
|
119
|
-
#### The `client_option` Method
|
120
|
-
|
121
|
-
There are several options that control the mounting process. Use `client_option` (or `client_options`) before accessing any client side to set any of these options:
|
122
|
-
|
123
|
-
+ `render_on`: `:server_only`, `:client_only`, or `:both`, default is client_only.
|
124
|
-
+ `layout`: specify the layout to be used. Default is :none.
|
125
|
-
+ `style_sheet`: specify the name of the style sheet to be loaded. Defaults to the application stylesheet.
|
126
|
-
+ `javascript`: specify the name of the javascript asset file to be loaded. Defaults to the application js file.
|
127
|
-
|
128
|
-
For example:
|
129
|
-
|
130
|
-
```ruby
|
131
|
-
it "can be rendered server side only" do
|
132
|
-
client_option render_on: :server_only
|
133
|
-
mount 'SayHello', name: 'George'
|
134
|
-
expect(page).to have_content('Hello there George')
|
135
|
-
# Server only means no code is downloaded to the client
|
136
|
-
expect(evaluate_script('typeof React')).to eq('undefined')
|
137
|
-
end
|
138
|
-
```
|
139
|
-
|
140
|
-
If you need to pull in alternative style sheets and javascript files, the recommended way to do this is to
|
141
|
-
|
142
|
-
1. Add them to a `specs/assets/stylesheets` and `specs/assets/javascripts` directory and
|
143
|
-
2. Add the following line to your `config/environment/test.rb` file:
|
144
|
-
```ruby
|
145
|
-
config.assets.paths << ::Rails.root.join('spec', 'assets', 'stylesheets').to_s
|
146
|
-
config.assets.paths << ::Rails.root.join('spec', 'assets', 'javascripts').to_s
|
147
|
-
```
|
148
|
-
|
149
|
-
This way you will not pollute your application with these 'test only' files.
|
150
|
-
|
151
|
-
*The javascript spec asset files can be `.rb` files and contain ruby code as well. See the specs for examples!*
|
152
|
-
|
153
|
-
#### The `on_client` Method
|
154
|
-
|
155
|
-
`on_client` takes a block and compiles and runs it on the client. This is useful in setting up test constants and client only fixtures.
|
156
|
-
|
157
|
-
Note that `on_client` needs to *proceed* any calls to `mount`, `evaluate_ruby`, `expect_evaluate_ruby` or `expect_promise` as these methods will initiate the client load process.
|
158
|
-
|
159
|
-
#### The `isomorphic` Method
|
160
|
-
|
161
|
-
Similar to `on_client` but the block is *also* run on the server. This is useful for setting constants shared by both client and server, and modifying behavior of isomorphic classes such as ActiveRecord models, and HyperOperations.
|
162
|
-
|
163
|
-
```ruby
|
164
|
-
isomorphic do
|
165
|
-
class SomeModel < ActiveRecord::Base
|
166
|
-
def fake_attribute
|
167
|
-
12
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
```
|
172
|
-
|
173
|
-
#### The `evaluate_ruby` Method
|
174
|
-
|
175
|
-
Takes either a string or a block, dynamically compiles it, downloads it to the client and runs it.
|
176
|
-
|
177
|
-
```ruby
|
178
|
-
evaluate_ruby do
|
179
|
-
i = 12
|
180
|
-
i * 2
|
181
|
-
end
|
182
|
-
# returns 24
|
183
|
-
|
184
|
-
isomorphic do
|
185
|
-
def factorial(n)
|
186
|
-
n == 1 ? 1 : n * factorial(n-1)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
expect(evaluate_ruby("factorial(5)")).to eq(factorial(5))
|
191
|
-
```
|
192
|
-
|
193
|
-
`evaluate_ruby` can also be very useful for debug. Set a breakpoint in your test, then use `evaluate_ruby` to interrogate the state of the client.
|
194
|
-
|
195
|
-
#### The `expect_evaluate_ruby` Method
|
196
|
-
|
197
|
-
Combines expect and evaluate methods:
|
198
|
-
|
199
|
-
```ruby
|
200
|
-
expect_evaluate_ruby do
|
201
|
-
i = 1
|
202
|
-
5.times { |n| i = i*n }
|
203
|
-
i
|
204
|
-
end.to eq(120)
|
205
|
-
```
|
206
|
-
|
207
|
-
#### The `expect_promise` Method
|
208
|
-
|
209
|
-
Works like `expect_evaluate_ruby` but is used with promises. `expect_promise` will hang until the promise resolves and then return to the results.
|
210
|
-
|
211
|
-
```ruby
|
212
|
-
expect_promise do
|
213
|
-
Promise.new.tap do |p|
|
214
|
-
after(2) { p.resolve('hello') }
|
215
|
-
end
|
216
|
-
end.to eq('hello')
|
217
|
-
```
|
218
|
-
|
219
|
-
#### Call Back and Event History Methods
|
220
|
-
|
221
|
-
HyperReact components can *generate* events and perform callbacks. HyperSpec provides methods to test if an event or callback was made.
|
222
|
-
|
223
|
-
```ruby
|
224
|
-
mount 'CallBackOnEveryThirdClick' do
|
225
|
-
class CallBackOnEveryThirdClick < React::Component::Base
|
226
|
-
param :click3, type: Proc
|
227
|
-
def increment_click
|
228
|
-
@clicks ||= 0
|
229
|
-
@clicks = (@clicks + 1)
|
230
|
-
params.click3(@clicks) if @clicks % 3 == 0
|
231
|
-
end
|
232
|
-
render do
|
233
|
-
DIV(class: :tp_clicker) { "click me" }
|
234
|
-
.on(:click) { increment_click }
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
7.times { page.click('#tp_clicker') }
|
240
|
-
expect(callback_history_for(:click3)).to eq([[3], [6]])
|
241
|
-
```
|
242
|
-
|
243
|
-
Note that for things to work, the param must be declared as a `type: Proc`.
|
244
|
-
|
245
|
-
+ `callback_history_for`: the entire history given as an array of arrays
|
246
|
-
+ `last_callback_for`: same as `callback_history_for(xxx).last`
|
247
|
-
+ `clear_callback_history_for`: clears the array (userful for repeating test variations without remounting)
|
248
|
-
+ `event_history_for, last_event_for, clear_event_history_for`: same but for events.
|
249
|
-
|
250
|
-
#### The `pause` Method
|
251
|
-
|
252
|
-
For debugging. Everything stops, until you type `go()` in the client console. Running binding.pry also has this effect, and is often sufficient, however it will also block the server from responding unless you have a multithreaded server.
|
253
|
-
|
254
|
-
#### The `attributes_on_client` Method
|
255
|
-
|
256
|
-
*This feature is currently untested - use at your own risk.*
|
257
|
-
|
258
|
-
This reads the value of active record model attributes on the client.
|
259
|
-
|
260
|
-
In other words the method `attributes_on_client` is added to all ActiveRecord models. You then take a model you have instance of on the server, and by passing the Capybara page object, you get back the attributes for that same model instance, currently on the client.
|
261
|
-
|
262
|
-
```ruby
|
263
|
-
expect(some_record_on_server.attributes_on_client(page)[:fred]).to eq(12)
|
264
|
-
```
|
265
|
-
|
266
|
-
Note that after persisting a record the client and server will be synced so this is mainly useful for debug or in rare cases where it is important to interrogate the value on the client before its persisted.
|
267
|
-
|
268
|
-
#### The `size_window` Method
|
269
|
-
|
270
|
-
Sets the size of the test window. You can say:
|
271
|
-
`size_window(width, height)` or pass one of the following standard sizes: to one of the following standard sizes:
|
272
|
-
|
273
|
-
+ small: 480 X 320
|
274
|
-
+ mobile: 640 X 480
|
275
|
-
+ tablet: 960 X 640
|
276
|
-
+ large: 1920 X 6000
|
277
|
-
+ default: 1024 X 768
|
278
|
-
|
279
|
-
example: `size_window(:mobile)`
|
280
|
-
|
281
|
-
You can also modify the standard sizes with `:portrait`
|
282
|
-
|
283
|
-
example: `size_window(:table, :portrait)`
|
284
|
-
|
285
|
-
You can also specify the size by providing the width and height.
|
286
|
-
|
287
|
-
example: `size_window(600, 600)`
|
288
|
-
|
289
|
-
size_window with no parameters is the same as `size_window(:default)`
|
290
|
-
|
291
|
-
Typically you will use this in a `before(:each)` or `before(:step)` block
|
292
|
-
|
293
|
-
#### The `add_class` Method
|
294
|
-
|
295
|
-
Sometimes it's useful to change styles during testing (mainly for debug so that changes on screen are visible.)
|
296
|
-
|
297
|
-
The `add_class` method takes a class name (as a symbol or string), and hash representing the style.
|
298
|
-
|
299
|
-
```ruby
|
300
|
-
it "can add classes during testing" do
|
301
|
-
add_class :some_class, borderStyle: :solid
|
302
|
-
mount 'StyledDiv' do
|
303
|
-
class StyledDiv < React::Component::Base
|
304
|
-
render(DIV, id: 'hello', class: 'some_class') do
|
305
|
-
'Hello!'
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|
309
|
-
expect(page.find('#hello').native.css_value('border-right-style')).to eq('solid')
|
310
|
-
end
|
311
|
-
```
|
312
|
-
|
313
|
-
## Integration with the Steps gem
|
314
|
-
|
315
|
-
The [rspec-steps gem](https://github.com/LRDesign/rspec-steps) can be useful in doing client side testing. Without rspec-steps, each test spec will cause a reload of the browser window. While this insures that each test runs in a clean environment, it is typically not necessary and can really slow down testing.
|
316
|
-
|
317
|
-
The rspec-steps gem will run each test without reloading the window, which is usually fine.
|
318
|
-
|
319
|
-
Checkout the rspec-steps example in the `hyper_spec.rb` file for an example.
|
320
|
-
|
321
|
-
*Note that hopefully in the near future we are going to build a custom capybara driver that will just directly talk to Hyperloop on the client side. Once this is in place these troubles should go away! - Volunteers welcome to help!*
|
322
|
-
|
323
|
-
## Timecop Integration
|
324
|
-
|
325
|
-
HyperSpec is integrated with [Timecop](https://github.com/travisjeffery/timecop) to freeze, move and speed up time. The client and server times will be kept in sync when you use any these Timecop methods:
|
326
|
-
|
327
|
-
+ `freeze`: Freezes time at the specified point in time (default is Time.now)
|
328
|
-
+ `travel`: Time runs normally forward from the point specified.
|
329
|
-
+ `scale`: Like travel but times runs faster.
|
330
|
-
+ `return`: Return to normal system time.
|
331
|
-
|
332
|
-
For example:
|
333
|
-
```ruby
|
334
|
-
Timecop.freeze # freeze time at current time
|
335
|
-
# ... test some stuff
|
336
|
-
Timecop.freeze Time.now+10.minutes # move time forward 10 minutes
|
337
|
-
# ... check to see if expected events happened etc
|
338
|
-
Timecop.return
|
339
|
-
```
|
340
|
-
|
341
|
-
```ruby
|
342
|
-
Timecop.scale 60, Time.now-1.year do
|
343
|
-
# Time will begin 1 year ago but advance 60 times faster than normal
|
344
|
-
sleep 10
|
345
|
-
# still sleeps for 10 seconds YOUR time, but server and client will
|
346
|
-
# think 10 minutes have passed
|
347
|
-
end
|
348
|
-
# no need for Timecop.return if using the block style
|
349
|
-
```
|
350
|
-
|
351
|
-
See the Timecop [README](https://github.com/travisjeffery/timecop/blob/master/README.markdown) for more details.
|
352
|
-
|
353
|
-
There is one confusing thing to note: On the server if you `sleep` then you will sleep for the specified number of seconds when viewed *outside* of the test. However inside the test environment if you look at Time.now, you will see it advancing according to the scale factor. Likewise if you have a `after` or `every` block on the client, you will wait according to *simulated* time.
|
354
|
-
|
355
|
-
## Common Problems
|
356
|
-
|
357
|
-
If you are getting failures on Poltergeist but not Firefox, make sure you are not requiring `browser` in your components.rb.
|
358
|
-
Requiring `browser/interval` or `browser/delay` is okay.
|
359
|
-
|
360
|
-
## Development
|
361
|
-
|
362
|
-
After checking out the repo, run bundle install and you should be good to go.
|
363
|
-
|
364
|
-
Tests are run either by running `rake` or for more control:
|
365
|
-
|
366
|
-
```
|
367
|
-
DRIVER=ff bundle exec rspec spec/hyper_spec.rb
|
368
|
-
```
|
369
|
-
|
370
|
-
where DRIVER can be either `ff` (firefox) or `pg` (poltergeist - default).
|
371
|
-
|
372
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
373
|
-
|
374
|
-
## Contributing
|
375
|
-
|
376
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/hyper-spec. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
377
|
-
|
378
|
-
## License
|
379
|
-
|
380
|
-
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
@@ -1,94 +0,0 @@
|
|
1
|
-
module React
|
2
|
-
class TopLevelRailsComponent
|
3
|
-
class << self
|
4
|
-
attr_accessor :event_history
|
5
|
-
|
6
|
-
def callback_history_for(proc_name)
|
7
|
-
event_history[proc_name]
|
8
|
-
end
|
9
|
-
|
10
|
-
def last_callback_for(proc_name)
|
11
|
-
event_history[proc_name].last
|
12
|
-
end
|
13
|
-
|
14
|
-
def clear_callback_history_for(proc_name)
|
15
|
-
event_history[proc_name] = []
|
16
|
-
end
|
17
|
-
|
18
|
-
def event_history_for(event_name)
|
19
|
-
event_history["_on#{event_name.event_camelize}"]
|
20
|
-
end
|
21
|
-
|
22
|
-
def last_event_for(event_name)
|
23
|
-
event_history["_on#{event_name.event_camelize}"].last
|
24
|
-
end
|
25
|
-
|
26
|
-
def clear_event_history_for(event_name)
|
27
|
-
event_history["_on#{event_name.event_camelize}"] = []
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def component
|
32
|
-
return @component if @component
|
33
|
-
paths_searched = []
|
34
|
-
component = nil
|
35
|
-
if params.component_name.start_with?('::')
|
36
|
-
# if absolute path of component is given, look it up and fail if not found
|
37
|
-
paths_searched << params.component_name
|
38
|
-
component = begin
|
39
|
-
Object.const_get(params.component_name)
|
40
|
-
rescue NameError
|
41
|
-
nil
|
42
|
-
end
|
43
|
-
else
|
44
|
-
# if relative path is given, look it up like this
|
45
|
-
# 1) we check each path + controller-name + component-name
|
46
|
-
# 2) if we can't find it there we check each path + component-name
|
47
|
-
# if we can't find it we just try const_get
|
48
|
-
# so (assuming controller name is Home)
|
49
|
-
# ::Foo::Bar will only resolve to some component named ::Foo::Bar
|
50
|
-
# but Foo::Bar will check (in this order) ::Home::Foo::Bar, ::Components::Home::Foo::Bar, ::Foo::Bar, ::Components::Foo::Bar
|
51
|
-
self.class.search_path.each do |scope|
|
52
|
-
paths_searched << "#{scope.name}::#{params.controller}::#{params.component_name}"
|
53
|
-
component = begin
|
54
|
-
scope.const_get(params.controller, false).const_get(params.component_name, false)
|
55
|
-
rescue NameError
|
56
|
-
nil
|
57
|
-
end
|
58
|
-
break if component != nil
|
59
|
-
end
|
60
|
-
unless component
|
61
|
-
self.class.search_path.each do |scope|
|
62
|
-
paths_searched << "#{scope.name}::#{params.component_name}"
|
63
|
-
component = begin
|
64
|
-
scope.const_get(params.component_name, false)
|
65
|
-
rescue NameError
|
66
|
-
nil
|
67
|
-
end
|
68
|
-
break if component != nil
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
@component = component
|
73
|
-
return @component if @component && @component.method_defined?(:render)
|
74
|
-
raise "Could not find component class '#{params.component_name}' for params.controller '#{params.controller}' in any component directory. Tried [#{paths_searched.join(", ")}]"
|
75
|
-
end
|
76
|
-
|
77
|
-
before_mount do
|
78
|
-
TopLevelRailsComponent.event_history = Hash.new { |h, k| h[k] = [] }
|
79
|
-
@render_params = params.render_params
|
80
|
-
component.validator.rules.each do |name, rules|
|
81
|
-
next unless rules[:type] == Proc
|
82
|
-
|
83
|
-
TopLevelRailsComponent.event_history[name] = []
|
84
|
-
@render_params[name] = lambda do |*args|
|
85
|
-
TopLevelRailsComponent.event_history[name] << args
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def render
|
91
|
-
React::RenderingContext.render(component, @render_params)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|