reactrb 0.7.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +6 -0
  3. data/.gitignore +33 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE +19 -0
  7. data/README.md +117 -0
  8. data/Rakefile +28 -0
  9. data/config.ru +16 -0
  10. data/example/examples/Gemfile +7 -0
  11. data/example/examples/app/basics.js.rb +42 -0
  12. data/example/examples/app/items.rb +11 -0
  13. data/example/examples/app/jquery.js +5 -0
  14. data/example/examples/app/nodes.rb +61 -0
  15. data/example/examples/app/react-router.js +6 -0
  16. data/example/examples/app/react_api_demo.rb +29 -0
  17. data/example/examples/app/rerendering.rb +72 -0
  18. data/example/examples/app/reuse.rb +59 -0
  19. data/example/examples/app/show.rb +52 -0
  20. data/example/examples/config.ru +38 -0
  21. data/example/rails-tutorial/.gitignore +17 -0
  22. data/example/rails-tutorial/Gemfile +51 -0
  23. data/example/rails-tutorial/README.rdoc +28 -0
  24. data/example/rails-tutorial/Rakefile +6 -0
  25. data/example/rails-tutorial/app/assets/images/.keep +0 -0
  26. data/example/rails-tutorial/app/assets/javascripts/application.rb +15 -0
  27. data/example/rails-tutorial/app/assets/stylesheets/application.css +15 -0
  28. data/example/rails-tutorial/app/controllers/application_controller.rb +6 -0
  29. data/example/rails-tutorial/app/controllers/concerns/.keep +0 -0
  30. data/example/rails-tutorial/app/controllers/home_controller.rb +6 -0
  31. data/example/rails-tutorial/app/helpers/application_helper.rb +2 -0
  32. data/example/rails-tutorial/app/mailers/.keep +0 -0
  33. data/example/rails-tutorial/app/models/.keep +0 -0
  34. data/example/rails-tutorial/app/models/concerns/.keep +0 -0
  35. data/example/rails-tutorial/app/views/components.rb +3 -0
  36. data/example/rails-tutorial/app/views/components/home/show.rb +47 -0
  37. data/example/rails-tutorial/app/views/layouts/application.html.erb +14 -0
  38. data/example/rails-tutorial/bin/bundle +3 -0
  39. data/example/rails-tutorial/bin/rails +8 -0
  40. data/example/rails-tutorial/bin/rake +8 -0
  41. data/example/rails-tutorial/bin/setup +29 -0
  42. data/example/rails-tutorial/bin/spring +15 -0
  43. data/example/rails-tutorial/config.ru +4 -0
  44. data/example/rails-tutorial/config/application.rb +26 -0
  45. data/example/rails-tutorial/config/boot.rb +3 -0
  46. data/example/rails-tutorial/config/database.yml +25 -0
  47. data/example/rails-tutorial/config/environment.rb +5 -0
  48. data/example/rails-tutorial/config/environments/development.rb +41 -0
  49. data/example/rails-tutorial/config/environments/production.rb +79 -0
  50. data/example/rails-tutorial/config/environments/test.rb +42 -0
  51. data/example/rails-tutorial/config/initializers/assets.rb +11 -0
  52. data/example/rails-tutorial/config/initializers/backtrace_silencers.rb +7 -0
  53. data/example/rails-tutorial/config/initializers/cookies_serializer.rb +3 -0
  54. data/example/rails-tutorial/config/initializers/filter_parameter_logging.rb +4 -0
  55. data/example/rails-tutorial/config/initializers/inflections.rb +16 -0
  56. data/example/rails-tutorial/config/initializers/mime_types.rb +4 -0
  57. data/example/rails-tutorial/config/initializers/session_store.rb +3 -0
  58. data/example/rails-tutorial/config/initializers/wrap_parameters.rb +14 -0
  59. data/example/rails-tutorial/config/locales/en.yml +23 -0
  60. data/example/rails-tutorial/config/routes.rb +59 -0
  61. data/example/rails-tutorial/config/secrets.yml +22 -0
  62. data/example/rails-tutorial/db/seeds.rb +7 -0
  63. data/example/rails-tutorial/lib/assets/.keep +0 -0
  64. data/example/rails-tutorial/lib/tasks/.keep +0 -0
  65. data/example/rails-tutorial/log/.keep +0 -0
  66. data/example/rails-tutorial/public/404.html +67 -0
  67. data/example/rails-tutorial/public/422.html +67 -0
  68. data/example/rails-tutorial/public/500.html +66 -0
  69. data/example/rails-tutorial/public/favicon.ico +0 -0
  70. data/example/rails-tutorial/public/robots.txt +5 -0
  71. data/example/rails-tutorial/test/controllers/.keep +0 -0
  72. data/example/rails-tutorial/test/fixtures/.keep +0 -0
  73. data/example/rails-tutorial/test/helpers/.keep +0 -0
  74. data/example/rails-tutorial/test/integration/.keep +0 -0
  75. data/example/rails-tutorial/test/mailers/.keep +0 -0
  76. data/example/rails-tutorial/test/models/.keep +0 -0
  77. data/example/rails-tutorial/test/test_helper.rb +10 -0
  78. data/example/rails-tutorial/vendor/assets/javascripts/.keep +0 -0
  79. data/example/rails-tutorial/vendor/assets/stylesheets/.keep +0 -0
  80. data/example/sinatra-tutorial/.DS_Store +0 -0
  81. data/example/sinatra-tutorial/Gemfile +5 -0
  82. data/example/sinatra-tutorial/README.md +8 -0
  83. data/example/sinatra-tutorial/_comments.json +42 -0
  84. data/example/sinatra-tutorial/app/example.rb +290 -0
  85. data/example/sinatra-tutorial/app/jquery.js +5 -0
  86. data/example/sinatra-tutorial/config.ru +58 -0
  87. data/example/sinatra-tutorial/public/base.css +62 -0
  88. data/example/todos/Gemfile +11 -0
  89. data/example/todos/README.md +37 -0
  90. data/example/todos/Rakefile +8 -0
  91. data/example/todos/app/application.rb +22 -0
  92. data/example/todos/app/components/app.react.rb +61 -0
  93. data/example/todos/app/components/footer.react.rb +31 -0
  94. data/example/todos/app/components/todo_item.react.rb +46 -0
  95. data/example/todos/app/components/todo_list.react.rb +25 -0
  96. data/example/todos/app/models/todo.rb +19 -0
  97. data/example/todos/config.ru +14 -0
  98. data/example/todos/index.html.haml +16 -0
  99. data/example/todos/spec/todo_spec.rb +28 -0
  100. data/example/todos/vendor/base.css +410 -0
  101. data/example/todos/vendor/bg.png +0 -0
  102. data/example/todos/vendor/jquery.js +4 -0
  103. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +4 -0
  104. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/test_application.rb +2 -0
  105. data/lib/generators/reactive_ruby/test_app/templates/boot.rb.erb +6 -0
  106. data/lib/generators/reactive_ruby/test_app/templates/script/rails +5 -0
  107. data/lib/generators/reactive_ruby/test_app/templates/test_application.rb.erb +13 -0
  108. data/lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +11 -0
  109. data/lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb +14 -0
  110. data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +105 -0
  111. data/lib/rails-helpers/top_level_rails_component.rb +54 -0
  112. data/lib/react/api.rb +127 -0
  113. data/lib/react/callbacks.rb +42 -0
  114. data/lib/react/component.rb +269 -0
  115. data/lib/react/component/api.rb +50 -0
  116. data/lib/react/component/base.rb +9 -0
  117. data/lib/react/component/class_methods.rb +190 -0
  118. data/lib/react/component/props_wrapper.rb +82 -0
  119. data/lib/react/element.rb +77 -0
  120. data/lib/react/event.rb +76 -0
  121. data/lib/react/ext/hash.rb +9 -0
  122. data/lib/react/ext/string.rb +8 -0
  123. data/lib/react/native_library.rb +53 -0
  124. data/lib/react/observable.rb +29 -0
  125. data/lib/react/rendering_context.rb +109 -0
  126. data/lib/react/state.rb +140 -0
  127. data/lib/react/top_level.rb +97 -0
  128. data/lib/react/validator.rb +136 -0
  129. data/lib/reactive-ruby/component_loader.rb +45 -0
  130. data/lib/reactive-ruby/isomorphic_helpers.rb +196 -0
  131. data/lib/reactive-ruby/rails.rb +7 -0
  132. data/lib/reactive-ruby/rails/component_mount.rb +44 -0
  133. data/lib/reactive-ruby/rails/controller_helper.rb +13 -0
  134. data/lib/reactive-ruby/rails/railtie.rb +14 -0
  135. data/lib/reactive-ruby/serializers.rb +15 -0
  136. data/lib/reactive-ruby/server_rendering/contextual_renderer.rb +42 -0
  137. data/lib/reactive-ruby/version.rb +3 -0
  138. data/lib/reactrb.rb +50 -0
  139. data/lib/sources/react-latest.js +21167 -0
  140. data/lib/sources/react-v13.js +21642 -0
  141. data/lib/sources/react-v14.js +20818 -0
  142. data/lib/sources/react-v15.js +21167 -0
  143. data/logo1.png +0 -0
  144. data/logo2.png +0 -0
  145. data/logo3.png +0 -0
  146. data/path_release_steps.md +9 -0
  147. data/reactrb.gemspec +43 -0
  148. data/spec/controller_helper_spec.rb +22 -0
  149. data/spec/index.html.erb +12 -0
  150. data/spec/react/callbacks_spec.rb +106 -0
  151. data/spec/react/component/base_spec.rb +36 -0
  152. data/spec/react/component_spec.rb +721 -0
  153. data/spec/react/dsl_spec.rb +161 -0
  154. data/spec/react/element_spec.rb +47 -0
  155. data/spec/react/event_spec.rb +24 -0
  156. data/spec/react/native_library_spec.rb +10 -0
  157. data/spec/react/observable_spec.rb +7 -0
  158. data/spec/react/param_declaration_spec.rb +286 -0
  159. data/spec/react/react_spec.rb +211 -0
  160. data/spec/react/state_spec.rb +26 -0
  161. data/spec/react/top_level_component_spec.rb +68 -0
  162. data/spec/react/tutorial/tutorial_spec.rb +35 -0
  163. data/spec/react/validator_spec.rb +128 -0
  164. data/spec/reactive-ruby/component_loader_spec.rb +68 -0
  165. data/spec/reactive-ruby/isomorphic_helpers_spec.rb +155 -0
  166. data/spec/reactive-ruby/rails/asset_pipeline_spec.rb +9 -0
  167. data/spec/reactive-ruby/rails/component_mount_spec.rb +66 -0
  168. data/spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb +35 -0
  169. data/spec/spec_helper.rb +109 -0
  170. data/spec/support/react/spec_helpers.rb +57 -0
  171. data/spec/vendor/es5-shim.min.js +6 -0
  172. data/spec/vendor/jquery-2.2.4.min.js +4 -0
  173. 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