reactrb 0.7.42
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 +7 -0
- data/.codeclimate.yml +6 -0
- data/.gitignore +33 -0
- data/.travis.yml +9 -0
- data/Gemfile +2 -0
- data/LICENSE +19 -0
- data/README.md +117 -0
- data/Rakefile +28 -0
- data/config.ru +16 -0
- data/example/examples/Gemfile +7 -0
- data/example/examples/app/basics.js.rb +42 -0
- data/example/examples/app/items.rb +11 -0
- data/example/examples/app/jquery.js +5 -0
- data/example/examples/app/nodes.rb +61 -0
- data/example/examples/app/react-router.js +6 -0
- data/example/examples/app/react_api_demo.rb +29 -0
- data/example/examples/app/rerendering.rb +72 -0
- data/example/examples/app/reuse.rb +59 -0
- data/example/examples/app/show.rb +52 -0
- data/example/examples/config.ru +38 -0
- data/example/rails-tutorial/.gitignore +17 -0
- data/example/rails-tutorial/Gemfile +51 -0
- data/example/rails-tutorial/README.rdoc +28 -0
- data/example/rails-tutorial/Rakefile +6 -0
- data/example/rails-tutorial/app/assets/images/.keep +0 -0
- data/example/rails-tutorial/app/assets/javascripts/application.rb +15 -0
- data/example/rails-tutorial/app/assets/stylesheets/application.css +15 -0
- data/example/rails-tutorial/app/controllers/application_controller.rb +6 -0
- data/example/rails-tutorial/app/controllers/concerns/.keep +0 -0
- data/example/rails-tutorial/app/controllers/home_controller.rb +6 -0
- data/example/rails-tutorial/app/helpers/application_helper.rb +2 -0
- data/example/rails-tutorial/app/mailers/.keep +0 -0
- data/example/rails-tutorial/app/models/.keep +0 -0
- data/example/rails-tutorial/app/models/concerns/.keep +0 -0
- data/example/rails-tutorial/app/views/components.rb +3 -0
- data/example/rails-tutorial/app/views/components/home/show.rb +47 -0
- data/example/rails-tutorial/app/views/layouts/application.html.erb +14 -0
- data/example/rails-tutorial/bin/bundle +3 -0
- data/example/rails-tutorial/bin/rails +8 -0
- data/example/rails-tutorial/bin/rake +8 -0
- data/example/rails-tutorial/bin/setup +29 -0
- data/example/rails-tutorial/bin/spring +15 -0
- data/example/rails-tutorial/config.ru +4 -0
- data/example/rails-tutorial/config/application.rb +26 -0
- data/example/rails-tutorial/config/boot.rb +3 -0
- data/example/rails-tutorial/config/database.yml +25 -0
- data/example/rails-tutorial/config/environment.rb +5 -0
- data/example/rails-tutorial/config/environments/development.rb +41 -0
- data/example/rails-tutorial/config/environments/production.rb +79 -0
- data/example/rails-tutorial/config/environments/test.rb +42 -0
- data/example/rails-tutorial/config/initializers/assets.rb +11 -0
- data/example/rails-tutorial/config/initializers/backtrace_silencers.rb +7 -0
- data/example/rails-tutorial/config/initializers/cookies_serializer.rb +3 -0
- data/example/rails-tutorial/config/initializers/filter_parameter_logging.rb +4 -0
- data/example/rails-tutorial/config/initializers/inflections.rb +16 -0
- data/example/rails-tutorial/config/initializers/mime_types.rb +4 -0
- data/example/rails-tutorial/config/initializers/session_store.rb +3 -0
- data/example/rails-tutorial/config/initializers/wrap_parameters.rb +14 -0
- data/example/rails-tutorial/config/locales/en.yml +23 -0
- data/example/rails-tutorial/config/routes.rb +59 -0
- data/example/rails-tutorial/config/secrets.yml +22 -0
- data/example/rails-tutorial/db/seeds.rb +7 -0
- data/example/rails-tutorial/lib/assets/.keep +0 -0
- data/example/rails-tutorial/lib/tasks/.keep +0 -0
- data/example/rails-tutorial/log/.keep +0 -0
- data/example/rails-tutorial/public/404.html +67 -0
- data/example/rails-tutorial/public/422.html +67 -0
- data/example/rails-tutorial/public/500.html +66 -0
- data/example/rails-tutorial/public/favicon.ico +0 -0
- data/example/rails-tutorial/public/robots.txt +5 -0
- data/example/rails-tutorial/test/controllers/.keep +0 -0
- data/example/rails-tutorial/test/fixtures/.keep +0 -0
- data/example/rails-tutorial/test/helpers/.keep +0 -0
- data/example/rails-tutorial/test/integration/.keep +0 -0
- data/example/rails-tutorial/test/mailers/.keep +0 -0
- data/example/rails-tutorial/test/models/.keep +0 -0
- data/example/rails-tutorial/test/test_helper.rb +10 -0
- data/example/rails-tutorial/vendor/assets/javascripts/.keep +0 -0
- data/example/rails-tutorial/vendor/assets/stylesheets/.keep +0 -0
- data/example/sinatra-tutorial/.DS_Store +0 -0
- data/example/sinatra-tutorial/Gemfile +5 -0
- data/example/sinatra-tutorial/README.md +8 -0
- data/example/sinatra-tutorial/_comments.json +42 -0
- data/example/sinatra-tutorial/app/example.rb +290 -0
- data/example/sinatra-tutorial/app/jquery.js +5 -0
- data/example/sinatra-tutorial/config.ru +58 -0
- data/example/sinatra-tutorial/public/base.css +62 -0
- data/example/todos/Gemfile +11 -0
- data/example/todos/README.md +37 -0
- data/example/todos/Rakefile +8 -0
- data/example/todos/app/application.rb +22 -0
- data/example/todos/app/components/app.react.rb +61 -0
- data/example/todos/app/components/footer.react.rb +31 -0
- data/example/todos/app/components/todo_item.react.rb +46 -0
- data/example/todos/app/components/todo_list.react.rb +25 -0
- data/example/todos/app/models/todo.rb +19 -0
- data/example/todos/config.ru +14 -0
- data/example/todos/index.html.haml +16 -0
- data/example/todos/spec/todo_spec.rb +28 -0
- data/example/todos/vendor/base.css +410 -0
- data/example/todos/vendor/bg.png +0 -0
- data/example/todos/vendor/jquery.js +4 -0
- data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +4 -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/test_app_generator.rb +105 -0
- data/lib/rails-helpers/top_level_rails_component.rb +54 -0
- data/lib/react/api.rb +127 -0
- data/lib/react/callbacks.rb +42 -0
- data/lib/react/component.rb +269 -0
- data/lib/react/component/api.rb +50 -0
- data/lib/react/component/base.rb +9 -0
- data/lib/react/component/class_methods.rb +190 -0
- data/lib/react/component/props_wrapper.rb +82 -0
- data/lib/react/element.rb +77 -0
- data/lib/react/event.rb +76 -0
- data/lib/react/ext/hash.rb +9 -0
- data/lib/react/ext/string.rb +8 -0
- data/lib/react/native_library.rb +53 -0
- data/lib/react/observable.rb +29 -0
- data/lib/react/rendering_context.rb +109 -0
- data/lib/react/state.rb +140 -0
- data/lib/react/top_level.rb +97 -0
- data/lib/react/validator.rb +136 -0
- data/lib/reactive-ruby/component_loader.rb +45 -0
- data/lib/reactive-ruby/isomorphic_helpers.rb +196 -0
- data/lib/reactive-ruby/rails.rb +7 -0
- data/lib/reactive-ruby/rails/component_mount.rb +44 -0
- data/lib/reactive-ruby/rails/controller_helper.rb +13 -0
- data/lib/reactive-ruby/rails/railtie.rb +14 -0
- data/lib/reactive-ruby/serializers.rb +15 -0
- data/lib/reactive-ruby/server_rendering/contextual_renderer.rb +42 -0
- data/lib/reactive-ruby/version.rb +3 -0
- data/lib/reactrb.rb +50 -0
- data/lib/sources/react-latest.js +21167 -0
- data/lib/sources/react-v13.js +21642 -0
- data/lib/sources/react-v14.js +20818 -0
- data/lib/sources/react-v15.js +21167 -0
- data/logo1.png +0 -0
- data/logo2.png +0 -0
- data/logo3.png +0 -0
- data/path_release_steps.md +9 -0
- data/reactrb.gemspec +43 -0
- data/spec/controller_helper_spec.rb +22 -0
- data/spec/index.html.erb +12 -0
- data/spec/react/callbacks_spec.rb +106 -0
- data/spec/react/component/base_spec.rb +36 -0
- data/spec/react/component_spec.rb +721 -0
- data/spec/react/dsl_spec.rb +161 -0
- data/spec/react/element_spec.rb +47 -0
- data/spec/react/event_spec.rb +24 -0
- data/spec/react/native_library_spec.rb +10 -0
- data/spec/react/observable_spec.rb +7 -0
- data/spec/react/param_declaration_spec.rb +286 -0
- data/spec/react/react_spec.rb +211 -0
- data/spec/react/state_spec.rb +26 -0
- data/spec/react/top_level_component_spec.rb +68 -0
- data/spec/react/tutorial/tutorial_spec.rb +35 -0
- data/spec/react/validator_spec.rb +128 -0
- data/spec/reactive-ruby/component_loader_spec.rb +68 -0
- data/spec/reactive-ruby/isomorphic_helpers_spec.rb +155 -0
- data/spec/reactive-ruby/rails/asset_pipeline_spec.rb +9 -0
- data/spec/reactive-ruby/rails/component_mount_spec.rb +66 -0
- data/spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb +35 -0
- data/spec/spec_helper.rb +109 -0
- data/spec/support/react/spec_helpers.rb +57 -0
- data/spec/vendor/es5-shim.min.js +6 -0
- data/spec/vendor/jquery-2.2.4.min.js +4 -0
- metadata +441 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
describe 'the React DSL' do
|
|
5
|
+
|
|
6
|
+
it "will turn the last string in a block into a element" do
|
|
7
|
+
stub_const 'Foo', Class.new
|
|
8
|
+
Foo.class_eval do
|
|
9
|
+
include React::Component
|
|
10
|
+
def render
|
|
11
|
+
div { "hello" }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
expect(React.render_to_static_markup(React.create_element(Foo))).to eq('<div>hello</div>')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "has a .span short hand String method" do
|
|
19
|
+
stub_const 'Foo', Class.new
|
|
20
|
+
Foo.class_eval do
|
|
21
|
+
include React::Component
|
|
22
|
+
def render
|
|
23
|
+
div { "hello".span; "goodby".span }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
expect(React.render_to_static_markup(React.create_element(Foo))).to eq('<div><span>hello</span><span>goodby</span></div>')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "has a .br short hand String method" do
|
|
31
|
+
stub_const 'Foo', Class.new
|
|
32
|
+
Foo.class_eval do
|
|
33
|
+
include React::Component
|
|
34
|
+
def render
|
|
35
|
+
div { "hello".br }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
expect(React.render_to_static_markup(React.create_element(Foo)).gsub("<br/>", "<br>")).to eq('<div><span>hello<br></span></div>')
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "has a .td short hand String method" do
|
|
43
|
+
stub_const 'Foo', Class.new
|
|
44
|
+
Foo.class_eval do
|
|
45
|
+
include React::Component
|
|
46
|
+
def render
|
|
47
|
+
table { tr { "hello".td } }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
expect(React.render_to_static_markup(React.create_element(Foo))).to eq('<table><tr><td>hello</td></tr></table>')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "has a .para short hand String method" do
|
|
55
|
+
stub_const 'Foo', Class.new
|
|
56
|
+
Foo.class_eval do
|
|
57
|
+
include React::Component
|
|
58
|
+
def render
|
|
59
|
+
div { "hello".para }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
expect(React.render_to_static_markup(React.create_element(Foo))).to eq('<div><p>hello</p></div>')
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "will treat the component class name as a first class component name" do
|
|
67
|
+
stub_const 'Mod::Bar', Class.new
|
|
68
|
+
Mod::Bar.class_eval do
|
|
69
|
+
include React::Component
|
|
70
|
+
def render
|
|
71
|
+
"a man walks into a bar"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
75
|
+
Foo.class_eval do
|
|
76
|
+
def render
|
|
77
|
+
Mod::Bar()
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
expect(React.render_to_static_markup(React.create_element(Foo))).to eq('<span>a man walks into a bar</span>')
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "can add class names by the haml .class notation" do
|
|
85
|
+
stub_const 'Mod::Bar', Class.new(React::Component::Base)
|
|
86
|
+
Mod::Bar.class_eval do
|
|
87
|
+
collect_other_params_as :attributes
|
|
88
|
+
def render
|
|
89
|
+
"a man walks into a bar".span(attributes)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
93
|
+
Foo.class_eval do
|
|
94
|
+
def render
|
|
95
|
+
Mod::Bar().the_class
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
expect(React.render_to_static_markup(React.create_element(Foo))).to eq('<span class="the-class">a man walks into a bar</span>')
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "can use the 'class' keyword for classes" do
|
|
103
|
+
stub_const 'Foo', Class.new
|
|
104
|
+
Foo.class_eval do
|
|
105
|
+
include React::Component
|
|
106
|
+
def render
|
|
107
|
+
span(class: "the-class") { "hello" }
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
expect(React.render_to_static_markup(React.create_element(Foo))).to eq('<span class="the-class">hello</span>')
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "can generate a unrendered node using the .as_node method" do # div { "hello" }.as_node
|
|
115
|
+
stub_const 'Foo', Class.new #(React::Component::Base)
|
|
116
|
+
Foo.class_eval do
|
|
117
|
+
include React::Component
|
|
118
|
+
def render
|
|
119
|
+
span { "hello".span.as_node.class.name }.as_node.render
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
expect(React.render_to_static_markup(React.create_element(Foo))).to eq('<span>React::Element</span>')
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "can use the dangerously_set_inner_HTML param" do
|
|
127
|
+
stub_const 'Foo', Class.new
|
|
128
|
+
Foo.class_eval do
|
|
129
|
+
include React::Component
|
|
130
|
+
def render
|
|
131
|
+
div(dangerously_set_inner_HTML: { __html: "Hello Goodby" })
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
expect(React.render_to_static_markup(React.create_element(Foo))).to eq('<div>Hello Goodby</div>')
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "will remove all elements passed as params from the rendering buffer" do
|
|
139
|
+
stub_const 'X2', Class.new
|
|
140
|
+
X2.class_eval do
|
|
141
|
+
include React::Component
|
|
142
|
+
param :ele
|
|
143
|
+
def render
|
|
144
|
+
div do
|
|
145
|
+
ele.render
|
|
146
|
+
ele.render
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
stub_const 'Test', Class.new
|
|
151
|
+
Test.class_eval do
|
|
152
|
+
include React::Component
|
|
153
|
+
def render
|
|
154
|
+
X2(ele: b { "hello" })
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
expect(React.render_to_static_markup(React.create_element(Test))).to eq('<div><b>hello</b><b>hello</b></div>')
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
describe React::Element do
|
|
5
|
+
it 'bridges `type` of native React.Element attributes' do
|
|
6
|
+
element = React.create_element('div')
|
|
7
|
+
expect(element.element_type).to eq("div")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
async 'is renderable' do
|
|
11
|
+
element = React.create_element('span')
|
|
12
|
+
div = `document.createElement("div")`
|
|
13
|
+
React.render(element, div) do
|
|
14
|
+
run_async {
|
|
15
|
+
expect(`div.children[0].tagName`).to eq("SPAN")
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe 'Event subscription' do
|
|
21
|
+
it 'is subscribable through `on(:event_name)` method' do
|
|
22
|
+
expect { |b|
|
|
23
|
+
element = React.create_element("div").on(:click, &b)
|
|
24
|
+
instance = renderElementToDocument(element)
|
|
25
|
+
simulateEvent(:click, instance)
|
|
26
|
+
}.to yield_with_args(React::Event)
|
|
27
|
+
|
|
28
|
+
expect { |b|
|
|
29
|
+
element = React.create_element("div").on(:key_down, &b)
|
|
30
|
+
instance = renderElementToDocument(element)
|
|
31
|
+
simulateEvent(:keyDown, instance, {key: "Enter"})
|
|
32
|
+
}.to yield_control
|
|
33
|
+
|
|
34
|
+
expect { |b|
|
|
35
|
+
element = React.create_element("form").on(:submit, &b)
|
|
36
|
+
instance = renderElementToDocument(element)
|
|
37
|
+
simulateEvent(:submit, instance, {})
|
|
38
|
+
}.to yield_control
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'returns self for `on` method' do
|
|
42
|
+
element = React.create_element("div")
|
|
43
|
+
expect(element.on(:click){}).to eq(element)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
describe React::Event do
|
|
5
|
+
it "should bridge attributes of native SyntheticEvent (see http://facebook.github.io/react/docs/events.html#syntheticevent)" do
|
|
6
|
+
element = React.create_element('div').on(:click) do |event|
|
|
7
|
+
expect(event.bubbles).to eq(`#{event.to_n}.bubbles`)
|
|
8
|
+
expect(event.cancelable).to eq(`#{event.to_n}.cancelable`)
|
|
9
|
+
expect(event.current_target).to eq(`#{event.to_n}.currentTarget`)
|
|
10
|
+
expect(event.default_prevented).to eq(`#{event.to_n}.defaultPrevented`)
|
|
11
|
+
expect(event.event_phase).to eq(`#{event.to_n}.eventPhase`)
|
|
12
|
+
expect(event.is_trusted?).to eq(`#{event.to_n}.isTrusted`)
|
|
13
|
+
expect(event.native_event).to eq(`#{event.to_n}.nativeEvent`)
|
|
14
|
+
expect(event.target).to eq(`#{event.to_n}.target`)
|
|
15
|
+
expect(event.timestamp).to eq(`#{event.to_n}.timeStamp`)
|
|
16
|
+
expect(event.event_type).to eq(`#{event.to_n}.type`)
|
|
17
|
+
expect(event).to respond_to(:prevent_default)
|
|
18
|
+
expect(event).to respond_to(:stop_propagation)
|
|
19
|
+
end
|
|
20
|
+
instance = renderElementToDocument(element)
|
|
21
|
+
simulateEvent(:click, instance)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
describe React::NativeLibrary do
|
|
5
|
+
it "will import a React.js library into the Ruby name space" # class BS < NativeLibrary; imports 'ReactBootstrap'; end
|
|
6
|
+
it "exclude specific components from a library" # exclude "Modal" # can't access BS.Modal
|
|
7
|
+
it "rename specific components from a library" # rename "Modal" => "FooBar" # BS.FooBar connects to ReactBootstrap.Modal
|
|
8
|
+
it "can importan multiple libraries into one class"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
describe 'the param macro' do
|
|
5
|
+
it 'defines collect_other_params_as method on params proxy' do
|
|
6
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
7
|
+
Foo.class_eval do
|
|
8
|
+
collect_other_params_as :foo
|
|
9
|
+
|
|
10
|
+
def render
|
|
11
|
+
div { params.foo[:bar] }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
html = React.render_to_static_markup(React.create_element(Foo, { bar: 'biz' }))
|
|
16
|
+
expect(html).to eq('<div>biz</div>')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'still defines deprecated collect_other_params_as method' do
|
|
20
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
21
|
+
Foo.class_eval do
|
|
22
|
+
collect_other_params_as :foo
|
|
23
|
+
|
|
24
|
+
def render
|
|
25
|
+
div { foo[:bar] }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
html = React.render_to_static_markup(React.create_element(Foo, { bar: 'biz' }))
|
|
30
|
+
expect(html).to eq('<div>biz</div>')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'still defines deprecated param accessor method' do
|
|
34
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
35
|
+
Foo.class_eval do
|
|
36
|
+
param :foo
|
|
37
|
+
|
|
38
|
+
def render
|
|
39
|
+
div { foo }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
html = React.render_to_static_markup(React.create_element(Foo, {foo: :bar}))
|
|
44
|
+
expect(html).to eq('<div>bar</div>')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "can create and access a required param" do
|
|
48
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
49
|
+
Foo.class_eval do
|
|
50
|
+
param :foo
|
|
51
|
+
|
|
52
|
+
def render
|
|
53
|
+
div { params.foo }
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
expect(React.render_to_static_markup(React.create_element(Foo, {foo: :bar}))).to eq('<div>bar</div>')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "can create and access an optional params" do
|
|
61
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
62
|
+
Foo.class_eval do
|
|
63
|
+
|
|
64
|
+
param foo1: :no_bar1
|
|
65
|
+
param foo2: :no_bar2
|
|
66
|
+
param :foo3, default: :no_bar3
|
|
67
|
+
param :foo4, default: :no_bar4
|
|
68
|
+
|
|
69
|
+
def render
|
|
70
|
+
div { "#{params.foo1}-#{params.foo2}-#{params.foo3}-#{params.foo4}" }
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
expect(React.render_to_static_markup(React.create_element(Foo, {foo1: :bar1, foo3: :bar3}))).to eq('<div>bar1-no_bar2-bar3-no_bar4</div>')
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'can specify validation rules with the type option' do
|
|
78
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
79
|
+
Foo.class_eval do
|
|
80
|
+
param :foo, type: String
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
expect(Foo.prop_types).to have_key(:_componentValidator)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "can type check params" do
|
|
87
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
88
|
+
Foo.class_eval do
|
|
89
|
+
|
|
90
|
+
param :foo1, type: String
|
|
91
|
+
param :foo2, type: String
|
|
92
|
+
|
|
93
|
+
def render
|
|
94
|
+
div { "#{params.foo1}-#{params.foo2}" }
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
expect(React.render_to_static_markup(React.create_element(Foo, {foo1: 12, foo2: "string"}))).to eq('<div>12-string</div>')
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'logs error in warning if validation failed' do
|
|
102
|
+
stub_const 'Lorem', Class.new
|
|
103
|
+
stub_const 'Foo2', Class.new(React::Component::Base)
|
|
104
|
+
Foo2.class_eval do
|
|
105
|
+
param :foo
|
|
106
|
+
param :lorem, type: Lorem
|
|
107
|
+
param :bar, default: nil, type: String
|
|
108
|
+
def render; div; end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
%x{
|
|
112
|
+
var log = [];
|
|
113
|
+
var org_warn_console = window.console.warn;
|
|
114
|
+
var org_error_console = window.console.error;
|
|
115
|
+
window.console.warn = window.console.error = function(str){log.push(str)}
|
|
116
|
+
}
|
|
117
|
+
renderToDocument(Foo2, bar: 10, lorem: Lorem.new)
|
|
118
|
+
`window.console.warn = org_warn_console; window.console.error = org_error_console;`
|
|
119
|
+
|
|
120
|
+
expect(`log`).to eq(["Warning: Failed propType: In component `Foo2`\nRequired prop `foo` was not specified\nProvided prop `bar` could not be converted to String"])
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'should not log anything if validation passes' do
|
|
124
|
+
stub_const 'Lorem', Class.new
|
|
125
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
126
|
+
Foo.class_eval do
|
|
127
|
+
param :foo
|
|
128
|
+
param :lorem, type: Lorem
|
|
129
|
+
param :bar, default: nil, type: String
|
|
130
|
+
|
|
131
|
+
def render; div; end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
%x{
|
|
135
|
+
var log = [];
|
|
136
|
+
var org_warn_console = window.console.warn;
|
|
137
|
+
var org_error_console = window.console.error;
|
|
138
|
+
window.console.warn = window.console.error = function(str){log.push(str)}
|
|
139
|
+
}
|
|
140
|
+
renderToDocument(Foo, foo: 10, bar: '10', lorem: Lorem.new)
|
|
141
|
+
`window.console.warn = org_warn_console; window.console.error = org_error_console;`
|
|
142
|
+
expect(`log`).to eq([])
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
describe 'advanced type handling' do
|
|
146
|
+
before(:each) do
|
|
147
|
+
%x{
|
|
148
|
+
window.dummy_log = [];
|
|
149
|
+
window.org_warn_console = window.console.warn;
|
|
150
|
+
window.org_error_console = window.console.warn
|
|
151
|
+
window.console.warn = window.console.error = function(str){window.dummy_log.push(str)}
|
|
152
|
+
}
|
|
153
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
|
154
|
+
Foo.class_eval { def render; ""; end }
|
|
155
|
+
end
|
|
156
|
+
after(:each) do
|
|
157
|
+
`window.console.warn = window.org_warn_console; window.console.error = window.org_error_console`
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "can use the [] notation for arrays" do
|
|
161
|
+
Foo.class_eval do
|
|
162
|
+
param :foo, type: []
|
|
163
|
+
param :bar, type: []
|
|
164
|
+
end
|
|
165
|
+
renderToDocument(Foo, foo: 10, bar: [10])
|
|
166
|
+
expect(`window.dummy_log`).to eq(["Warning: Failed propType: In component `Foo`\nProvided prop `foo` could not be converted to Array"])
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "can use the [xxx] notation for arrays of a specific type" do
|
|
170
|
+
Foo.class_eval do
|
|
171
|
+
param :foo, type: [String]
|
|
172
|
+
param :bar, type: [String]
|
|
173
|
+
end
|
|
174
|
+
renderToDocument(Foo, foo: [10], bar: ["10"])
|
|
175
|
+
expect(`window.dummy_log`).to eq(["Warning: Failed propType: In component `Foo`\nProvided prop `foo`[0] could not be converted to String"])
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it "can convert a json hash to a type" do
|
|
179
|
+
stub_const "BazWoggle", Class.new
|
|
180
|
+
BazWoggle.class_eval do
|
|
181
|
+
def initialize(kind)
|
|
182
|
+
@kind = kind
|
|
183
|
+
end
|
|
184
|
+
attr_accessor :kind
|
|
185
|
+
def self._react_param_conversion(json, validate_only)
|
|
186
|
+
new(json[:bazwoggle]) if json[:bazwoggle]
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
Foo.class_eval do
|
|
190
|
+
param :foo, type: BazWoggle
|
|
191
|
+
param :bar, type: BazWoggle
|
|
192
|
+
param :baz, type: [BazWoggle]
|
|
193
|
+
def render
|
|
194
|
+
"#{params.bar.kind}, #{params.baz[0].kind}"
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
expect(React.render_to_static_markup(React.create_element(
|
|
198
|
+
Foo, foo: "", bar: {bazwoggle: 1}, baz: [{bazwoggle: 2}]))).to eq('<span>1, 2</span>')
|
|
199
|
+
expect(`window.dummy_log`).to eq(["Warning: Failed propType: In component `Foo`\nProvided prop `foo` could not be converted to BazWoggle"])
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
describe "converts params only once" do
|
|
203
|
+
|
|
204
|
+
it "not on every access" do
|
|
205
|
+
stub_const "BazWoggle", Class.new
|
|
206
|
+
BazWoggle.class_eval do
|
|
207
|
+
def initialize(kind)
|
|
208
|
+
@kind = kind
|
|
209
|
+
end
|
|
210
|
+
attr_accessor :kind
|
|
211
|
+
def self._react_param_conversion(json, validate_only)
|
|
212
|
+
new(json[:bazwoggle]) if json[:bazwoggle]
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
Foo.class_eval do
|
|
216
|
+
param :foo, type: BazWoggle
|
|
217
|
+
def render
|
|
218
|
+
params.foo.kind = params.foo.kind+1
|
|
219
|
+
"#{params.foo.kind}"
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
expect(React.render_to_static_markup(React.create_element(Foo, foo: {bazwoggle: 1}))).to eq('<span>2</span>')
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "even if contains an embedded native object" do
|
|
226
|
+
stub_const "Bar", Class.new(React::Component::Base)
|
|
227
|
+
stub_const "BazWoggle", Class.new
|
|
228
|
+
BazWoggle.class_eval do
|
|
229
|
+
def initialize(kind)
|
|
230
|
+
@kind = kind
|
|
231
|
+
end
|
|
232
|
+
attr_accessor :kind
|
|
233
|
+
def self._react_param_conversion(json, validate_only)
|
|
234
|
+
new(JSON.from_object(json[0])[:bazwoggle]) if JSON.from_object(json[0])[:bazwoggle]
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
Bar.class_eval do
|
|
238
|
+
param :foo, type: BazWoggle
|
|
239
|
+
def render
|
|
240
|
+
params.foo.kind.to_s
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
Foo.class_eval do
|
|
244
|
+
export_state :change_me
|
|
245
|
+
before_mount do
|
|
246
|
+
Foo.change_me! "initial"
|
|
247
|
+
end
|
|
248
|
+
def render
|
|
249
|
+
Bar(foo: Native([`{bazwoggle: #{Foo.change_me}}`]))
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
div = `document.createElement("div")`
|
|
253
|
+
React.render(React.create_element(Foo, {}), div)
|
|
254
|
+
Foo.change_me! "updated"
|
|
255
|
+
expect(`div.children[0].innerHTML`).to eq("updated")
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it "will alias a Proc type param" do
|
|
260
|
+
Foo.class_eval do
|
|
261
|
+
param :foo, type: Proc
|
|
262
|
+
def render
|
|
263
|
+
params.foo
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
expect(React.render_to_static_markup(React.create_element(Foo, foo: lambda { 'works!' }))).to eq('<span>works!</span>')
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it "will create a 'bang' (i.e. update) method if the type is React::Observable" do
|
|
270
|
+
Foo.class_eval do
|
|
271
|
+
param :foo, type: React::Observable
|
|
272
|
+
before_mount do
|
|
273
|
+
params.foo! "ha!"
|
|
274
|
+
end
|
|
275
|
+
def render
|
|
276
|
+
params.foo
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
current_state = ""
|
|
280
|
+
observer = React::Observable.new(current_state) { |new_state| current_state = new_state }
|
|
281
|
+
expect(React.render_to_static_markup(React.create_element(Foo, foo: observer))).to eq('<span>ha!</span>')
|
|
282
|
+
expect(current_state).to eq("ha!")
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|