hyper-spec 0.1.2 → 0.99.0

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.
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
data/CODE_OF_CONDUCT.md DELETED
@@ -1,49 +0,0 @@
1
- # Contributor Code of Conduct
2
-
3
- As contributors and maintainers of this project, and in the interest of
4
- fostering an open and welcoming community, we pledge to respect all people who
5
- contribute through reporting issues, posting feature requests, updating
6
- documentation, submitting pull requests or patches, and other activities.
7
-
8
- We are committed to making participation in this project a harassment-free
9
- experience for everyone, regardless of level of experience, gender, gender
10
- identity and expression, sexual orientation, disability, personal appearance,
11
- body size, race, ethnicity, age, religion, or nationality.
12
-
13
- Examples of unacceptable behavior by participants include:
14
-
15
- * The use of sexualized language or imagery
16
- * Personal attacks
17
- * Trolling or insulting/derogatory comments
18
- * Public or private harassment
19
- * Publishing other's private information, such as physical or electronic
20
- addresses, without explicit permission
21
- * Other unethical or unprofessional conduct
22
-
23
- Project maintainers have the right and responsibility to remove, edit, or
24
- reject comments, commits, code, wiki edits, issues, and other contributions
25
- that are not aligned to this Code of Conduct, or to ban temporarily or
26
- permanently any contributor for other behaviors that they deem inappropriate,
27
- threatening, offensive, or harmful.
28
-
29
- By adopting this Code of Conduct, project maintainers commit themselves to
30
- fairly and consistently applying these principles to every aspect of managing
31
- this project. Project maintainers who do not follow or enforce the Code of
32
- Conduct may be permanently removed from the project team.
33
-
34
- This code of conduct applies both within project spaces and in public spaces
35
- when an individual is representing the project or its community.
36
-
37
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
- reported by contacting a project maintainer at mitch@catprint.com. All
39
- complaints will be reviewed and investigated and will result in a response that
40
- is deemed necessary and appropriate to the circumstances. Maintainers are
41
- obligated to maintain confidentiality with regard to the reporter of an
42
- incident.
43
-
44
- This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
- version 1.3.0, available at
46
- [http://contributor-covenant.org/version/1/3/0/][version]
47
-
48
- [homepage]: http://contributor-covenant.org
49
- [version]: http://contributor-covenant.org/version/1/3/0/
data/LICENSE.txt DELETED
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2017 catmando
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
@@ -1,368 +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
-
9
- module ComponentTestHelpers
10
-
11
- def self.compile_to_opal(&block)
12
- Opal.compile(block.source.split("\n")[1..-2].join("\n"))
13
- end
14
-
15
-
16
- TOP_LEVEL_COMPONENT_PATCH = lambda { |&block| Opal.compile(block.source.split("\n")[1..-2].join("\n"))}.call do #ComponentTestHelpers.compile_to_opal do
17
- module React
18
- class TopLevelRailsComponent
19
-
20
- class << self
21
- attr_accessor :event_history
22
-
23
- def callback_history_for(proc_name)
24
- event_history[proc_name]
25
- end
26
-
27
- def last_callback_for(proc_name)
28
- event_history[proc_name].last
29
- end
30
-
31
- def clear_callback_history_for(proc_name)
32
- event_history[proc_name] = []
33
- end
34
-
35
- def event_history_for(event_name)
36
- event_history["_on#{event_name.event_camelize}"]
37
- end
38
-
39
- def last_event_for(event_name)
40
- event_history["_on#{event_name.event_camelize}"].last
41
- end
42
-
43
- def clear_event_history_for(event_name)
44
- event_history["_on#{event_name.event_camelize}"] = []
45
- end
46
-
47
- end
48
-
49
- def component
50
- return @component if @component
51
- paths_searched = []
52
- if params.component_name.start_with? "::"
53
- paths_searched << params.component_name.gsub(/^\:\:/,"")
54
- @component = params.component_name.gsub(/^\:\:/,"").split("::").inject(Module) { |scope, next_const| scope.const_get(next_const, false) } rescue nil
55
- return @component if @component && @component.method_defined?(:render)
56
- else
57
- self.class.search_path.each do |path|
58
- # try each path + params.controller + params.component_name
59
- paths_searched << "#{path.name + '::' unless path == Module}#{params.controller}::#{params.component_name}"
60
- @component = "#{params.controller}::#{params.component_name}".split("::").inject(path) { |scope, next_const| scope.const_get(next_const, false) } rescue nil
61
- return @component if @component && @component.method_defined?(:render)
62
- end
63
- self.class.search_path.each do |path|
64
- # then try each path + params.component_name
65
- paths_searched << "#{path.name + '::' unless path == Module}#{params.component_name}"
66
- @component = "#{params.component_name}".split("::").inject(path) { |scope, next_const| scope.const_get(next_const, false) } rescue nil
67
- return @component if @component && @component.method_defined?(:render)
68
- end
69
- end
70
- @component = nil
71
- raise "Could not find component class '#{params.component_name}' for params.controller '#{params.controller}' in any component directory. Tried [#{paths_searched.join(", ")}]"
72
- end
73
-
74
- before_mount do
75
- TopLevelRailsComponent.event_history = Hash.new {|h,k| h[k] = [] }
76
- @render_params = params.render_params
77
- component.validator.rules.each do |name, rules|
78
- if rules[:type] == Proc
79
- TopLevelRailsComponent.event_history[name] = []
80
- @render_params[name] = lambda { |*args| TopLevelRailsComponent.event_history[name] << args } #args.collect { |arg| Native(arg).to_n } }
81
- end
82
- end
83
- end
84
-
85
- def render
86
- present component, @render_params
87
- end
88
- end
89
- end
90
- end
91
-
92
- def build_test_url_for(controller)
93
-
94
- unless controller
95
- Object.const_set("ReactTestController", Class.new(ApplicationController)) unless defined?(::ReactTestController)
96
- controller = ::ReactTestController
97
- end
98
-
99
- route_root = controller.name.gsub(/Controller$/,"").underscore
100
-
101
- unless controller.method_defined? :test
102
- controller.class_eval do
103
- define_method(:test) do
104
- route_root = self.class.name.gsub(/Controller$/,"").underscore
105
- test_params = Rails.cache.read("/#{route_root}/#{params[:id]}")
106
- @component_name = test_params[0]
107
- @component_params = test_params[1]
108
- render_params = test_params[2]
109
- render_on = render_params.delete(:render_on) || :client_only
110
- mock_time = render_params.delete(:mock_time)
111
- style_sheet = render_params.delete(:style_sheet)
112
- javascript = render_params.delete(:javascript)
113
- code = render_params.delete(:code)
114
- page = "<%= react_component @component_name, @component_params, { prerender: #{render_on != :client_only} } %>"
115
- page = "<script type='text/javascript'>\n#{TOP_LEVEL_COMPONENT_PATCH}\n</script>\n#{page}"
116
-
117
- if code
118
- page = "<script type='text/javascript'>\n#{code}\n</script>\n"+page
119
- end
120
-
121
- #TODO figure out how to auto insert this line???? something like:
122
- #page = "<%= javascript_include_tag 'reactrb-router' %>\n#{page}"
123
-
124
-
125
- if true || Lolex.initialized?
126
- page = "<%= javascript_include_tag 'time_cop' %>\n"+page
127
- end
128
- if (render_on != :server_only && !render_params[:layout]) || javascript
129
- #page = "<script src='/assets/application.js?ts=#{Time.now.to_f}'></script>\n"+page
130
- page = "<%= javascript_include_tag '#{javascript || 'application'}' %>\n"+page
131
- end
132
- if !render_params[:layout] || style_sheet
133
- page = "<%= stylesheet_link_tag '#{style_sheet || 'application'}' %>\n"+page
134
- end
135
- if render_on == :server_only # so that test helper wait_for_ajax works
136
- page = "<script type='text/javascript'>window.jQuery = {'active': 0}</script>\n#{page}"
137
- else
138
- page = "<%= javascript_include_tag 'jquery' %>\n<%= javascript_include_tag 'jquery_ujs' %>\n#{page}"
139
- end
140
- page = "<script type='text/javascript'>go = function() {window.hyper_spec_waiting_for_go = false}</script>\n#{page}"
141
- title = view_context.escape_javascript(ComponentTestHelpers.current_example.description)
142
- title = "#{title}...continued." if ComponentTestHelpers.description_displayed
143
- page = "<script type='text/javascript'>console.log(console.log('%c#{title}','color:green; font-weight:bold; font-size: 200%'))</script>\n#{page}"
144
- ComponentTestHelpers.description_displayed = true
145
- render_params[:inline] = page
146
- render render_params
147
- end
148
- end
149
-
150
- # test_routes = Proc.new do
151
- # get "/#{route_root}/:id", to: "#{route_root}#test"
152
- # end
153
- # Rails.application.routes.eval_block(test_routes)
154
-
155
- begin
156
- routes = Rails.application.routes
157
- routes.disable_clear_and_finalize = true
158
- routes.clear!
159
- routes.draw do
160
- get "/#{route_root}/:id", to: "#{route_root}#test"
161
- end
162
- Rails.application.routes_reloader.paths.each{ |path| load(path) }
163
- routes.finalize!
164
- ActiveSupport.on_load(:action_controller) { routes.finalize! }
165
- ensure
166
- routes.disable_clear_and_finalize = false
167
- end
168
- end
169
-
170
- "/#{route_root}/#{@test_id = (@test_id || 0) + 1}"
171
-
172
- end
173
-
174
- def isomorphic(&block)
175
- yield
176
- on_client(&block)
177
- end
178
-
179
- def evaluate_ruby(str="", opts={}, &block)
180
- insure_mount
181
- str = "#{str}\n#{Unparser.unparse Parser::CurrentRuby.parse(block.source).children.last}" if block
182
- js = Opal.compile(str).gsub("\n","").gsub("(Opal);","(Opal)")
183
- JSON.parse(evaluate_script("[#{js}].$to_json()"), opts).first
184
- end
185
-
186
- def expect_evaluate_ruby(str = '', opts = {}, &block)
187
- insure_mount
188
- expect(evaluate_ruby(add_opal_block(str, block), opts))
189
- end
190
-
191
- def add_opal_block(str, block)
192
- # big assumption here is that we are going to follow this with a .to
193
- # hence .children.first followed by .children.last
194
- # probably should do some kind of "search" to make this work nicely
195
- return str unless block
196
- "#{str}\n"\
197
- "#{Unparser.unparse Parser::CurrentRuby.parse(block.source).children.first.children.last}"
198
- end
199
-
200
- def expect_promise(str = '', opts = {}, &block)
201
- insure_mount
202
- str = add_opal_block(str, block)
203
- str = "#{str}.then { |args| args = [args]; `window.hyper_spec_promise_result = args` }"
204
- js = Opal.compile(str).gsub("\n","").gsub("(Opal);","(Opal)")
205
- page.evaluate_script("window.hyper_spec_promise_result = false")
206
- page.execute_script(js)
207
- Timeout.timeout(Capybara.default_max_wait_time) do
208
- loop do
209
- sleep 0.25
210
- break if page.evaluate_script("!!window.hyper_spec_promise_result")
211
- end
212
- end
213
- expect(JSON.parse(page.evaluate_script("window.hyper_spec_promise_result.$to_json()"), opts).first)
214
- end
215
-
216
- def ppr(str)
217
- js = Opal.compile(str).gsub("\n","").gsub("(Opal);","(Opal)")
218
- execute_script("console.log(#{js})")
219
- end
220
-
221
-
222
- def on_client(&block)
223
- @client_code = "#{@client_code}#{Unparser.unparse Parser::CurrentRuby.parse(block.source).children.last}\n"
224
- end
225
-
226
- def debugger
227
- `debugger`
228
- nil
229
- end
230
-
231
- class << self
232
- attr_accessor :current_example
233
- attr_accessor :description_displayed
234
- def display_example_description
235
- "<script type='text/javascript'>console.log(console.log('%c#{current_example.description}','color:green; font-weight:bold; font-size: 200%'))</script>"
236
- end
237
- end
238
-
239
- def insure_mount
240
- # rescue in case page is not defined...
241
- mount unless page.instance_variable_get("@hyper_spec_mounted") #rescue nil
242
- end
243
-
244
- def client_option(opts = {})
245
- @client_options ||= {}
246
- @client_options.merge! opts
247
- end
248
-
249
- alias client_options client_option
250
-
251
- def mount(component_name = nil, params = nil, opts = {}, &block)
252
- unless params
253
- params = opts
254
- opts = {}
255
- end
256
- opts = client_options opts
257
- test_url = build_test_url_for(opts.delete(:controller))
258
- if block || @client_code || component_name.nil?
259
- block_with_helpers = <<-code
260
- module ComponentHelpers
261
- def self.js_eval(s)
262
- `eval(s)`
263
- end
264
- def self.dasherize(s)
265
- `s.replace(/[-_\\s]+/g, '-')
266
- .replace(/([A-Z\\d]+)([A-Z][a-z])/g, '$1-$2')
267
- .replace(/([a-z\\d])([A-Z])/g, '$1-$2')
268
- .toLowerCase()`
269
- end
270
- def self.add_class(class_name, styles={})
271
- style = styles.collect { |attr, value| "\#{dasherize(attr)}:\#{value}"}.join("; ")
272
- s = "<style type='text/css'> .\#{class_name}{ \#{style} } </style>"
273
- `$(\#{s}).appendTo("head");`
274
- end
275
- end
276
- class React::Component::HyperTestDummy < React::Component::Base
277
- def render; end
278
- end
279
- #{@client_code}
280
- #{Unparser.unparse(Parser::CurrentRuby.parse(block.source).children.last) if block}
281
- code
282
- opts[:code] = Opal.compile(block_with_helpers)
283
- end
284
- component_name ||= 'React::Component::HyperTestDummy'
285
- Rails.cache.write(test_url, [component_name, params, opts])
286
- visit test_url
287
- wait_for_ajax unless opts[:no_wait]
288
- page.instance_variable_set("@hyper_spec_mounted", true)
289
- Lolex.init(self, client_options[:time_zone], client_options[:clock_resolution])
290
- end
291
-
292
- [:callback_history_for, :last_callback_for, :clear_callback_history_for, :event_history_for, :last_event_for, :clear_event_history_for].each do |method|
293
- define_method(method) { |event_name| evaluate_ruby("React::TopLevelRailsComponent.#{method}('#{event_name}')") }
294
- end
295
-
296
- def run_on_client(&block)
297
- script = Opal.compile(Unparser.unparse Parser::CurrentRuby.parse(block.source).children.last)
298
- execute_script(script)
299
- end
300
-
301
- def add_class(class_name, style)
302
- @client_code = "#{@client_code}ComponentHelpers.add_class '#{class_name}', #{style}\n"
303
- end
304
-
305
- def open_in_chrome
306
- if false && ['linux', 'freebsd'].include?(`uname`.downcase)
307
- `google-chrome http://#{page.server.host}:#{page.server.port}#{page.current_path}`
308
- else
309
- `open http://#{page.server.host}:#{page.server.port}#{page.current_path}`
310
- end
311
- while true
312
- sleep 1.hour
313
- end
314
- end
315
-
316
- def pause(message = nil)
317
- if message
318
- puts message
319
- page.evaluate_ruby "puts #{message.inspect}.to_s + ' (type go() to continue)'"
320
- end
321
- page.evaluate_script("window.hyper_spec_waiting_for_go = true")
322
- loop do
323
- sleep 0.25
324
- break unless page.evaluate_script("window.hyper_spec_waiting_for_go")
325
- end
326
- end
327
-
328
- def size_window(width=nil, height=nil)
329
- width, height = [height, width] if width == :portrait
330
- width, height = width if width.is_a? Array
331
- portrait = true if height == :portrait
332
- case width
333
- when :small
334
- width, height = [480, 320]
335
- when :mobile
336
- width, height = [640, 480]
337
- when :tablet
338
- width, height = [960, 640]
339
- when :large
340
- width, height = [1920, 6000]
341
- when :default, nil
342
- width, height = [1024, 768]
343
- end
344
- if portrait
345
- width, height = [height, width]
346
- end
347
- if page.driver.browser.respond_to?(:manage)
348
- page.driver.browser.manage.window.resize_to(width, height)
349
- elsif page.driver.respond_to?(:resize)
350
- page.driver.resize(width, height)
351
- end
352
- end
353
-
354
- end
355
-
356
- RSpec.configure do |config|
357
- config.before(:each) do |example|
358
- ComponentTestHelpers.current_example = example
359
- ComponentTestHelpers.description_displayed = false
360
- end
361
- config.before(:all) do
362
- ActiveRecord::Base.class_eval do
363
- def attributes_on_client(page)
364
- page.evaluate_ruby("#{self.class.name}.find(#{id}).attributes", symbolize_names: true)
365
- end
366
- end
367
- end if defined? ActiveRecord
368
- end