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.
- checksums.yaml +5 -5
- data/.codeclimate.yml +27 -0
- data/.gitignore +30 -37
- data/.rubocop.yml +1159 -0
- data/.travis.yml +32 -0
- data/Appraisals +31 -0
- data/CHANGELOG.md +143 -0
- data/DOCS.md +1515 -0
- data/Gemfile +2 -5
- data/LICENSE +19 -0
- data/README.md +5 -33
- data/Rakefile +25 -6
- data/UPGRADING.md +24 -0
- data/component-name-lookup.md +145 -0
- data/dciy.toml +3 -0
- data/dciy_prepare.sh +8 -0
- data/dciy_run.sh +10 -0
- data/hyper-react.gemspec +24 -18
- data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +3 -0
- data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/server_rendering.js +5 -0
- data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/test_application.rb +2 -0
- data/lib/generators/reactive_ruby/test_app/templates/boot.rb.erb +6 -0
- data/lib/generators/reactive_ruby/test_app/templates/script/rails +5 -0
- data/lib/generators/reactive_ruby/test_app/templates/test_application.rb.erb +13 -0
- data/lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +11 -0
- data/lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb +14 -0
- data/lib/generators/reactive_ruby/test_app/templates/views/layouts/test_layout.html.erb +0 -0
- data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +117 -0
- data/lib/hyper-react.rb +66 -4
- data/lib/rails-helpers/top_level_rails_component.rb +75 -0
- data/lib/react/api.rb +203 -0
- data/lib/react/callbacks.rb +41 -0
- data/lib/react/children.rb +30 -0
- data/lib/react/component.rb +177 -0
- data/lib/react/component/api.rb +69 -0
- data/lib/react/component/base.rb +13 -0
- data/lib/react/component/class_methods.rb +181 -0
- data/lib/react/component/dsl_instance_methods.rb +23 -0
- data/lib/react/component/params.rb +6 -0
- data/lib/react/component/props_wrapper.rb +78 -0
- data/lib/react/component/should_component_update.rb +99 -0
- data/lib/react/component/tags.rb +108 -0
- data/lib/react/config.rb +5 -0
- data/lib/react/config/client.rb.erb +19 -0
- data/lib/react/config/server.rb +23 -0
- data/lib/react/element.rb +150 -0
- data/lib/react/event.rb +76 -0
- data/lib/react/ext/hash.rb +9 -0
- data/lib/react/ext/opal-jquery/element.rb +26 -0
- data/lib/react/ext/string.rb +8 -0
- data/lib/react/hash.rb +13 -0
- data/lib/react/native_library.rb +87 -0
- data/lib/react/object.rb +15 -0
- data/lib/react/react-source-browser.rb +3 -0
- data/lib/react/react-source-server.rb +3 -0
- data/lib/react/react-source.rb +16 -0
- data/lib/react/ref_callback.rb +31 -0
- data/lib/react/rendering_context.rb +146 -0
- data/lib/react/server.rb +19 -0
- data/lib/react/state_wrapper.rb +23 -0
- data/lib/react/test.rb +16 -0
- data/lib/react/test/dsl.rb +17 -0
- data/lib/react/test/matchers/render_html_matcher.rb +56 -0
- data/lib/react/test/rspec.rb +15 -0
- data/lib/react/test/session.rb +37 -0
- data/lib/react/test/utils.rb +71 -0
- data/lib/react/top_level.rb +110 -0
- data/lib/react/top_level_render.rb +28 -0
- data/lib/react/validator.rb +136 -0
- data/lib/reactive-ruby/component_loader.rb +43 -0
- data/lib/reactive-ruby/isomorphic_helpers.rb +235 -0
- data/lib/reactive-ruby/rails.rb +8 -0
- data/lib/reactive-ruby/rails/component_mount.rb +48 -0
- data/lib/reactive-ruby/rails/controller_helper.rb +14 -0
- data/lib/reactive-ruby/rails/railtie.rb +20 -0
- data/lib/reactive-ruby/serializers.rb +15 -0
- data/lib/reactive-ruby/server_rendering/contextual_renderer.rb +41 -0
- data/lib/reactive-ruby/server_rendering/hyper_asset_container.rb +46 -0
- data/lib/reactive-ruby/version.rb +3 -0
- data/lib/reactrb/auto-import.rb +27 -0
- data/logo1.png +0 -0
- data/logo2.png +0 -0
- data/logo3.png +0 -0
- data/path_release_steps.md +9 -0
- data/spec/controller_helper_spec.rb +35 -0
- data/spec/index.html.erb +11 -0
- data/spec/react/callbacks_spec.rb +142 -0
- data/spec/react/children_spec.rb +132 -0
- data/spec/react/component/base_spec.rb +36 -0
- data/spec/react/component_spec.rb +1073 -0
- data/spec/react/dsl_spec.rb +323 -0
- data/spec/react/element_spec.rb +132 -0
- data/spec/react/event_spec.rb +39 -0
- data/spec/react/native_library_spec.rb +387 -0
- data/spec/react/observable_spec.rb +31 -0
- data/spec/react/opal_jquery_extensions_spec.rb +68 -0
- data/spec/react/param_declaration_spec.rb +253 -0
- data/spec/react/react_spec.rb +278 -0
- data/spec/react/refs_callback_spec.rb +65 -0
- data/spec/react/server_spec.rb +25 -0
- data/spec/react/state_spec.rb +52 -0
- data/spec/react/test/dsl_spec.rb +43 -0
- data/spec/react/test/matchers/render_html_matcher_spec.rb +83 -0
- data/spec/react/test/rspec_spec.rb +62 -0
- data/spec/react/test/session_spec.rb +88 -0
- data/spec/react/test/utils_spec.rb +28 -0
- data/spec/react/top_level_component_spec.rb +103 -0
- data/spec/react/tutorial/tutorial_spec.rb +42 -0
- data/spec/react/validator_spec.rb +134 -0
- data/spec/reactive-ruby/component_loader_spec.rb +74 -0
- data/spec/reactive-ruby/isomorphic_helpers_spec.rb +157 -0
- data/spec/reactive-ruby/rails/asset_pipeline_spec.rb +17 -0
- data/spec/reactive-ruby/rails/component_mount_spec.rb +64 -0
- data/spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb +39 -0
- data/spec/spec_helper.rb +55 -0
- data/spec/test_app/README.md +24 -0
- data/spec/test_app/Rakefile +6 -0
- data/spec/test_app/app/assets/config/manifest.js +3 -0
- data/spec/test_app/app/assets/images/.keep +0 -0
- data/spec/test_app/app/assets/javascripts/application.rb +7 -0
- data/spec/test_app/app/assets/javascripts/cable.js +13 -0
- data/spec/test_app/app/assets/javascripts/channels/.keep +0 -0
- data/spec/test_app/app/assets/javascripts/server_rendering.js +5 -0
- data/spec/test_app/app/assets/stylesheets/application.css +15 -0
- data/spec/test_app/app/channels/application_cable/channel.rb +4 -0
- data/spec/test_app/app/channels/application_cable/connection.rb +4 -0
- data/spec/test_app/app/controllers/application_controller.rb +3 -0
- data/spec/test_app/app/controllers/concerns/.keep +0 -0
- data/spec/test_app/app/helpers/application_helper.rb +2 -0
- data/spec/test_app/app/jobs/application_job.rb +2 -0
- data/spec/test_app/app/mailers/application_mailer.rb +4 -0
- data/spec/test_app/app/models/application_record.rb +3 -0
- data/spec/test_app/app/models/concerns/.keep +0 -0
- data/spec/test_app/app/views/components.rb +11 -0
- data/spec/test_app/app/views/components/hello_world.rb +11 -0
- data/spec/test_app/app/views/components/todo.rb +14 -0
- data/spec/test_app/app/views/layouts/application.html.erb +14 -0
- data/spec/test_app/app/views/layouts/explicit_layout.html.erb +0 -0
- data/spec/test_app/app/views/layouts/mailer.html.erb +13 -0
- data/spec/test_app/app/views/layouts/mailer.text.erb +1 -0
- data/spec/test_app/app/views/layouts/test_layout.html.erb +0 -0
- data/spec/test_app/bin/bundle +3 -0
- data/spec/test_app/bin/rails +4 -0
- data/spec/test_app/bin/rake +4 -0
- data/spec/test_app/bin/setup +38 -0
- data/spec/test_app/bin/update +29 -0
- data/spec/test_app/bin/yarn +11 -0
- data/spec/test_app/config.ru +5 -0
- data/spec/test_app/config/application.rb +45 -0
- data/spec/test_app/config/boot.rb +6 -0
- data/spec/test_app/config/cable.yml +10 -0
- data/spec/test_app/config/database.yml +25 -0
- data/spec/test_app/config/environment.rb +5 -0
- data/spec/test_app/config/environments/development.rb +54 -0
- data/spec/test_app/config/environments/production.rb +91 -0
- data/spec/test_app/config/environments/test.rb +42 -0
- data/spec/test_app/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/test_app/config/initializers/assets.rb +14 -0
- data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_app/config/initializers/cookies_serializer.rb +5 -0
- data/spec/test_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/test_app/config/initializers/inflections.rb +16 -0
- data/spec/test_app/config/initializers/mime_types.rb +4 -0
- data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/test_app/config/locales/en.yml +33 -0
- data/spec/test_app/config/puma.rb +56 -0
- data/spec/test_app/config/routes.rb +3 -0
- data/spec/test_app/config/secrets.yml +32 -0
- data/spec/test_app/config/spring.rb +6 -0
- data/spec/test_app/db/development.sqlite3 +0 -0
- data/spec/test_app/db/schema.rb +15 -0
- data/spec/test_app/db/seeds.rb +7 -0
- data/spec/test_app/db/test.sqlite3 +0 -0
- data/spec/test_app/lib/assets/.keep +0 -0
- data/spec/test_app/log/.keep +0 -0
- data/spec/test_app/package.json +5 -0
- data/spec/test_app/public/404.html +67 -0
- data/spec/test_app/public/422.html +67 -0
- data/spec/test_app/public/500.html +66 -0
- data/spec/test_app/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/test_app/public/apple-touch-icon.png +0 -0
- data/spec/test_app/public/favicon.ico +0 -0
- data/spec/vendor/es5-shim.min.js +7 -0
- data/spec/vendor/jquery-2.2.4.min.js +4 -0
- metadata +401 -61
- data/CODE_OF_CONDUCT.md +0 -49
- 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
|