hyper-react 0.99.6 → 1.0.0.lap21

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.
Files changed (187) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +27 -0
  3. data/.gitignore +30 -37
  4. data/.rubocop.yml +1159 -0
  5. data/.travis.yml +32 -0
  6. data/Appraisals +31 -0
  7. data/CHANGELOG.md +143 -0
  8. data/DOCS.md +1515 -0
  9. data/Gemfile +2 -5
  10. data/LICENSE +19 -0
  11. data/README.md +5 -33
  12. data/Rakefile +25 -6
  13. data/UPGRADING.md +24 -0
  14. data/component-name-lookup.md +145 -0
  15. data/dciy.toml +3 -0
  16. data/dciy_prepare.sh +8 -0
  17. data/dciy_run.sh +10 -0
  18. data/hyper-react.gemspec +24 -18
  19. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +3 -0
  20. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/server_rendering.js +5 -0
  21. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/test_application.rb +2 -0
  22. data/lib/generators/reactive_ruby/test_app/templates/boot.rb.erb +6 -0
  23. data/lib/generators/reactive_ruby/test_app/templates/script/rails +5 -0
  24. data/lib/generators/reactive_ruby/test_app/templates/test_application.rb.erb +13 -0
  25. data/lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +11 -0
  26. data/lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb +14 -0
  27. data/lib/generators/reactive_ruby/test_app/templates/views/layouts/test_layout.html.erb +0 -0
  28. data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +117 -0
  29. data/lib/hyper-react.rb +66 -4
  30. data/lib/rails-helpers/top_level_rails_component.rb +75 -0
  31. data/lib/react/api.rb +203 -0
  32. data/lib/react/callbacks.rb +41 -0
  33. data/lib/react/children.rb +30 -0
  34. data/lib/react/component.rb +177 -0
  35. data/lib/react/component/api.rb +69 -0
  36. data/lib/react/component/base.rb +13 -0
  37. data/lib/react/component/class_methods.rb +181 -0
  38. data/lib/react/component/dsl_instance_methods.rb +23 -0
  39. data/lib/react/component/params.rb +6 -0
  40. data/lib/react/component/props_wrapper.rb +78 -0
  41. data/lib/react/component/should_component_update.rb +99 -0
  42. data/lib/react/component/tags.rb +108 -0
  43. data/lib/react/config.rb +5 -0
  44. data/lib/react/config/client.rb.erb +19 -0
  45. data/lib/react/config/server.rb +23 -0
  46. data/lib/react/element.rb +150 -0
  47. data/lib/react/event.rb +76 -0
  48. data/lib/react/ext/hash.rb +9 -0
  49. data/lib/react/ext/opal-jquery/element.rb +26 -0
  50. data/lib/react/ext/string.rb +8 -0
  51. data/lib/react/hash.rb +13 -0
  52. data/lib/react/native_library.rb +87 -0
  53. data/lib/react/object.rb +15 -0
  54. data/lib/react/react-source-browser.rb +3 -0
  55. data/lib/react/react-source-server.rb +3 -0
  56. data/lib/react/react-source.rb +16 -0
  57. data/lib/react/ref_callback.rb +31 -0
  58. data/lib/react/rendering_context.rb +146 -0
  59. data/lib/react/server.rb +19 -0
  60. data/lib/react/state_wrapper.rb +23 -0
  61. data/lib/react/test.rb +16 -0
  62. data/lib/react/test/dsl.rb +17 -0
  63. data/lib/react/test/matchers/render_html_matcher.rb +56 -0
  64. data/lib/react/test/rspec.rb +15 -0
  65. data/lib/react/test/session.rb +37 -0
  66. data/lib/react/test/utils.rb +71 -0
  67. data/lib/react/top_level.rb +110 -0
  68. data/lib/react/top_level_render.rb +28 -0
  69. data/lib/react/validator.rb +136 -0
  70. data/lib/reactive-ruby/component_loader.rb +43 -0
  71. data/lib/reactive-ruby/isomorphic_helpers.rb +235 -0
  72. data/lib/reactive-ruby/rails.rb +8 -0
  73. data/lib/reactive-ruby/rails/component_mount.rb +48 -0
  74. data/lib/reactive-ruby/rails/controller_helper.rb +14 -0
  75. data/lib/reactive-ruby/rails/railtie.rb +20 -0
  76. data/lib/reactive-ruby/serializers.rb +15 -0
  77. data/lib/reactive-ruby/server_rendering/contextual_renderer.rb +41 -0
  78. data/lib/reactive-ruby/server_rendering/hyper_asset_container.rb +46 -0
  79. data/lib/reactive-ruby/version.rb +3 -0
  80. data/lib/reactrb/auto-import.rb +27 -0
  81. data/logo1.png +0 -0
  82. data/logo2.png +0 -0
  83. data/logo3.png +0 -0
  84. data/path_release_steps.md +9 -0
  85. data/spec/controller_helper_spec.rb +35 -0
  86. data/spec/index.html.erb +11 -0
  87. data/spec/react/callbacks_spec.rb +142 -0
  88. data/spec/react/children_spec.rb +132 -0
  89. data/spec/react/component/base_spec.rb +36 -0
  90. data/spec/react/component_spec.rb +1073 -0
  91. data/spec/react/dsl_spec.rb +323 -0
  92. data/spec/react/element_spec.rb +132 -0
  93. data/spec/react/event_spec.rb +39 -0
  94. data/spec/react/native_library_spec.rb +387 -0
  95. data/spec/react/observable_spec.rb +31 -0
  96. data/spec/react/opal_jquery_extensions_spec.rb +68 -0
  97. data/spec/react/param_declaration_spec.rb +253 -0
  98. data/spec/react/react_spec.rb +278 -0
  99. data/spec/react/refs_callback_spec.rb +65 -0
  100. data/spec/react/server_spec.rb +25 -0
  101. data/spec/react/state_spec.rb +52 -0
  102. data/spec/react/test/dsl_spec.rb +43 -0
  103. data/spec/react/test/matchers/render_html_matcher_spec.rb +83 -0
  104. data/spec/react/test/rspec_spec.rb +62 -0
  105. data/spec/react/test/session_spec.rb +88 -0
  106. data/spec/react/test/utils_spec.rb +28 -0
  107. data/spec/react/top_level_component_spec.rb +103 -0
  108. data/spec/react/tutorial/tutorial_spec.rb +42 -0
  109. data/spec/react/validator_spec.rb +134 -0
  110. data/spec/reactive-ruby/component_loader_spec.rb +74 -0
  111. data/spec/reactive-ruby/isomorphic_helpers_spec.rb +157 -0
  112. data/spec/reactive-ruby/rails/asset_pipeline_spec.rb +17 -0
  113. data/spec/reactive-ruby/rails/component_mount_spec.rb +64 -0
  114. data/spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb +39 -0
  115. data/spec/spec_helper.rb +55 -0
  116. data/spec/test_app/README.md +24 -0
  117. data/spec/test_app/Rakefile +6 -0
  118. data/spec/test_app/app/assets/config/manifest.js +3 -0
  119. data/spec/test_app/app/assets/images/.keep +0 -0
  120. data/spec/test_app/app/assets/javascripts/application.rb +7 -0
  121. data/spec/test_app/app/assets/javascripts/cable.js +13 -0
  122. data/spec/test_app/app/assets/javascripts/channels/.keep +0 -0
  123. data/spec/test_app/app/assets/javascripts/server_rendering.js +5 -0
  124. data/spec/test_app/app/assets/stylesheets/application.css +15 -0
  125. data/spec/test_app/app/channels/application_cable/channel.rb +4 -0
  126. data/spec/test_app/app/channels/application_cable/connection.rb +4 -0
  127. data/spec/test_app/app/controllers/application_controller.rb +3 -0
  128. data/spec/test_app/app/controllers/concerns/.keep +0 -0
  129. data/spec/test_app/app/helpers/application_helper.rb +2 -0
  130. data/spec/test_app/app/jobs/application_job.rb +2 -0
  131. data/spec/test_app/app/mailers/application_mailer.rb +4 -0
  132. data/spec/test_app/app/models/application_record.rb +3 -0
  133. data/spec/test_app/app/models/concerns/.keep +0 -0
  134. data/spec/test_app/app/views/components.rb +11 -0
  135. data/spec/test_app/app/views/components/hello_world.rb +11 -0
  136. data/spec/test_app/app/views/components/todo.rb +14 -0
  137. data/spec/test_app/app/views/layouts/application.html.erb +14 -0
  138. data/spec/test_app/app/views/layouts/explicit_layout.html.erb +0 -0
  139. data/spec/test_app/app/views/layouts/mailer.html.erb +13 -0
  140. data/spec/test_app/app/views/layouts/mailer.text.erb +1 -0
  141. data/spec/test_app/app/views/layouts/test_layout.html.erb +0 -0
  142. data/spec/test_app/bin/bundle +3 -0
  143. data/spec/test_app/bin/rails +4 -0
  144. data/spec/test_app/bin/rake +4 -0
  145. data/spec/test_app/bin/setup +38 -0
  146. data/spec/test_app/bin/update +29 -0
  147. data/spec/test_app/bin/yarn +11 -0
  148. data/spec/test_app/config.ru +5 -0
  149. data/spec/test_app/config/application.rb +45 -0
  150. data/spec/test_app/config/boot.rb +6 -0
  151. data/spec/test_app/config/cable.yml +10 -0
  152. data/spec/test_app/config/database.yml +25 -0
  153. data/spec/test_app/config/environment.rb +5 -0
  154. data/spec/test_app/config/environments/development.rb +54 -0
  155. data/spec/test_app/config/environments/production.rb +91 -0
  156. data/spec/test_app/config/environments/test.rb +42 -0
  157. data/spec/test_app/config/initializers/application_controller_renderer.rb +8 -0
  158. data/spec/test_app/config/initializers/assets.rb +14 -0
  159. data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
  160. data/spec/test_app/config/initializers/cookies_serializer.rb +5 -0
  161. data/spec/test_app/config/initializers/filter_parameter_logging.rb +4 -0
  162. data/spec/test_app/config/initializers/inflections.rb +16 -0
  163. data/spec/test_app/config/initializers/mime_types.rb +4 -0
  164. data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
  165. data/spec/test_app/config/locales/en.yml +33 -0
  166. data/spec/test_app/config/puma.rb +56 -0
  167. data/spec/test_app/config/routes.rb +3 -0
  168. data/spec/test_app/config/secrets.yml +32 -0
  169. data/spec/test_app/config/spring.rb +6 -0
  170. data/spec/test_app/db/development.sqlite3 +0 -0
  171. data/spec/test_app/db/schema.rb +15 -0
  172. data/spec/test_app/db/seeds.rb +7 -0
  173. data/spec/test_app/db/test.sqlite3 +0 -0
  174. data/spec/test_app/lib/assets/.keep +0 -0
  175. data/spec/test_app/log/.keep +0 -0
  176. data/spec/test_app/package.json +5 -0
  177. data/spec/test_app/public/404.html +67 -0
  178. data/spec/test_app/public/422.html +67 -0
  179. data/spec/test_app/public/500.html +66 -0
  180. data/spec/test_app/public/apple-touch-icon-precomposed.png +0 -0
  181. data/spec/test_app/public/apple-touch-icon.png +0 -0
  182. data/spec/test_app/public/favicon.ico +0 -0
  183. data/spec/vendor/es5-shim.min.js +7 -0
  184. data/spec/vendor/jquery-2.2.4.min.js +4 -0
  185. metadata +401 -61
  186. data/CODE_OF_CONDUCT.md +0 -49
  187. data/lib/react/version.rb +0 -3
