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,39 @@
1
+ require "spec_helper"
2
+
3
+ describe 'React::Event', js: true do
4
+ it "should bridge attributes of native SyntheticEvent (see http://facebook.github.io/react/docs/events.html#syntheticevent)" do
5
+ expect_evaluate_ruby do
6
+ results = {}
7
+ element = React.create_element('div').on(:click) do |event|
8
+ results[:bubbles] = event.bubbles == event.to_n.JS[:bubbles]
9
+ results[:cancelable] = event.cancelable == event.to_n.JS[:cancelable]
10
+ results[:current_target] = event.current_target == event.to_n.JS[:currentTarget]
11
+ results[:default_prevented] = event.default_prevented == event.to_n.JS[:defaultPrevented]
12
+ results[:event_phase] = event.event_phase == event.to_n.JS[:eventPhase]
13
+ results[:is_trusted?] = event.is_trusted? == event.to_n.JS[:isTrusted]
14
+ results[:native_event] = event.native_event == event.to_n.JS[:nativeEvent]
15
+ results[:target] = event.target == event.to_n.JS[:target]
16
+ results[:timestamp] = event.timestamp == event.to_n.JS[:timeStamp]
17
+ results[:event_type] = event.event_type == event.to_n.JS[:type]
18
+ results[:prevent_default] = event.respond_to?(:prevent_default)
19
+ results[:stop_propagation] = event.respond_to?(:stop_propagation)
20
+ end
21
+ dom_node = React::Test::Utils.render_into_document(element)
22
+ React::Test::Utils.simulate_click(dom_node)
23
+ results
24
+ end.to eq({
25
+ 'bubbles' => true,
26
+ 'cancelable' => true,
27
+ 'current_target' => true,
28
+ 'default_prevented' => true,
29
+ 'event_phase' => true,
30
+ 'is_trusted?' => true,
31
+ 'native_event' => true,
32
+ 'target' => true,
33
+ 'timestamp' => true,
34
+ 'event_type' => true,
35
+ 'prevent_default' => true,
36
+ 'stop_propagation' => true
37
+ })
38
+ end
39
+ end
@@ -0,0 +1,387 @@
1
+ require 'spec_helper'
2
+ # This definitely is work in progress
3
+ describe "React::NativeLibrary", js: true do
4
+ before :each do
5
+ on_client do
6
+ module NativeLibraryTestModule
7
+ class Component < React::Component::Base
8
+ param :time_stamp
9
+ backtrace :none
10
+ render { NativeComponent(name: "There - #{params.time_stamp}") }
11
+ end
12
+
13
+ class NestedComponent < React::Component::Base
14
+ param :time_stamp
15
+ backtrace :none
16
+ render { NativeLibrary::NativeNestedLibrary::NativeComponent(name: "There - #{params.time_stamp}") }
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ describe "functional stateless component (supported in reactjs v14+ only)" do
23
+ it "is detected as native React.js component by `native_react_component?`" do
24
+ expect_evaluate_ruby do
25
+ React::API.native_react_component?(JS.call(:eval, "(function () { return function C () { return null; }; })();"))
26
+ end.to be_truthy
27
+ end
28
+
29
+ it "imports a React.js functional stateless component" do
30
+ mount 'Foo', name: "There" do
31
+ JS.call(:eval, 'window.NativeLibrary = { FunctionalComponent: function HelloMessage(props){
32
+ return React.createElement("div", null, "Hello ", props.name); }}')
33
+ class Foo < React::Component::Base
34
+ imports "NativeLibrary.FunctionalComponent"
35
+ end
36
+ end
37
+ expect(page.body[-60..-19]).to include('<div>Hello There</div>')
38
+ end
39
+ end
40
+
41
+ it "can use native_react_component? to detect a native React.js component" do
42
+ evaluate_ruby do
43
+ "this makes sure React is loaded for this test, before js is run"
44
+ end
45
+ page.execute_script('window.NativeComponent = class extends React.Component {
46
+ constructor(props) {
47
+ super(props);
48
+ this.displayName = "HelloMessage";
49
+ }
50
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
51
+ }')
52
+ expect_evaluate_ruby do
53
+ React::API.native_react_component?(JS.call(:eval, '(function(){ return window.NativeComponent; })();'))
54
+ end.to be_truthy
55
+ expect_evaluate_ruby do
56
+ React::API.native_react_component?(JS.call(:eval, '(function(){ return {render: function render() {}}; })();'))
57
+ end.to be_falsy
58
+ expect_evaluate_ruby do
59
+ React::API.native_react_component?(JS.call(:eval, '(function(){ return window.DoesntExist; })();'))
60
+ end.to be_falsy
61
+ expect_evaluate_ruby do
62
+ React::API.native_react_component?()
63
+ end.to be_falsy
64
+ end
65
+
66
+ it "will import a React.js library into the Ruby name space" do
67
+ mount 'Foo::NativeComponent', name: "There" do
68
+ JS.call(:eval,
69
+ <<-JSCODE
70
+ window.NativeLibrary = {
71
+ NativeComponent: class extends React.Component {
72
+ constructor(props) {
73
+ super(props);
74
+ this.displayName = "HelloMessage";
75
+ }
76
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
77
+ }}
78
+ JSCODE
79
+ )
80
+ class Foo < React::NativeLibrary
81
+ imports "NativeLibrary"
82
+ end
83
+ end
84
+ expect(page.body[-60..-19]).to include('<div>Hello There</div>')
85
+ end
86
+
87
+ it "will import a nested React.js library into the Ruby name space" do
88
+ mount 'Foo::NestedLibrary::NativeComponent', name: "There" do
89
+ JS.call(:eval,
90
+ <<-JSCODE
91
+ window.NativeLibrary = {
92
+ NestedLibrary: {
93
+ NativeComponent: class extends React.Component {
94
+ constructor(props) {
95
+ super(props);
96
+ this.displayName = "HelloMessage";
97
+ }
98
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
99
+ }}}
100
+ JSCODE
101
+ )
102
+ class Foo < React::NativeLibrary
103
+ imports "NativeLibrary"
104
+ end
105
+ end
106
+ expect(page.body[-60..-19]).to include('<div>Hello There</div>')
107
+ end
108
+
109
+ it "will rename an imported a React.js component" do
110
+ mount 'Foo::Bar', name: "There" do
111
+ JS.call(:eval,
112
+ <<-JSCODE
113
+ window.NativeLibrary = {
114
+ NativeComponent: class extends React.Component {
115
+ constructor(props) {
116
+ super(props);
117
+ this.displayName = "HelloMessage";
118
+ }
119
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
120
+ }}
121
+ JSCODE
122
+ )
123
+ class Foo < React::NativeLibrary
124
+ imports "NativeLibrary"
125
+ rename "NativeComponent" => "Bar"
126
+ end
127
+ end
128
+ expect(page.body[-60..-19]).to include('<div>Hello There</div>')
129
+ end
130
+
131
+ it "will give a reasonable error when failing to import a renamed component" do
132
+ client_option raise_on_js_errors: :off
133
+ mount 'Foo' do
134
+ JS.call(:eval,
135
+ <<-JSCODE
136
+ window.NativeLibrary = {
137
+ NativeComponent: class extends React.Component {
138
+ constructor(props) {
139
+ super(props);
140
+ this.displayName = "HelloMessage";
141
+ }
142
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
143
+ }}
144
+ JSCODE
145
+ )
146
+ class Foo < React::NativeLibrary
147
+ imports "NativeLibrary"
148
+ rename "MispelledComponent" => "Bar"
149
+ end
150
+ end
151
+ expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
152
+ .to match(/NativeLibrary.MispelledComponent is undefined/)
153
+ # TODO was testing for cannot import, but that message gets trunkated
154
+ end
155
+
156
+ it "will import a single React.js component into the ruby name space" do
157
+ mount 'Foo', name: "There" do
158
+ JS.call(:eval,
159
+ <<-JSCODE
160
+ window.NativeComponent = class extends React.Component {
161
+ constructor(props) {
162
+ super(props);
163
+ this.displayName = "HelloMessage";
164
+ }
165
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
166
+ }
167
+ JSCODE
168
+ )
169
+ class Foo < React::Component::Base
170
+ imports "NativeComponent"
171
+ end
172
+ end
173
+ expect(page.body[-60..-19]).to include('<div>Hello There</div>')
174
+ end
175
+
176
+ it "will import a name scoped React.js component into the ruby name space" do
177
+ mount 'Foo', name: "There" do
178
+ JS.call(:eval,
179
+ <<-JSCODE
180
+ window.NativeLibrary = {
181
+ NativeComponent: class extends React.Component {
182
+ constructor(props) {
183
+ super(props);
184
+ this.displayName = "HelloMessage";
185
+ }
186
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
187
+ }}
188
+ JSCODE
189
+ )
190
+ class Foo < React::Component::Base
191
+ imports "NativeLibrary.NativeComponent"
192
+ end
193
+ end
194
+ expect(page.body[-60..-19]).to include('<div>Hello There</div>')
195
+ end
196
+
197
+ it "will give a meaningful error if the React.js component is invalid" do
198
+ client_option raise_on_js_errors: :off
199
+ evaluate_ruby do
200
+ JS.call(:eval, "window.NativeObject = {}")
201
+ class Foo < React::Component::Base; end
202
+ end
203
+ expect_evaluate_ruby do
204
+ begin
205
+ Foo.class_eval do
206
+ imports "NativeObject"
207
+ end
208
+ rescue Exception => e
209
+ e.message
210
+ end
211
+ end.to match(/Foo cannot import 'NativeObject': does not appear to be a native react component./)
212
+ expect_evaluate_ruby do
213
+ begin
214
+ Foo.class_eval do
215
+ imports "window.Baz"
216
+ end
217
+ rescue Exception => e
218
+ e.message
219
+ end
220
+ end.to match(/Foo cannot import \'window\.Baz\'\: (?!does not appear to be a native react component)./)
221
+ end
222
+
223
+ it "allows passing native object as props" do
224
+ mount 'Wrapper' do
225
+ JS.call(:eval,
226
+ <<-JSCODE
227
+ window.NativeComponent = class extends React.Component {
228
+ constructor(props) {
229
+ super(props);
230
+ this.displayName = "HelloMessage";
231
+ }
232
+ render() { return React.createElement("div", null, "Hello " + this.props.user.name); }
233
+ }
234
+ JSCODE
235
+ )
236
+ class Foo < React::Component::Base
237
+ imports "NativeComponent"
238
+ end
239
+ class Wrapper < React::Component::Base
240
+ def render
241
+ Foo(user: JS.call(:eval, "(function () { return {name: 'David'}; })();"))
242
+ end
243
+ end
244
+ end
245
+ expect(page.body[-60..-19]).to include('<div>Hello David</div>')
246
+ end
247
+
248
+ context "automatic importing" do
249
+
250
+ it "will automatically import a React.js component when referenced in another component" do
251
+ evaluate_ruby do
252
+ JS.call(:eval,
253
+ <<-JSCODE
254
+ window.NativeComponent = class extends React.Component {
255
+ constructor(props) {
256
+ super(props);
257
+ this.displayName = "HelloMessage";
258
+ }
259
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
260
+ }
261
+ JSCODE
262
+ )
263
+ React::Test::Utils.render_component_into_document(NativeLibraryTestModule::Component, time_stamp: Time.now)
264
+ end
265
+ expect(page.body[-100..-19]).to match(/<div>Hello There.*<\/div>/)
266
+ end
267
+
268
+ it "will automatically import a React.js component when referenced in another component in a different way" do
269
+ mount 'Foo' do
270
+ class Foo < React::Component::Base
271
+ render { NativeComponent(name: "There") }
272
+ end
273
+ JS.call(:eval,
274
+ <<-JSCODE
275
+ window.NativeComponent = class extends React.Component {
276
+ constructor(props) {
277
+ super(props);
278
+ this.displayName = "HelloMessage";
279
+ }
280
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
281
+ }
282
+ JSCODE
283
+ )
284
+ end
285
+ expect(page.body[-50..-19]).to match('<div>Hello There</div>')
286
+ end
287
+
288
+ it "will automatically import a React.js component when referenced as a constant" do
289
+ mount 'NativeComponent', name: "There" do
290
+ JS.call(:eval,
291
+ <<-JSCODE
292
+ window.NativeComponent = class extends React.Component {
293
+ constructor(props) {
294
+ super(props);
295
+ this.displayName = "HelloMessage";
296
+ }
297
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
298
+ }
299
+ JSCODE
300
+ )
301
+ end
302
+ expect(page.body[-50..-19]).to match('<div>Hello There</div>')
303
+ end
304
+
305
+ it "will automatically import a native library containing a React.js component" do
306
+ evaluate_ruby do
307
+ JS.call(:eval,
308
+ <<-JSCODE
309
+ window.NativeLibrary = {
310
+ NativeNestedLibrary: {
311
+ NativeComponent: class extends React.Component {
312
+ constructor(props) {
313
+ super(props);
314
+ this.displayName = "HelloMessage";
315
+ }
316
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
317
+ }}}
318
+ JSCODE
319
+ )
320
+ React::Test::Utils.render_component_into_document(NativeLibraryTestModule::NestedComponent, time_stamp: Time.now)
321
+ end
322
+ expect(page.body[-100..-19]).to match(/<div>Hello There.*<\/div>/)
323
+ end
324
+
325
+ it "the library and components can begin with lower case letters" do
326
+ mount 'NativeLibrary::NativeComponent', name: "There" do
327
+ JS.call(:eval,
328
+ <<-JSCODE
329
+ window.nativeLibrary = {
330
+ nativeComponent: class extends React.Component {
331
+ constructor(props) {
332
+ super(props);
333
+ this.displayName = "HelloMessage";
334
+ }
335
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
336
+ }}
337
+ JSCODE
338
+ )
339
+ end
340
+ expect(page.body[-50..-19]).to match('<div>Hello There</div>')
341
+ end
342
+
343
+ it "will produce a sensible error if the component is not in the library" do
344
+ client_option raise_on_js_errors: :off
345
+ expect_evaluate_ruby do
346
+ JS.call(:eval,
347
+ <<-JSCODE
348
+ window.NativeLibrary = {
349
+ NativeNestedLibrary: { }
350
+ }
351
+ JSCODE
352
+ )
353
+ begin
354
+ React::Test::Utils.render_component_into_document(NativeLibraryTestModule::NestedComponent, time_stamp: Time.now)
355
+ rescue Exception => e
356
+ e.message
357
+ end
358
+ end.to match(/could not import a react component named: NativeLibrary.NativeNestedLibrary.NativeComponent/)
359
+ end
360
+
361
+ it "a NativeLibrary::NestedLibrary::NativeComponent() call will not resolve to a toplevel module NativeComponent (was a bug)" do
362
+ evaluate_ruby do
363
+ module NativeComponent; end
364
+ JS.call(:eval,
365
+ <<-JSCODE
366
+ window.NativeLibrary = {
367
+ NativeNestedLibrary: {
368
+ NativeComponent: class extends React.Component {
369
+ constructor(props) {
370
+ super(props);
371
+ this.displayName = "HelloMessage";
372
+ }
373
+ render() { return React.createElement("div", null, "Hello ", this.props.name); }
374
+ }}}
375
+ JSCODE
376
+ )
377
+ class Foo < React::NativeLibrary
378
+ def render
379
+ NativeLibrary::NativeNestedLibrary::NativeComponent(name: 'Worksmaker')
380
+ end
381
+ end
382
+ React::Test::Utils.render_component_into_document(Foo)
383
+ end
384
+ expect(page.body[-80..-19]).to match(/<div>Hello Worksmaker<\/div>/)
385
+ end
386
+ end
387
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'React::Observable', js: true do
4
+ it "allows to set value on Observable" do
5
+ mount 'Foo' do
6
+ class Zoo
7
+ include React::Component
8
+ param :foo, type: React::Observable
9
+ before_mount do
10
+ params.foo! 4
11
+ end
12
+
13
+ def render
14
+ nil
15
+ end
16
+ end
17
+
18
+ class Foo
19
+ include React::Component
20
+
21
+ def render
22
+ div do
23
+ Zoo(foo: state.foo! )
24
+ span { state.foo.to_s }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ expect(page.body[-60..-19]).to include('<span></span><span>4</span>')
30
+ end
31
+ end