reactrb 0.7.42
Sign up to get free protection for your applications and to get access to all the features.
- 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,211 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
if opal?
|
4
|
+
describe React do
|
5
|
+
after(:each) do
|
6
|
+
React::API.clear_component_class_cache
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "is_valid_element" do
|
10
|
+
it "should return true if passed a valid element" do
|
11
|
+
element = React::Element.new(`React.createElement('div')`)
|
12
|
+
expect(React.is_valid_element(element)).to eq(true)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return false is passed a non React element" do
|
16
|
+
element = React::Element.new(`{}`)
|
17
|
+
expect(React.is_valid_element(element)).to eq(false)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "create_element" do
|
22
|
+
it "should create a valid element with only tag" do
|
23
|
+
element = React.create_element('div')
|
24
|
+
expect(React.is_valid_element(element)).to eq(true)
|
25
|
+
end
|
26
|
+
|
27
|
+
context "with block" do
|
28
|
+
it "should create a valid element with text as only child when block yield String" do
|
29
|
+
element = React.create_element('div') { "lorem ipsum" }
|
30
|
+
expect(React.is_valid_element(element)).to eq(true)
|
31
|
+
expect(element.props.children).to eq("lorem ipsum")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should create a valid element with children as array when block yield Array of element" do
|
35
|
+
element = React.create_element('div') do
|
36
|
+
[React.create_element('span'), React.create_element('span'), React.create_element('span')]
|
37
|
+
end
|
38
|
+
expect(React.is_valid_element(element)).to eq(true)
|
39
|
+
expect(element.props.children.length).to eq(3)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should render element with children as array when block yield Array of element" do
|
43
|
+
element = React.create_element('div') do
|
44
|
+
[React.create_element('span'), React.create_element('span'), React.create_element('span')]
|
45
|
+
end
|
46
|
+
instance = renderElementToDocument(element)
|
47
|
+
expect(Element[instance].children.length).to eq(3)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "custom element" do
|
52
|
+
before do
|
53
|
+
stub_const 'Foo', Class.new
|
54
|
+
Foo.class_eval do
|
55
|
+
def render
|
56
|
+
React.create_element("div") { "lorem" }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should render element with only one children correctly" do
|
62
|
+
element = React.create_element(Foo) { React.create_element('span') }
|
63
|
+
instance = renderElementToDocument(element)
|
64
|
+
expect(instance.props.children).not_to be_a(Array)
|
65
|
+
expect(instance.props.children.type).to eq("span")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should render element with more than one children correctly" do
|
69
|
+
element = React.create_element(Foo) { [React.create_element('span'), React.create_element('span')] }
|
70
|
+
instance = renderElementToDocument(element)
|
71
|
+
expect(instance.props.children).to be_a(Array)
|
72
|
+
expect(instance.props.children.length).to eq(2)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should create a valid element provided class defined `render`" do
|
76
|
+
element = React.create_element(Foo)
|
77
|
+
expect(React.is_valid_element(element)).to eq(true)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should allow creating with properties" do
|
81
|
+
element = React.create_element(Foo, foo: "bar")
|
82
|
+
expect(element.props.foo).to eq("bar")
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should raise error if provided class doesn't defined `render`" do
|
86
|
+
expect { React.create_element(Array) }.to raise_error
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should use the same instance for the same ReactComponent" do
|
90
|
+
Foo.class_eval do
|
91
|
+
attr_accessor :a
|
92
|
+
def initialize(n)
|
93
|
+
self.a = 10
|
94
|
+
end
|
95
|
+
|
96
|
+
def component_will_mount
|
97
|
+
self.a = 20
|
98
|
+
end
|
99
|
+
|
100
|
+
def render
|
101
|
+
React.create_element("div") { self.a.to_s }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
expect(React.render_to_static_markup(React.create_element(Foo))).to eq("<div>20</div>")
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should match the instance cycle to ReactComponent life cycle" do
|
109
|
+
`var count = 0;`
|
110
|
+
|
111
|
+
Foo.class_eval do
|
112
|
+
def initialize
|
113
|
+
`count = count + 1;`
|
114
|
+
end
|
115
|
+
def render
|
116
|
+
React.create_element("div")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
renderToDocument(Foo)
|
121
|
+
renderToDocument(Foo)
|
122
|
+
|
123
|
+
expect(`count`).to eq(2)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "create element with properties" do
|
128
|
+
it "should enforce snake-cased property name" do
|
129
|
+
element = React.create_element("div", class_name: "foo")
|
130
|
+
expect(element.props.className).to eq("foo")
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should allow custom property" do
|
134
|
+
element = React.create_element("div", foo: "bar")
|
135
|
+
expect(element.props.foo).to eq("bar")
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should not camel-case custom property" do
|
139
|
+
element = React.create_element("div", foo_bar: "foo")
|
140
|
+
expect(element.props.foo_bar).to eq("foo")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "class_name helpers (React.addons.classSet)" do
|
145
|
+
|
146
|
+
# deprecated as of React 14
|
147
|
+
# it "should transform Hash provided to `class_name` props as string" do
|
148
|
+
# classes = {foo: true, bar: false, lorem: true}
|
149
|
+
# element = React.create_element("div", class_name: classes)
|
150
|
+
# expect(element.props.className).to eq("foo lorem")
|
151
|
+
# end
|
152
|
+
|
153
|
+
it "should not alter behavior when passing a string" do
|
154
|
+
element = React.create_element("div", class_name: "foo bar")
|
155
|
+
|
156
|
+
expect(element.props.className).to eq("foo bar")
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "render" do
|
162
|
+
async "should render element to DOM" do
|
163
|
+
div = `document.createElement("div")`
|
164
|
+
React.render(React.create_element('span') { "lorem" }, div) do
|
165
|
+
run_async {
|
166
|
+
expect(`div.children[0].tagName`).to eq("SPAN")
|
167
|
+
expect(`div.textContent`).to eq("lorem")
|
168
|
+
}
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should work without providing a block" do
|
173
|
+
div = `document.createElement("div")`
|
174
|
+
React.render(React.create_element('span') { "lorem" }, div)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should return a React::Component::API compatible object" do
|
178
|
+
div = `document.createElement("div")`
|
179
|
+
component = React.render(React.create_element('span') { "lorem" }, div)
|
180
|
+
React::Component::API.public_instance_methods(true).each do |method_name|
|
181
|
+
expect(component).to respond_to(method_name)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
pending "should return nil to prevent abstraction leakage" do
|
186
|
+
div = `document.createElement("div")`
|
187
|
+
expect {
|
188
|
+
React.render(React.create_element('span') { "lorem" }, div)
|
189
|
+
}.to be_nil
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "render_to_string" do
|
194
|
+
it "should render a React.Element to string" do
|
195
|
+
ele = React.create_element('span') { "lorem" }
|
196
|
+
expect(React.render_to_string(ele)).to be_kind_of(String)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "unmount_component_at_node" do
|
201
|
+
async "should unmount component at node" do
|
202
|
+
div = `document.createElement("div")`
|
203
|
+
React.render(React.create_element('span') { "lorem" }, div ) do
|
204
|
+
run_async {
|
205
|
+
expect(React.unmount_component_at_node(div)).to eq(true)
|
206
|
+
}
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
if opal?
|
4
|
+
describe 'React::State' do
|
5
|
+
it "can created static exported states" do
|
6
|
+
stub_const 'Foo', Class.new
|
7
|
+
Foo.class_eval do
|
8
|
+
include React::Component
|
9
|
+
export_state(:foo) { 'bar' }
|
10
|
+
end
|
11
|
+
|
12
|
+
expect(Foo.foo).to eq('bar')
|
13
|
+
end
|
14
|
+
|
15
|
+
# these will all require async operations and testing to see if things get
|
16
|
+
# re-rendered see spec_helper the "render" test method
|
17
|
+
|
18
|
+
# if Foo.foo is used during rendering then when Foo.foo changes we will
|
19
|
+
# rerender
|
20
|
+
it "sets up observers when exported states are read"
|
21
|
+
|
22
|
+
# React::State.set_state(object, attribute, value) +
|
23
|
+
# React::State.get_state(object, attribute)
|
24
|
+
it "can be accessed outside of react using get/set_state"
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
if opal?
|
4
|
+
|
5
|
+
module Components
|
6
|
+
|
7
|
+
module Controller
|
8
|
+
class Component1
|
9
|
+
include React::Component
|
10
|
+
def render
|
11
|
+
self.class.name.to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Component1
|
17
|
+
include React::Component
|
18
|
+
def render
|
19
|
+
self.class.name.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Component2
|
24
|
+
include React::Component
|
25
|
+
def render
|
26
|
+
self.class.name.to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module Controller
|
32
|
+
class SomeOtherClass # see issue #80
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Component1
|
37
|
+
include React::Component
|
38
|
+
def render
|
39
|
+
self.class.name.to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def render_top_level(controller, component_name)
|
45
|
+
React.render_to_static_markup(React.create_element(
|
46
|
+
React::TopLevelRailsComponent, {controller: controller, component_name: component_name, render_params: {}}))
|
47
|
+
end
|
48
|
+
|
49
|
+
describe React::TopLevelRailsComponent do
|
50
|
+
|
51
|
+
it 'uses the controller name to lookup a component' do
|
52
|
+
expect(render_top_level("Controller", "Component1")).to eq('<span>Components::Controller::Component1</span>')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'can find the name without matching the controller' do
|
56
|
+
expect(render_top_level("Controller", "Component2")).to eq('<span>Components::Component2</span>')
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'will find the outer most matching component' do
|
60
|
+
expect(render_top_level("OtherController", "Component1")).to eq('<span>Component1</span>')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'can find the correct component when the name is fully qualified' do
|
64
|
+
expect(render_top_level("Controller", "::Components::Component1")).to eq('<span>Components::Component1</span>')
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
if opal?
|
4
|
+
class HelloMessage
|
5
|
+
include React::Component
|
6
|
+
def render
|
7
|
+
div { "Hello World!" }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'An Example from the react.rb doc' do
|
12
|
+
it 'produces the correct result' do
|
13
|
+
expect(React.render_to_static_markup(React.create_element(HelloMessage))).to eq('<div>Hello World!</div>')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class HelloMessage2
|
18
|
+
include React::Component
|
19
|
+
define_state(:user_name) { '@catmando' }
|
20
|
+
def render
|
21
|
+
div { "Hello #{user_name}" }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'Adding state to a component (second tutorial example)' do
|
26
|
+
it "produces the correct result" do
|
27
|
+
expect(React.render_to_static_markup(React.create_element(HelloMessage2))).to eq('<div>Hello @catmando</div>')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'renders to the document' do
|
31
|
+
React.render(React.create_element(HelloMessage2), `document.getElementById('render_here')`)
|
32
|
+
expect(`document.getElementById('render_here').innerHTML`) =~ 'Hello @catmando'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
if opal?
|
4
|
+
describe React::Validator do
|
5
|
+
before do
|
6
|
+
stub_const 'Foo', Class.new(React::Component::Base)
|
7
|
+
end
|
8
|
+
describe '#validate' do
|
9
|
+
describe "Presence validation" do
|
10
|
+
it "should check if required props provided" do
|
11
|
+
validator = React::Validator.new(Foo).build do
|
12
|
+
requires :foo
|
13
|
+
requires :bar
|
14
|
+
end
|
15
|
+
|
16
|
+
expect(validator.validate({})).to eq(["Required prop `foo` was not specified", "Required prop `bar` was not specified"])
|
17
|
+
expect(validator.validate({foo: 1, bar: 3})).to eq([])
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should check if passed non specified prop" do
|
21
|
+
validator = React::Validator.new(Foo).build do
|
22
|
+
optional :foo
|
23
|
+
end
|
24
|
+
|
25
|
+
expect(validator.validate({bar: 10})).to eq(["Provided prop `bar` not specified in spec"])
|
26
|
+
expect(validator.validate({foo: 10})).to eq([])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "Type validation" do
|
31
|
+
it "should check if passed value with wrong type" do
|
32
|
+
validator = React::Validator.new(Foo).build do
|
33
|
+
requires :foo, type: String
|
34
|
+
end
|
35
|
+
|
36
|
+
expect(validator.validate({foo: 10})).to eq(["Provided prop `foo` could not be converted to String"])
|
37
|
+
expect(validator.validate({foo: "10"})).to eq([])
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should check if passed value with wrong custom type" do
|
41
|
+
stub_const 'Bar', Class.new
|
42
|
+
validator = React::Validator.new(Foo).build do
|
43
|
+
requires :foo, type: Bar
|
44
|
+
end
|
45
|
+
|
46
|
+
expect(validator.validate({foo: 10})).to eq(["Provided prop `foo` could not be converted to Bar"])
|
47
|
+
expect(validator.validate({foo: Bar.new})).to eq([])
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'coerces native JS prop types to opal objects' do
|
51
|
+
validator = React::Validator.new(Foo).build do
|
52
|
+
requires :foo, type: `{ x: 1 }`
|
53
|
+
end
|
54
|
+
|
55
|
+
message = "Provided prop `foo` could not be converted to [object Object]"
|
56
|
+
expect(validator.validate({foo: `{ x: 1 }`})).to eq([message])
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'coerces native JS values to opal objects' do
|
60
|
+
validator = React::Validator.new(Foo).build do
|
61
|
+
requires :foo, type: Array[Fixnum]
|
62
|
+
end
|
63
|
+
|
64
|
+
message = "Provided prop `foo`[0] could not be converted to Numeric"
|
65
|
+
expect(validator.validate({foo: `[ { x: 1 } ]`})).to eq([message])
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should support Array[Class] validation" do
|
69
|
+
validator = React::Validator.new(Foo).build do
|
70
|
+
requires :foo, type: Array[Hash]
|
71
|
+
end
|
72
|
+
|
73
|
+
expect(validator.validate({foo: [1,'2',3]})).to eq(
|
74
|
+
[
|
75
|
+
"Provided prop `foo`[0] could not be converted to Hash",
|
76
|
+
"Provided prop `foo`[1] could not be converted to Hash",
|
77
|
+
"Provided prop `foo`[2] could not be converted to Hash"
|
78
|
+
]
|
79
|
+
)
|
80
|
+
expect(validator.validate({foo: [{},{},{}]})).to eq([])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "Limited values" do
|
85
|
+
it "should check if passed value is not one of the specified values" do
|
86
|
+
validator = React::Validator.new(Foo).build do
|
87
|
+
requires :foo, values: [4,5,6]
|
88
|
+
end
|
89
|
+
|
90
|
+
expect(validator.validate({foo: 3})).to eq(["Value `3` for prop `foo` is not an allowed value"])
|
91
|
+
expect(validator.validate({foo: 4})).to eq([])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#undefined_props' do
|
97
|
+
let(:props) { { foo: 'foo', bar: 'bar', biz: 'biz', baz: 'baz' } }
|
98
|
+
let(:validator) do
|
99
|
+
React::Validator.new(Foo).build do
|
100
|
+
requires :foo
|
101
|
+
optional :bar
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'slurps up any extra params into a hash' do
|
106
|
+
others = validator.undefined_props(props)
|
107
|
+
expect(others).to eq({ biz: 'biz', baz: 'baz' })
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'prevents validate non-specified params' do
|
111
|
+
validator.undefined_props(props)
|
112
|
+
expect(validator.validate(props)).to eq([])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "default_props" do
|
117
|
+
it "should return specified default values" do
|
118
|
+
validator = React::Validator.new(Foo).build do
|
119
|
+
requires :foo, default: 10
|
120
|
+
requires :bar
|
121
|
+
optional :lorem, default: 20
|
122
|
+
end
|
123
|
+
|
124
|
+
expect(validator.default_props).to eq({foo: 10, lorem: 20})
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|