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,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
|