hyper-react 0.10.0
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 +27 -0
- data/.gitignore +36 -0
- data/.rubocop.yml +1159 -0
- data/.travis.yml +29 -0
- data/Appraisals +20 -0
- data/CHANGELOG.md +93 -0
- data/Gemfile +6 -0
- data/LICENSE +19 -0
- data/README.md +121 -0
- data/Rakefile +33 -0
- data/UPGRADING.md +24 -0
- data/component-name-lookup.md +145 -0
- data/config.ru +25 -0
- data/gemfiles/opal_0.8_react_13.gemfile +13 -0
- data/gemfiles/opal_0.8_react_14.gemfile +13 -0
- data/gemfiles/opal_0.8_react_15.gemfile +13 -0
- data/gemfiles/opal_0.9_react_13.gemfile +13 -0
- data/gemfiles/opal_0.9_react_14.gemfile +13 -0
- data/gemfiles/opal_0.9_react_15.gemfile +13 -0
- data/hyper-react.gemspec +43 -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/templates/views/layouts/test_layout.html.erb +0 -0
- data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +109 -0
- data/lib/hyper-react.rb +52 -0
- data/lib/rails-helpers/top_level_rails_component.rb +54 -0
- data/lib/react-sources/react-server.js +2 -0
- data/lib/react/api.rb +162 -0
- data/lib/react/callbacks.rb +42 -0
- data/lib/react/children.rb +30 -0
- data/lib/react/component.rb +139 -0
- data/lib/react/component/api.rb +50 -0
- data/lib/react/component/base.rb +9 -0
- data/lib/react/component/class_methods.rb +214 -0
- data/lib/react/component/dsl_instance_methods.rb +27 -0
- data/lib/react/component/params.rb +6 -0
- data/lib/react/component/props_wrapper.rb +83 -0
- data/lib/react/component/should_component_update.rb +98 -0
- data/lib/react/component/tags.rb +144 -0
- data/lib/react/element.rb +168 -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/hash.rb +13 -0
- data/lib/react/native_library.rb +92 -0
- data/lib/react/object.rb +15 -0
- data/lib/react/observable.rb +29 -0
- data/lib/react/react-source.rb +9 -0
- data/lib/react/rendering_context.rb +142 -0
- data/lib/react/state.rb +190 -0
- data/lib/react/test.rb +16 -0
- data/lib/react/test/dsl.rb +17 -0
- data/lib/react/test/matchers/render_html_matcher.rb +49 -0
- data/lib/react/test/rspec.rb +15 -0
- data/lib/react/test/session.rb +46 -0
- data/lib/react/top_level.rb +132 -0
- data/lib/react/validator.rb +136 -0
- data/lib/reactive-ruby/component_loader.rb +49 -0
- data/lib/reactive-ruby/isomorphic_helpers.rb +197 -0
- data/lib/reactive-ruby/rails.rb +7 -0
- data/lib/reactive-ruby/rails/component_mount.rb +46 -0
- data/lib/reactive-ruby/rails/controller_helper.rb +15 -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/auto-import.rb +32 -0
- data/lib/reactrb/deep-compare.rb +24 -0
- data/lib/reactrb/new-event-name-convention.rb +11 -0
- data/lib/sources/react-latest.js +21169 -0
- data/lib/sources/react-v13.js +21645 -0
- data/lib/sources/react-v14.js +20821 -0
- data/lib/sources/react-v15.js +21170 -0
- data/logo1.png +0 -0
- data/logo2.png +0 -0
- data/logo3.png +0 -0
- data/path_release_steps.md +9 -0
- data/spec/controller_helper_spec.rb +34 -0
- data/spec/index.html.erb +10 -0
- data/spec/react/callbacks_spec.rb +106 -0
- data/spec/react/children_spec.rb +76 -0
- data/spec/react/component/base_spec.rb +32 -0
- data/spec/react/component_spec.rb +872 -0
- data/spec/react/dsl_spec.rb +296 -0
- data/spec/react/element_spec.rb +136 -0
- data/spec/react/event_spec.rb +24 -0
- data/spec/react/native_library_spec.rb +344 -0
- data/spec/react/observable_spec.rb +7 -0
- data/spec/react/opal_jquery_extensions_spec.rb +66 -0
- data/spec/react/param_declaration_spec.rb +258 -0
- data/spec/react/react_spec.rb +209 -0
- data/spec/react/state_spec.rb +55 -0
- data/spec/react/test/dsl_spec.rb +43 -0
- data/spec/react/test/matchers/render_html_matcher_spec.rb +83 -0
- data/spec/react/test/rspec_spec.rb +62 -0
- data/spec/react/test/session_spec.rb +100 -0
- data/spec/react/test/utils_spec.rb +45 -0
- data/spec/react/top_level_component_spec.rb +96 -0
- data/spec/react/tutorial/tutorial_spec.rb +36 -0
- data/spec/react/validator_spec.rb +124 -0
- data/spec/reactive-ruby/component_loader_spec.rb +71 -0
- data/spec/reactive-ruby/isomorphic_helpers_spec.rb +155 -0
- data/spec/reactive-ruby/rails/asset_pipeline_spec.rb +10 -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 +115 -0
- data/spec/support/react/spec_helpers.rb +64 -0
- data/spec/vendor/es5-shim.min.js +6 -0
- data/spec/vendor/jquery-2.2.4.min.js +4 -0
- metadata +387 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
RSpec.describe React::Test::Session do
|
|
5
|
+
subject { described_class.new }
|
|
6
|
+
before do
|
|
7
|
+
stub_const 'Greeter', Class.new
|
|
8
|
+
Greeter.class_eval do
|
|
9
|
+
include React::Component
|
|
10
|
+
|
|
11
|
+
params do
|
|
12
|
+
optional :message
|
|
13
|
+
optional :from
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def render
|
|
17
|
+
span { "Hello #{params.message}" }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe '#mount' do
|
|
23
|
+
it 'returns an instance of the mounted component' do
|
|
24
|
+
expect(subject.mount(Greeter)).to be_a(Greeter)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'actualy mounts the component' do
|
|
28
|
+
expect(subject.mount(Greeter)).to be_mounted
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'optionaly passes params to the component' do
|
|
32
|
+
instance = subject.mount(Greeter, message: 'world')
|
|
33
|
+
expect(instance.params.message).to eq('world')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '#instance' do
|
|
38
|
+
it 'returns the instance of the mounted component' do
|
|
39
|
+
instance = subject.mount(Greeter)
|
|
40
|
+
expect(subject.instance).to eq(instance)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe '#element' do
|
|
45
|
+
it 'returns the React::Element for the mounted component' do
|
|
46
|
+
subject.mount(Greeter)
|
|
47
|
+
expect(subject.element).to be_a(React::Element)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '#native' do
|
|
52
|
+
it 'returns the React native instance of the component' do
|
|
53
|
+
instance = subject.mount(Greeter)
|
|
54
|
+
native = instance.instance_variable_get('@native')
|
|
55
|
+
expect(subject.native).to eq(native)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe '#html' do
|
|
60
|
+
it 'returns the component rendered to static html' do
|
|
61
|
+
subject.mount(Greeter, message: 'world')
|
|
62
|
+
expect(subject.html).to eq('<span>Hello world</span>')
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'returns the updated static html' do
|
|
66
|
+
subject.mount(Greeter)
|
|
67
|
+
subject.update_params(message: 'moon')
|
|
68
|
+
expect(subject.html).to eq('<span>Hello moon</span>')
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe '#update_params' do
|
|
73
|
+
it 'sends new params to the component' do
|
|
74
|
+
instance = subject.mount(Greeter, message: 'world')
|
|
75
|
+
subject.update_params(message: 'moon')
|
|
76
|
+
expect(instance.params.message).to eq('moon')
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'leaves unspecified params in tact' do
|
|
80
|
+
instance = subject.mount(Greeter, message: 'world', from: 'outerspace')
|
|
81
|
+
subject.update_params(message: 'moon')
|
|
82
|
+
expect(instance.params.from).to eq('outerspace')
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'causes the component to render' do
|
|
86
|
+
instance = subject.mount(Greeter, message: 'world')
|
|
87
|
+
expect(instance).to receive(:render)
|
|
88
|
+
subject.update_params(message: 'moon')
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe '#force_update' do
|
|
93
|
+
it 'causes the component to render' do
|
|
94
|
+
instance = subject.mount(Greeter)
|
|
95
|
+
expect(instance).to receive(:render)
|
|
96
|
+
subject.force_update!
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
module React
|
|
5
|
+
module Test
|
|
6
|
+
class Utils
|
|
7
|
+
def self.simulate(event, element)
|
|
8
|
+
Simulate.new.click(element)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Simulate
|
|
12
|
+
include Native
|
|
13
|
+
def initialize
|
|
14
|
+
super(`React.addons.TestUtils.Simulate`)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def click(component_instance)
|
|
18
|
+
`#{@native}['click']`.call(component_instance.dom_node, {})
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
RSpec.describe React::Test::Utils do
|
|
25
|
+
it 'simulates' do
|
|
26
|
+
stub_const 'Foo', Class.new
|
|
27
|
+
Foo.class_eval do
|
|
28
|
+
include React::Component
|
|
29
|
+
|
|
30
|
+
def hello
|
|
31
|
+
@hello
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def render
|
|
35
|
+
@hello = 'hello'
|
|
36
|
+
div { 'Click Me' }.on(:click) { |e| click(e) }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
instance = renderToDocument(Foo)
|
|
41
|
+
expect_any_instance_of(Foo).to receive(:click)
|
|
42
|
+
described_class.simulate(:click, instance)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
module Components
|
|
5
|
+
module Controller
|
|
6
|
+
class Component1
|
|
7
|
+
include React::Component
|
|
8
|
+
def render
|
|
9
|
+
self.class.name.to_s
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Component1
|
|
15
|
+
include React::Component
|
|
16
|
+
def render
|
|
17
|
+
self.class.name.to_s
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class Component2
|
|
22
|
+
include React::Component
|
|
23
|
+
def render
|
|
24
|
+
self.class.name.to_s
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
module Controller
|
|
30
|
+
class SomeOtherClass # see issue #80
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class Component1
|
|
35
|
+
include React::Component
|
|
36
|
+
def render
|
|
37
|
+
self.class.name.to_s
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def render_top_level(controller, component_name)
|
|
42
|
+
render_to_html(React::TopLevelRailsComponent, controller: controller,
|
|
43
|
+
component_name: component_name, render_params: {})
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe React::TopLevelRailsComponent do
|
|
47
|
+
|
|
48
|
+
it 'uses the controller name to lookup a component' do
|
|
49
|
+
expect(render_top_level("Controller", "Component1")).to eq('<span>Components::Controller::Component1</span>')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'can find the name without matching the controller' do
|
|
53
|
+
expect(render_top_level("Controller", "Component2")).to eq('<span>Components::Component2</span>')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'will find the outer most matching component' do
|
|
57
|
+
expect(render_top_level("OtherController", "Component1")).to eq('<span>Component1</span>')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'can find the correct component when the name is fully qualified' do
|
|
61
|
+
expect(render_top_level("Controller", "::Components::Component1")).to eq('<span>Components::Component1</span>')
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe '.html_tag?' do
|
|
65
|
+
it 'is truthy for valid html tags' do
|
|
66
|
+
expect(React.html_tag?('a')).to be_truthy
|
|
67
|
+
expect(React.html_tag?('div')).to be_truthy
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'is truthy for valid svg tags' do
|
|
71
|
+
expect(React.html_tag?('svg')).to be_truthy
|
|
72
|
+
expect(React.html_tag?('circle')).to be_truthy
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'is falsey for invalid tags' do
|
|
76
|
+
expect(React.html_tag?('tagizzle')).to be_falsey
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe '.html_attr?' do
|
|
81
|
+
it 'is truthy for valid html attributes' do
|
|
82
|
+
expect(React.html_attr?('id')).to be_truthy
|
|
83
|
+
expect(React.html_attr?('data')).to be_truthy
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'is truthy for valid svg attributes' do
|
|
87
|
+
expect(React.html_attr?('cx')).to be_truthy
|
|
88
|
+
expect(React.html_attr?('strokeWidth')).to be_truthy
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'is falsey for invalid attributes' do
|
|
92
|
+
expect(React.html_tag?('attrizzle')).to be_falsey
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
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', type: :component do
|
|
12
|
+
it 'produces the correct result' do
|
|
13
|
+
expect(HelloMessage).to render('<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 #{state.user_name}" }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe 'Adding state to a component (second tutorial example)', type: :component do
|
|
26
|
+
it "produces the correct result" do
|
|
27
|
+
expect(HelloMessage2).to render('<div>Hello @catmando</div>')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'renders to the document' do
|
|
31
|
+
ele = `document.createElement('div')`
|
|
32
|
+
React.render(React.create_element(HelloMessage2), ele)
|
|
33
|
+
expect(`#{ele}.innerHTML`) =~ 'Hello @catmando'
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
describe React::Validator do
|
|
5
|
+
describe '#validate' do
|
|
6
|
+
describe "Presence validation" do
|
|
7
|
+
it "should check if required props provided" do
|
|
8
|
+
validator = React::Validator.new.build do
|
|
9
|
+
requires :foo
|
|
10
|
+
requires :bar
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
expect(validator.validate({})).to eq(["Required prop `foo` was not specified", "Required prop `bar` was not specified"])
|
|
14
|
+
expect(validator.validate({foo: 1, bar: 3})).to eq([])
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should check if passed non specified prop" do
|
|
18
|
+
validator = React::Validator.new.build do
|
|
19
|
+
optional :foo
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
expect(validator.validate({bar: 10})).to eq(["Provided prop `bar` not specified in spec"])
|
|
23
|
+
expect(validator.validate({foo: 10})).to eq([])
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "Type validation" do
|
|
28
|
+
it "should check if passed value with wrong type" do
|
|
29
|
+
validator = React::Validator.new.build do
|
|
30
|
+
requires :foo, type: String
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
expect(validator.validate({foo: 10})).to eq(["Provided prop `foo` could not be converted to String"])
|
|
34
|
+
expect(validator.validate({foo: "10"})).to eq([])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should check if passed value with wrong custom type" do
|
|
38
|
+
stub_const 'Bar', Class.new
|
|
39
|
+
validator = React::Validator.new.build do
|
|
40
|
+
requires :foo, type: Bar
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
expect(validator.validate({foo: 10})).to eq(["Provided prop `foo` could not be converted to Bar"])
|
|
44
|
+
expect(validator.validate({foo: Bar.new})).to eq([])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'coerces native JS prop types to opal objects' do
|
|
48
|
+
validator = React::Validator.new.build do
|
|
49
|
+
requires :foo, type: `{ x: 1 }`
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
message = "Provided prop `foo` could not be converted to [object Object]"
|
|
53
|
+
expect(validator.validate({foo: `{ x: 1 }`})).to eq([message])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'coerces native JS values to opal objects' do
|
|
57
|
+
validator = React::Validator.new.build do
|
|
58
|
+
requires :foo, type: Array[Fixnum]
|
|
59
|
+
end
|
|
60
|
+
message = "Provided prop `foo`[0] could not be converted to #{Fixnum.name}"
|
|
61
|
+
expect(validator.validate({foo: `[ { x: 1 } ]`})).to eq([message])
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "should support Array[Class] validation" do
|
|
65
|
+
validator = React::Validator.new.build do
|
|
66
|
+
requires :foo, type: Array[Hash]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
expect(validator.validate({foo: [1,'2',3]})).to eq(
|
|
70
|
+
[
|
|
71
|
+
"Provided prop `foo`[0] could not be converted to Hash",
|
|
72
|
+
"Provided prop `foo`[1] could not be converted to Hash",
|
|
73
|
+
"Provided prop `foo`[2] could not be converted to Hash"
|
|
74
|
+
]
|
|
75
|
+
)
|
|
76
|
+
expect(validator.validate({foo: [{},{},{}]})).to eq([])
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe "Limited values" do
|
|
81
|
+
it "should check if passed value is not one of the specified values" do
|
|
82
|
+
validator = React::Validator.new.build do
|
|
83
|
+
requires :foo, values: [4,5,6]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
expect(validator.validate({foo: 3})).to eq(["Value `3` for prop `foo` is not an allowed value"])
|
|
87
|
+
expect(validator.validate({foo: 4})).to eq([])
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe '#undefined_props' do
|
|
93
|
+
let(:props) { { foo: 'foo', bar: 'bar', biz: 'biz', baz: 'baz' } }
|
|
94
|
+
let(:validator) do
|
|
95
|
+
React::Validator.new.build do
|
|
96
|
+
requires :foo
|
|
97
|
+
optional :bar
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'slurps up any extra params into a hash' do
|
|
102
|
+
others = validator.undefined_props(props)
|
|
103
|
+
expect(others).to eq({ biz: 'biz', baz: 'baz' })
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'prevents validate non-specified params' do
|
|
107
|
+
validator.undefined_props(props)
|
|
108
|
+
expect(validator.validate(props)).to eq([])
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe "default_props" do
|
|
113
|
+
it "should return specified default values" do
|
|
114
|
+
validator = React::Validator.new.build do
|
|
115
|
+
requires :foo, default: 10
|
|
116
|
+
requires :bar
|
|
117
|
+
optional :lorem, default: 20
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
expect(validator.default_props).to eq({foo: 10, lorem: 20})
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if ruby?
|
|
4
|
+
RSpec.describe ReactiveRuby::ComponentLoader do
|
|
5
|
+
GLOBAL_WRAPPER = <<-JS
|
|
6
|
+
var global = global || this;
|
|
7
|
+
var self = self || this;
|
|
8
|
+
var window = window || this;
|
|
9
|
+
var console = {
|
|
10
|
+
warn: function(s) { }
|
|
11
|
+
};
|
|
12
|
+
JS
|
|
13
|
+
|
|
14
|
+
let(:js) { ::Rails.application.assets['components'].to_s }
|
|
15
|
+
let(:context) { ExecJS.compile(GLOBAL_WRAPPER + js) }
|
|
16
|
+
let(:v8_context) { ReactiveRuby::ServerRendering.context_instance_for(context) }
|
|
17
|
+
|
|
18
|
+
describe '.new' do
|
|
19
|
+
it 'raises a meaningful exception when initialized without a context' do
|
|
20
|
+
expect {
|
|
21
|
+
described_class.new(nil)
|
|
22
|
+
}.to raise_error(/Could not obtain ExecJS runtime context/)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe '#load' do
|
|
27
|
+
it 'loads given asset file into context' do
|
|
28
|
+
loader = described_class.new(v8_context)
|
|
29
|
+
|
|
30
|
+
expect {
|
|
31
|
+
loader.load
|
|
32
|
+
}.to change { !!v8_context.eval('Opal.React') }.from(false).to(true)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'is truthy upon successful load' do
|
|
36
|
+
loader = described_class.new(v8_context)
|
|
37
|
+
expect(loader.load).to be_truthy
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'fails silently returning false' do
|
|
41
|
+
loader = described_class.new(v8_context)
|
|
42
|
+
expect(loader.load('foo')).to be_falsey
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe '#load!' do
|
|
47
|
+
it 'is truthy upon successful load' do
|
|
48
|
+
loader = described_class.new(v8_context)
|
|
49
|
+
expect(loader.load!).to be_truthy
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'raises an expection if loading fails' do
|
|
53
|
+
loader = described_class.new(v8_context)
|
|
54
|
+
expect { loader.load!('foo') }.to raise_error(/No react\.rb components/)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe '#loaded?' do
|
|
59
|
+
it 'is truthy if components file is already loaded' do
|
|
60
|
+
loader = described_class.new(v8_context)
|
|
61
|
+
loader.load
|
|
62
|
+
expect(loader).to be_loaded
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'is false if components file is not loaded' do
|
|
66
|
+
loader = described_class.new(v8_context)
|
|
67
|
+
expect(loader).to_not be_loaded
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|