hyper-spec 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.rubocop.yml DELETED
@@ -1,107 +0,0 @@
1
- Style/BlockDelimiters:
2
- EnforcedStyle: line_count_based
3
- SupportedStyles:
4
- # The `line_count_based` style enforces braces around single line blocks and
5
- # do..end around multi-line blocks.
6
- - line_count_based
7
- # The `semantic` style enforces braces around functional blocks, where the
8
- # primary purpose of the block is to return a value and do..end for
9
- # procedural blocks, where the primary purpose of the block is its
10
- # side-effects.
11
- #
12
- # This looks at the usage of a block's method to determine its type (e.g. is
13
- # the result of a `map` assigned to a variable or passed to another
14
- # method) but exceptions are permitted in the `ProceduralMethods`,
15
- # `FunctionalMethods` and `IgnoredMethods` sections below.
16
- - semantic
17
- # The `braces_for_chaining` style enforces braces around single line blocks
18
- # and do..end around multi-line blocks, except for multi-line blocks whose
19
- # return value is being chained with another method (in which case braces
20
- # are enforced).
21
- - braces_for_chaining
22
- ProceduralMethods:
23
- # Methods that are known to be procedural in nature but look functional from
24
- # their usage, e.g.
25
- #
26
- # time = Benchmark.realtime do
27
- # foo.bar
28
- # end
29
- #
30
- # Here, the return value of the block is discarded but the return value of
31
- # `Benchmark.realtime` is used.
32
- - benchmark
33
- - bm
34
- - bmbm
35
- - create
36
- - each_with_object
37
- - measure
38
- - new
39
- - realtime
40
- - tap
41
- - with_object
42
- FunctionalMethods:
43
- # Methods that are known to be functional in nature but look procedural from
44
- # their usage, e.g.
45
- #
46
- # let(:foo) { Foo.new }
47
- #
48
- # Here, the return value of `Foo.new` is used to define a `foo` helper but
49
- # doesn't appear to be used from the return value of `let`.
50
- - let
51
- - let!
52
- - subject
53
- - watch
54
- IgnoredMethods:
55
- # Methods that can be either procedural or functional and cannot be
56
- # categorised from their usage alone, e.g.
57
- #
58
- # foo = lambda do |x|
59
- # puts "Hello, #{x}"
60
- # end
61
- #
62
- # foo = lambda do |x|
63
- # x * 100
64
- # end
65
- #
66
- # Here, it is impossible to tell from the return value of `lambda` whether
67
- # the inner block's return value is significant.
68
- - lambda
69
- - proc
70
- - it
71
-
72
- Style/Documentation:
73
- Description: 'Document classes and non-namespace modules.'
74
- Enabled: false
75
- Exclude:
76
- - 'spec/**/*'
77
- - 'test/**/*'
78
-
79
- # Multi-line method chaining should be done with trailing dots.
80
- Style/DotPosition:
81
- EnforcedStyle: leading
82
- SupportedStyles:
83
- - leading
84
- - trailing
85
-
86
- Style/FrozenStringLiteralComment:
87
- Description: >-
88
- Add the frozen_string_literal comment to the top of files
89
- to help transition from Ruby 2.3.0 to Ruby 3.0.
90
- Enabled: false
91
-
92
- Style/MultilineBlockChain:
93
- Description: 'Avoid multi-line chains of blocks.'
94
- StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks'
95
- Enabled: false
96
-
97
- Style/MutableConstant:
98
- Description: 'Do not assign mutable objects to constants.'
99
- Enabled: false
100
-
101
- Metrics/AbcSize:
102
- # The ABC size is a calculated magnitude, so this number can be a Fixnum or
103
- # a Float.
104
- Max: 20
105
-
106
- Metrics/LineLength:
107
- Max: 100
@@ -1,306 +0,0 @@
1
- # see component_test_helpers_spec.rb for examples
2
-
3
- require 'parser/current'
4
- require 'unparser'
5
- require 'method_source'
6
- require_relative '../../vendor/assets/javascripts/time_cop' # 'hyper-spec/time_cop'
7
-
8
- module HyperSpec
9
- module ComponentTestHelpers
10
- TOP_LEVEL_COMPONENT_PATCH =
11
- Opal.compile(File.read(File.expand_path('../../react/top_level_rails_component.rb', __FILE__)))
12
-
13
- class << self
14
- attr_accessor :current_example
15
- attr_accessor :description_displayed
16
-
17
- def display_example_description
18
- "<script type='text/javascript'>console.log(console.log('%c#{current_example.description}'"\
19
- ",'color:green; font-weight:bold; font-size: 200%'))</script>"
20
- end
21
- end
22
-
23
- def build_test_url_for(controller)
24
- unless controller
25
- unless defined?(::ReactTestController)
26
- Object.const_set('ReactTestController', Class.new(ActionController::Base))
27
- end
28
-
29
- controller = ::ReactTestController
30
- end
31
-
32
- route_root = controller.name.gsub(/Controller$/, '').underscore
33
-
34
- unless controller.method_defined?(:test)
35
- controller.class_eval do
36
- define_method(:test) do
37
- route_root = self.class.name.gsub(/Controller$/, '').underscore
38
- test_params = ::Rails.cache.read("/#{route_root}/#{params[:id]}")
39
- @component_name = test_params[0]
40
- @component_params = test_params[1]
41
- render_params = test_params[2]
42
- render_on = render_params.delete(:render_on) || :client_only
43
- _mock_time = render_params.delete(:mock_time)
44
- style_sheet = render_params.delete(:style_sheet)
45
- javascript = render_params.delete(:javascript)
46
- code = render_params.delete(:code)
47
-
48
- page = '<%= react_component @component_name, @component_params, '\
49
- "{ prerender: #{render_on != :client_only} } %>"
50
- page = "<script type='text/javascript'>\n#{TOP_LEVEL_COMPONENT_PATCH}\n</script>\n#{page}"
51
-
52
- page = "<script type='text/javascript'>\n#{code}\n</script>\n#{page}" if code
53
-
54
- page = "<%= javascript_include_tag 'time_cop' %>\n#{page}" if true || Lolex.initialized?
55
-
56
- if (render_on != :server_only && !render_params[:layout]) || javascript
57
- page = "<%= javascript_include_tag '#{javascript || 'application'}' %>\n#{page}"
58
- end
59
-
60
- if !render_params[:layout] || style_sheet
61
- page = "<%= stylesheet_link_tag '#{style_sheet || 'application'}' %>\n#{page}"
62
- end
63
-
64
- if render_on == :server_only # so that test helper wait_for_ajax works
65
- page = "<script type='text/javascript'>window.jQuery = {'active': 0}</script>\n#{page}"
66
- else
67
- page = "<%= javascript_include_tag 'jquery' %>\n"\
68
- "<%= javascript_include_tag 'jquery_ujs' %>\n#{page}"
69
- end
70
-
71
- page = "<script type='text/javascript'>go = function() "\
72
- "{window.hyper_spec_waiting_for_go = false}</script>\n#{page}"
73
-
74
- title = view_context.escape_javascript(ComponentTestHelpers.current_example.description)
75
- title = "#{title}...continued." if ComponentTestHelpers.description_displayed
76
-
77
- page = "<script type='text/javascript'>console.log(console.log('%c#{title}',"\
78
- "'color:green; font-weight:bold; font-size: 200%'))</script>\n#{page}"
79
-
80
- ComponentTestHelpers.description_displayed = true
81
- render_params[:inline] = page
82
- render render_params
83
- end
84
- end
85
-
86
- begin
87
- routes = ::Rails.application.routes
88
- routes.disable_clear_and_finalize = true
89
- routes.clear!
90
- routes.draw do
91
- get "/#{route_root}/:id", to: "#{route_root}#test"
92
- end
93
- ::Rails.application.routes_reloader.paths.each { |path| load(path) }
94
- routes.finalize!
95
- ActiveSupport.on_load(:action_controller) { routes.finalize! }
96
- ensure
97
- routes.disable_clear_and_finalize = false
98
- end
99
- end
100
-
101
- "/#{route_root}/#{@test_id = (@test_id || 0) + 1}"
102
- end
103
-
104
- def isomorphic(&block)
105
- yield
106
- on_client(&block)
107
- end
108
-
109
- def evaluate_ruby(str = '', opts = {}, &block)
110
- insure_mount
111
- if block
112
- str = "#{str}\n#{Unparser.unparse Parser::CurrentRuby.parse(block.source).children.last}"
113
- end
114
- js = Opal.compile(str).delete("\n").gsub('(Opal);', '(Opal)')
115
- JSON.parse(evaluate_script("[#{js}].$to_json()"), opts).first
116
- end
117
-
118
- def expect_evaluate_ruby(str = '', opts = {}, &block)
119
- insure_mount
120
- expect(evaluate_ruby(add_opal_block(str, block), opts))
121
- end
122
-
123
- def add_opal_block(str, block)
124
- # big assumption here is that we are going to follow this with a .to
125
- # hence .children.first followed by .children.last
126
- # probably should do some kind of "search" to make this work nicely
127
- return str unless block
128
- "#{str}\n"\
129
- "#{Unparser.unparse Parser::CurrentRuby.parse(block.source).children.first.children.last}"
130
- end
131
-
132
- def expect_promise(str = '', opts = {}, &block)
133
- insure_mount
134
-
135
- str = add_opal_block(str, block)
136
- str = "#{str}.then { |args| args = [args]; `window.hyper_spec_promise_result = args` }"
137
- js = Opal.compile(str).delete("\n").gsub('(Opal);', '(Opal)')
138
- page.evaluate_script('window.hyper_spec_promise_result = false')
139
- page.execute_script(js)
140
-
141
- Timeout.timeout(Capybara.default_max_wait_time) do
142
- loop do
143
- sleep 0.25
144
- break if page.evaluate_script('!!window.hyper_spec_promise_result')
145
- end
146
- end
147
-
148
- result =
149
- JSON.parse(page.evaluate_script('window.hyper_spec_promise_result.$to_json()'), opts).first
150
- expect(result)
151
- end
152
-
153
- def ppr(str)
154
- js = Opal.compile(str).delete("\n").gsub('(Opal);', '(Opal)')
155
- execute_script("console.log(#{js})")
156
- end
157
-
158
- def on_client(&block)
159
- @client_code =
160
- "#{@client_code}#{Unparser.unparse Parser::CurrentRuby.parse(block.source).children.last}\n"
161
- end
162
-
163
- def debugger
164
- `debugger`
165
- nil
166
- end
167
-
168
- def insure_mount
169
- # rescue in case page is not defined...
170
- mount unless page.instance_variable_get('@hyper_spec_mounted')
171
- end
172
-
173
- def client_option(opts = {})
174
- @client_options ||= {}
175
- @client_options.merge! opts
176
- end
177
-
178
- alias client_options client_option
179
-
180
- def mount(component_name = nil, params = nil, opts = {}, &block)
181
- unless params
182
- params = opts
183
- opts = {}
184
- end
185
-
186
- opts = client_options opts
187
- test_url = build_test_url_for(opts.delete(:controller))
188
-
189
- if block || @client_code || component_name.nil?
190
- block_with_helpers = <<-code
191
- module ComponentHelpers
192
- def self.js_eval(s)
193
- `eval(s)`
194
- end
195
- def self.dasherize(s)
196
- `s.replace(/[-_\\s]+/g, '-')
197
- .replace(/([A-Z\\d]+)([A-Z][a-z])/g, '$1-$2')
198
- .replace(/([a-z\\d])([A-Z])/g, '$1-$2')
199
- .toLowerCase()`
200
- end
201
- def self.add_class(class_name, styles={})
202
- style = styles.collect { |attr, value| "\#{dasherize(attr)}:\#{value}"}.join("; ")
203
- s = "<style type='text/css'> .\#{class_name}{ \#{style} } </style>"
204
- `$(\#{s}).appendTo("head");`
205
- end
206
- end
207
- class React::Component::HyperTestDummy < React::Component::Base
208
- def render; end
209
- end
210
- #{@client_code}
211
- #{Unparser.unparse(Parser::CurrentRuby.parse(block.source).children.last) if block}
212
- code
213
- opts[:code] = Opal.compile(block_with_helpers)
214
- end
215
-
216
- component_name ||= 'React::Component::HyperTestDummy'
217
- ::Rails.cache.write(test_url, [component_name, params, opts])
218
- visit test_url
219
- wait_for_ajax unless opts[:no_wait]
220
- page.instance_variable_set('@hyper_spec_mounted', true)
221
- Lolex.init(self, client_options[:time_zone], client_options[:clock_resolution])
222
- end
223
-
224
- [:callback_history_for, :last_callback_for, :clear_callback_history_for,
225
- :event_history_for, :last_event_for, :clear_event_history_for].each do |method|
226
- define_method(method) do |event_name|
227
- evaluate_ruby("React::TopLevelRailsComponent.#{method}('#{event_name}')")
228
- end
229
- end
230
-
231
- def run_on_client(&block)
232
- script = Opal.compile(Unparser.unparse(Parser::CurrentRuby.parse(block.source).children.last))
233
- execute_script(script)
234
- end
235
-
236
- def add_class(class_name, style)
237
- @client_code = "#{@client_code}ComponentHelpers.add_class '#{class_name}', #{style}\n"
238
- end
239
-
240
- def open_in_chrome
241
- if false && ['linux', 'freebsd'].include?(`uname`.downcase)
242
- `google-chrome http://#{page.server.host}:#{page.server.port}#{page.current_path}`
243
- else
244
- `open http://#{page.server.host}:#{page.server.port}#{page.current_path}`
245
- end
246
-
247
- while true
248
- sleep 1.hour
249
- end
250
- end
251
-
252
- def pause(message = nil)
253
- if message
254
- puts message
255
- page.evaluate_ruby "puts #{message.inspect}.to_s + ' (type go() to continue)'"
256
- end
257
-
258
- page.evaluate_script('window.hyper_spec_waiting_for_go = true')
259
-
260
- loop do
261
- sleep 0.25
262
- break unless page.evaluate_script('window.hyper_spec_waiting_for_go')
263
- end
264
- end
265
-
266
- def size_window(width = nil, height = nil)
267
- width, height = [height, width] if width == :portrait
268
- width, height = width if width.is_a? Array
269
- portrait = true if height == :portrait
270
-
271
- case width
272
- when :small
273
- width, height = [480, 320]
274
- when :mobile
275
- width, height = [640, 480]
276
- when :tablet
277
- width, height = [960, 640]
278
- when :large
279
- width, height = [1920, 6000]
280
- when :default, nil
281
- width, height = [1024, 768]
282
- end
283
-
284
- width, height = [height, width] if portrait
285
-
286
- Capybara.current_session.current_window.resize_to(width, height)
287
- end
288
- end
289
-
290
- RSpec.configure do |config|
291
- config.before(:each) do |example|
292
- ComponentTestHelpers.current_example = example
293
- ComponentTestHelpers.description_displayed = false
294
- end
295
-
296
- if defined?(ActiveRecord)
297
- config.before(:all) do
298
- ActiveRecord::Base.class_eval do
299
- def attributes_on_client(page)
300
- page.evaluate_ruby("#{self.class.name}.find(#{id}).attributes", symbolize_names: true)
301
- end
302
- end
303
- end
304
- end
305
- end
306
- end
@@ -1,66 +0,0 @@
1
- module HyperSpec
2
- class Lolex
3
- class << self
4
- def init(page, client_time_zone, resolution)
5
- @capybara_page = page
6
- @resolution = resolution || 10
7
- @client_time_zone = client_time_zone
8
- run_pending_evaluations
9
- @initialized = true
10
- end
11
-
12
- def initialized?
13
- @initialized
14
- end
15
-
16
- def push(mock_type, *args)
17
- scale = if mock_type == :freeze
18
- 0
19
- elsif mock_type == :scale
20
- args[0]
21
- else
22
- 1
23
- end
24
- evaluate_ruby do
25
- "Lolex.push('#{time_string_in_zone}', #{scale}, #{@resolution})"
26
- end
27
- end
28
-
29
- def pop
30
- evaluate_ruby { 'Lolex.pop' }
31
- end
32
-
33
- def unmock
34
- evaluate_ruby { "Lolex.unmock('#{time_string_in_zone}', #{@resolution})" }
35
- end
36
-
37
- def restore
38
- evaluate_ruby { 'Lolex.restore' }
39
- end
40
-
41
- private
42
-
43
- def time_string_in_zone
44
- Time.now.in_time_zone(@client_time_zone).strftime('%Y/%m/%d %H:%M:%S %z')
45
- end
46
-
47
- def pending_evaluations
48
- @pending_evaluations ||= []
49
- end
50
-
51
- def evaluate_ruby(&block)
52
- if @capybara_page
53
- @capybara_page.evaluate_ruby(yield)
54
- else
55
- pending_evaluations << block
56
- end
57
- end
58
-
59
- def run_pending_evaluations
60
- return if pending_evaluations.empty?
61
- @capybara_page.evaluate_ruby(pending_evaluations.collect(&:call).join("\n"))
62
- @pending_evaluations ||= []
63
- end
64
- end
65
- end
66
- end