@@ -0,0 +1,323 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'the React DSL', js: true do
4
+
5
+ context "render macro" do
6
+
7
+ it "can define the render method with the render macro with a html tag container" do
8
+ mount 'Foo' do
9
+ class Foo
10
+ include React::Component
11
+ render(:div, class: :foo) do
12
+ "hello"
13
+ end
14
+ end
15
+ end
16
+ expect(page.body[-60..-19]).to include('<div class="foo">hello</div>')
17
+ end
18
+
19
+ it "can define the render method with the render macro without a container" do
20
+ mount 'Foo' do
21
+ class Foo
22
+ include React::Component
23
+ render do
24
+ "hello"
25
+ end
26
+ end
27
+ end
28
+ expect(page.body[-60..-19]).to include('<span>hello</span>')
29
+ end
30
+
31
+ it "can define the render method with the render macro with a application defined container" do
32
+ on_client do
33
+ class Bar < React::Component::Base
34
+ param :p1
35
+ render { "hello #{params.p1}" }
36
+ end
37
+ class Foo < React::Component::Base
38
+ render Bar, p1: "fred"
39
+ end
40
+ end
41
+ mount 'Foo'
42
+ expect(page.body[-60..-19]).to include('<span>hello fred</span>')
43
+ end
44
+ end
45
+
46
+ it "will turn the last string in a block into a element" do
47
+ mount 'Foo' do
48
+ class Foo
49
+ include React::Component
50
+ def render
51
+ div { "hello" }
52
+ end
53
+ end
54
+ end
55
+ expect(page.body[-60..-19]).to include('<div>hello</div>')
56
+ end
57
+
58
+ it "in prerender will pass converted props through event handlers" do
59
+ client_option render_on: :both
60
+ mount 'Foo' do
61
+ class Foo
62
+ include React::Component
63
+ def render
64
+ INPUT(data: {foo: 12}).on(:change) {}
65
+ end
66
+ end
67
+ end
68
+ expect(page.body).to match(/<input data-foo="12" data-reactroot="" \/>/)
69
+ end
70
+
71
+ it "will turn the last string in a block into a element" do
72
+ mount 'Foo' do
73
+ class Foo
74
+ include React::Component
75
+ def render
76
+ DIV { "hello" }
77
+ end
78
+ end
79
+ end
80
+ expect(page.body[-60..-19]).to include('<div>hello</div>')
81
+ end
82
+
83
+ it "has a .span short hand String method" do
84
+ mount 'Foo' do
85
+ class Foo
86
+ include React::Component
87
+ def render
88
+ div { "hello".span; "goodby".span }
89
+ end
90
+ end
91
+ end
92
+ expect(page.body[-70..-19]).to include('<div><span>hello</span><span>goodby</span></div>')
93
+ end
94
+
95
+ it "in prerendering has a .br short hand String method" do
96
+ client_option render_on: :both
97
+ client_option raise_on_js_errors: :off
98
+ mount 'Foo' do
99
+ class Foo
100
+ include React::Component
101
+ def render
102
+ div { "hello".br }
103
+ end
104
+ end
105
+ end
106
+ expect(page.body[-80..-19]).to match(/(<div data-reactroot=""|<div)><span>hello<(br|br\/|br \/)><\/span><\/div>/)
107
+ end
108
+
109
+ it "has a .td short hand String method" do
110
+ mount 'Foo' do
111
+ class Foo
112
+ include React::Component
113
+ def render
114
+ table {
115
+ tbody {
116
+ tr { "hello".td }
117
+ }
118
+ }
119
+ end
120
+ end
121
+ end
122
+ expect(page.body[-90..-19]).to include('<table><tbody><tr><td>hello</td></tr></tbody></table>')
123
+ end
124
+
125
+ it "has a .para short hand String method" do
126
+ mount 'Foo' do
127
+ class Foo
128
+ include React::Component
129
+ def render
130
+ div { "hello".para }
131
+ end
132
+ end
133
+ end
134
+ expect(page.body[-60..-19]).to include('<div><p>hello</p></div>')
135
+ end
136
+
137
+ it 'can do a method call on a class name that is not a direct sibling' do
138
+ # this test is failing because Comp() is not serialized/compiled to a method call,
139
+ # but instead to a $scope.get("Comp"); which returns the Component Class Mod::Comp
140
+ # instead it sould serialize/compile to a $scope.$Comp();
141
+ # this is a bug in unparser, workaround is to pass a argument to comp
142
+ mount 'Mod::NestedMod::NestedComp' do
143
+ module Mod
144
+ class Comp
145
+ include React::Component
146
+ param :test
147
+ def render
148
+ "Mod::Comp"
149
+ end
150
+ end
151
+ module NestedMod
152
+ class NestedComp
153
+ include React::Component
154
+ def render
155
+ Comp(test: 'string')
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+ expect(page.body[-60..-19]).to include('<span>Mod::Comp</span>')
162
+ end
163
+
164
+ it 'raises a meaningful error if a Constant Name is not actually a component' do
165
+ client_option raise_on_js_errors: :off
166
+ mount 'Mod::NestedMod::NestedComp' do
167
+ module Mod
168
+ module NestedMod
169
+ class NestedComp < React::Component::Base
170
+ backtrace :none
171
+ render do
172
+ Comp(test: 'string')
173
+ end
174
+ end
175
+ end
176
+ class Comp; end
177
+ end
178
+ end
179
+ expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
180
+ .to match(/Comp does not appear to be a react component./)
181
+ end
182
+
183
+ it 'raises a method missing error' do
184
+ client_option render_on: :both
185
+ client_option raise_on_js_errors: :off
186
+ expect_evaluate_ruby do
187
+ class Foo < React::Component::Base
188
+ backtrace :none
189
+ render do
190
+ _undefined_method
191
+ end
192
+ end
193
+ begin
194
+ React::Test::Utils.render_component_into_document(Foo)
195
+ 'not raised'
196
+ rescue NoMethodError
197
+ 'raised for sure!'
198
+ end
199
+ end.to eq('raised for sure!')
200
+
201
+ end
202
+
203
+ it "will treat the component class name as a first class component name" do
204
+ mount 'Foo' do
205
+ module Mod
206
+ class Bar
207
+ include React::Component
208
+ def render
209
+ "a man walks into a bar"
210
+ end
211
+ end
212
+ end
213
+ class Foo < React::Component::Base
214
+ def render
215
+ Mod::Bar()
216
+ end
217
+ end
218
+ end
219
+ expect(page.body[-60..-19]).to include('<span>a man walks into a bar</span>')
220
+ end
221
+
222
+ it "can add class names by the haml .class notation" do
223
+ mount 'Foo' do
224
+ module Mod
225
+ class Bar
226
+ include React::Component
227
+ collect_other_params_as :attributes
228
+ def render
229
+ "a man walks into a bar".span(params.attributes)
230
+ end
231
+ end
232
+ end
233
+ class Foo < React::Component::Base
234
+ def render
235
+ Mod::Bar().the_class.other_class
236
+ end
237
+ end
238
+ end
239
+ expect(page.body[-90..-19]).to include('<span class="other-class the-class">a man walks into a bar</span>')
240
+ end
241
+
242
+ it "can use the 'class' keyword for classes" do
243
+ mount 'Foo' do
244
+ class Foo
245
+ include React::Component
246
+ def render
247
+ span(class: "the-class") { "hello" }
248
+ end
249
+ end
250
+ end
251
+ expect(page.body[-60..-19]).to include('<span class="the-class">hello</span>')
252
+ end
253
+
254
+ it "can generate a unrendered node using the .as_node method" do # div { "hello" }.as_node
255
+ mount 'Foo' do
256
+ class Foo
257
+ include React::Component
258
+ def render
259
+ span(data: {size: 12}) { "hello".span.as_node.class.name }.as_node.render
260
+ end
261
+ end
262
+ end
263
+ expect(page.body[-80..-19]).to include('<span data-size="12">React::Element</span>')
264
+ end
265
+
266
+ it "can use the dangerously_set_inner_HTML param" do
267
+ mount 'Foo' do
268
+ class Foo
269
+ include React::Component
270
+ def render
271
+ div(dangerously_set_inner_HTML: { __html: "Hello and Goodby" })
272
+ end
273
+ end
274
+ end
275
+ expect(page.body[-60..-19]).to include('<div>Hello and Goodby</div>')
276
+ end
277
+
278
+ it 'should convert a hash param to hyphenated html attributes if in React::HASH_ATTRIBUTES' do
279
+ mount 'Foo' do
280
+ class Foo
281
+ include React::Component
282
+ def render
283
+ div(data: { foo: :bar }, aria: { label: "title" })
284
+ end
285
+ end
286
+ end
287
+ expect(page.body[-70..-19]).to include('<div data-foo="bar" aria-label="title"></div>')
288
+ end
289
+
290
+ it 'should not convert a hash param to hyphenated html attributes if not in React::HASH_ATTRIBUTES' do
291
+ mount 'Foo' do
292
+ class Foo
293
+ include React::Component
294
+ def render
295
+ div(title: { bar: :foo })
296
+ end
297
+ end
298
+ end
299
+ expect(page.body[-80..-19]).to include('<div title="{&quot;bar&quot;=&gt;&quot;foo&quot;}"></div>')
300
+ end
301
+
302
+ it "will remove all elements passed as params from the rendering buffer" do
303
+ mount 'Foo' do
304
+ class X2
305
+ include React::Component
306
+ param :ele
307
+ def render
308
+ div do
309
+ params[:ele].render
310
+ params[:ele].render
311
+ end
312
+ end
313
+ end
314
+ class Foo
315
+ include React::Component
316
+ def render
317
+ X2(ele: b { "hello" })
318
+ end
319
+ end
320
+ end
321
+ expect(page.body[-60..-19]).to include('<div><b>hello</b><b>hello</b></div>')
322
+ end
323
+ end
@@ -0,0 +1,132 @@
1
+ require "spec_helper"
2
+
3
+ describe 'React::Element', js: true do
4
+ it 'bridges `type` of native React.Element attributes' do
5
+ expect_evaluate_ruby do
6
+ element = React.create_element('div')
7
+ element.element_type
8
+ end.to eq("div")
9
+ end
10
+
11
+ it 'is renderable' do
12
+ expect_evaluate_ruby do
13
+ element = React.create_element('span')
14
+ div = JS.call(:eval, 'document.createElement("div")')
15
+ React.render(element, div)
16
+ div.JS[:children].JS[0].JS[:tagName]
17
+ end.to eq("SPAN")
18
+ end
19
+
20
+ describe "Event Subscription" do
21
+ it "keeps the original params" do
22
+ client_option render_on: :both
23
+ mount 'Foo' do
24
+ class Foo
25
+ include React::Component
26
+ def render
27
+ INPUT(value: nil, type: 'text').on(:change) {}
28
+ end
29
+ end
30
+ end
31
+ expect(page.body[-80..-19]).to match(/<input (type="text" value=""|value="" type="text").*\/>/)
32
+ end
33
+ end
34
+
35
+ describe 'Component Event Subscription' do
36
+
37
+ it 'will subscribe to a component event param' do
38
+ evaluate_ruby do
39
+ class Foo < React::Component::Base
40
+ param :on_event, type: Proc, default: nil, allow_nil: true
41
+ def render
42
+ params.on_event
43
+ end
44
+ end
45
+ React::Test::Utils.render_into_document(React.create_element(Foo).on(:event) {'works!'})
46
+ end
47
+ expect(page.body[-50..-19]).to include('<span>works!</span>')
48
+ end
49
+
50
+ it 'will subscribe to multiple component event params' do
51
+ evaluate_ruby do
52
+ class Foo < React::Component::Base
53
+ param :on_event1, type: Proc, default: nil, allow_nil: true
54
+ param :on_event2, type: Proc, default: nil, allow_nil: true
55
+ def render
56
+ params.on_event1+params.on_event2
57
+ end
58
+ end
59
+ React::Test::Utils.render_into_document(React.create_element(Foo).on(:event1, :event2) {'works!'})
60
+ end
61
+ expect(page.body[-60..-19]).to include('<span>works!works!</span>')
62
+ end
63
+
64
+ it 'will subscribe to a native components event param' do
65
+
66
+ evaluate_ruby do
67
+ "this makes sure everything is loaded"
68
+ end
69
+ page.execute_script('window.NativeComponent = class extends React.Component {
70
+ constructor(props) {
71
+ super(props);
72
+ this.displayName = "HelloMessage";
73
+ }
74
+ render() { return React.createElement("span", null, this.props.onEvent()); }
75
+ }')
76
+ evaluate_ruby do
77
+ class Foo < React::Component::Base
78
+ imports "NativeComponent"
79
+ end
80
+ React::Test::Utils.render_into_document(React.create_element(Foo).on(:event) {'works!'})
81
+ true
82
+ end
83
+ expect(page.body[-60..-19]).to include('<span>works!</span>')
84
+ end
85
+
86
+ it 'will subscribe to a component event param with a non-default name' do
87
+
88
+ evaluate_ruby do
89
+ class Foo < React::Component::Base
90
+ param :my_event, type: Proc, default: nil, allow_nil: true
91
+ def render
92
+ params.my_event
93
+ end
94
+ end
95
+ React::Test::Utils.render_into_document(React.create_element(Foo).on("<my_event>") {'works!'})
96
+ end
97
+ expect(page.body[-60..-19]).to include('<span>works!</span>')
98
+ end
99
+ end
100
+
101
+ describe 'Builtin Event subscription' do
102
+ it 'is subscribable through `on(:event_name)` method' do
103
+ expect_evaluate_ruby do
104
+ element = React.create_element("div").on(:click) { |event| RESULT_C = 'clicked' if event.is_a? React::Event }
105
+ dom_node = React::Test::Utils.render_into_document(element)
106
+ React::Test::Utils.simulate_click(dom_node)
107
+ RESULT_C rescue 'not clicked'
108
+ end.to eq('clicked')
109
+
110
+ expect_evaluate_ruby do
111
+ element = React.create_element("div").on(:key_down) { |event| RESULT_P = 'pressed' if event.is_a? React::Event }
112
+ dom_node = React::Test::Utils.render_into_document(element)
113
+ React::Test::Utils.simulate_keydown(dom_node, "Enter")
114
+ RESULT_P rescue 'not pressed'
115
+ end.to eq('pressed')
116
+
117
+ expect_evaluate_ruby do
118
+ element = React.create_element("form").on(:submit) { |event| RESULT_S = 'submitted' if event.is_a? React::Event }
119
+ dom_node = React::Test::Utils.render_into_document(element)
120
+ React::Test::Utils.simulate_submit(dom_node)
121
+ RESULT_S rescue 'not submitted'
122
+ end.to eq('submitted')
123
+ end
124
+
125
+ it 'returns self for `on` method' do
126
+ expect_evaluate_ruby do
127
+ element = React.create_element("div")
128
+ element.on(:click){} == element
129
+ end.to be_truthy
130
+ end
131
+ end
132
+ end