hyper-react 0.12.7 → 0.99.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +48 -34
  3. data/CODE_OF_CONDUCT.md +49 -0
  4. data/Gemfile +5 -6
  5. data/README.md +47 -98
  6. data/Rakefile +6 -28
  7. data/hyper-react.gemspec +36 -43
  8. data/lib/hyper-react.rb +4 -73
  9. data/lib/react/version.rb +3 -0
  10. metadata +91 -249
  11. data/.codeclimate.yml +0 -27
  12. data/.rubocop.yml +0 -1159
  13. data/.travis.yml +0 -62
  14. data/Appraisals +0 -31
  15. data/CHANGELOG.md +0 -143
  16. data/LICENSE +0 -19
  17. data/UPGRADING.md +0 -24
  18. data/component-name-lookup.md +0 -145
  19. data/config.ru +0 -26
  20. data/gemfiles/opal_0.10_react_13.gemfile +0 -15
  21. data/gemfiles/opal_0.10_react_14.gemfile +0 -15
  22. data/gemfiles/opal_0.10_react_15.gemfile +0 -15
  23. data/gemfiles/opal_0.8_react_13.gemfile +0 -15
  24. data/gemfiles/opal_0.8_react_14.gemfile +0 -15
  25. data/gemfiles/opal_0.8_react_15.gemfile +0 -15
  26. data/gemfiles/opal_0.9_react_13.gemfile +0 -15
  27. data/gemfiles/opal_0.9_react_14.gemfile +0 -15
  28. data/gemfiles/opal_0.9_react_15.gemfile +0 -15
  29. data/gemfiles/opal_master_react_15.gemfile +0 -16
  30. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +0 -3
  31. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/test_application.rb +0 -2
  32. data/lib/generators/reactive_ruby/test_app/templates/boot.rb.erb +0 -6
  33. data/lib/generators/reactive_ruby/test_app/templates/script/rails +0 -5
  34. data/lib/generators/reactive_ruby/test_app/templates/test_application.rb.erb +0 -13
  35. data/lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +0 -11
  36. data/lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb +0 -14
  37. data/lib/generators/reactive_ruby/test_app/templates/views/layouts/test_layout.html.erb +0 -0
  38. data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +0 -111
  39. data/lib/rails-helpers/top_level_rails_component.rb +0 -54
  40. data/lib/react-sources/react-server.js +0 -2
  41. data/lib/react/api.rb +0 -173
  42. data/lib/react/callbacks.rb +0 -41
  43. data/lib/react/children.rb +0 -30
  44. data/lib/react/component.rb +0 -168
  45. data/lib/react/component/api.rb +0 -50
  46. data/lib/react/component/base.rb +0 -13
  47. data/lib/react/component/class_methods.rb +0 -189
  48. data/lib/react/component/dsl_instance_methods.rb +0 -23
  49. data/lib/react/component/params.rb +0 -6
  50. data/lib/react/component/props_wrapper.rb +0 -78
  51. data/lib/react/component/should_component_update.rb +0 -94
  52. data/lib/react/component/tags.rb +0 -129
  53. data/lib/react/config.rb +0 -5
  54. data/lib/react/config/client.rb.erb +0 -19
  55. data/lib/react/config/server.rb +0 -23
  56. data/lib/react/element.rb +0 -169
  57. data/lib/react/event.rb +0 -76
  58. data/lib/react/ext/hash.rb +0 -9
  59. data/lib/react/ext/opal-jquery/element.rb +0 -26
  60. data/lib/react/ext/string.rb +0 -8
  61. data/lib/react/hash.rb +0 -13
  62. data/lib/react/native_library.rb +0 -87
  63. data/lib/react/object.rb +0 -15
  64. data/lib/react/react-source-browser.rb +0 -3
  65. data/lib/react/react-source-server.rb +0 -3
  66. data/lib/react/react-source.rb +0 -20
  67. data/lib/react/ref_callback.rb +0 -31
  68. data/lib/react/rendering_context.rb +0 -144
  69. data/lib/react/server.rb +0 -23
  70. data/lib/react/state_wrapper.rb +0 -23
  71. data/lib/react/test.rb +0 -16
  72. data/lib/react/test/dsl.rb +0 -17
  73. data/lib/react/test/matchers/render_html_matcher.rb +0 -56
  74. data/lib/react/test/rspec.rb +0 -15
  75. data/lib/react/test/session.rb +0 -37
  76. data/lib/react/test/utils.rb +0 -25
  77. data/lib/react/top_level.rb +0 -118
  78. data/lib/react/top_level_render.rb +0 -29
  79. data/lib/react/validator.rb +0 -136
  80. data/lib/reactive-ruby/component_loader.rb +0 -50
  81. data/lib/reactive-ruby/isomorphic_helpers.rb +0 -212
  82. data/lib/reactive-ruby/rails.rb +0 -7
  83. data/lib/reactive-ruby/rails/component_mount.rb +0 -46
  84. data/lib/reactive-ruby/rails/controller_helper.rb +0 -15
  85. data/lib/reactive-ruby/rails/railtie.rb +0 -33
  86. data/lib/reactive-ruby/serializers.rb +0 -15
  87. data/lib/reactive-ruby/server_rendering/contextual_renderer.rb +0 -42
  88. data/lib/reactive-ruby/version.rb +0 -3
  89. data/lib/reactrb/auto-import.rb +0 -27
  90. data/lib/reactrb/deep-compare.rb +0 -24
  91. data/lib/reactrb/new-event-name-convention.rb +0 -11
  92. data/logo1.png +0 -0
  93. data/logo2.png +0 -0
  94. data/logo3.png +0 -0
  95. data/path_release_steps.md +0 -9
  96. data/spec/controller_helper_spec.rb +0 -34
  97. data/spec/index.html.erb +0 -11
  98. data/spec/react/callbacks_spec.rb +0 -138
  99. data/spec/react/children_spec.rb +0 -76
  100. data/spec/react/component/base_spec.rb +0 -32
  101. data/spec/react/component_spec.rb +0 -884
  102. data/spec/react/dsl_spec.rb +0 -303
  103. data/spec/react/element_spec.rb +0 -136
  104. data/spec/react/event_spec.rb +0 -24
  105. data/spec/react/native_library_spec.rb +0 -322
  106. data/spec/react/observable_spec.rb +0 -42
  107. data/spec/react/opal_jquery_extensions_spec.rb +0 -68
  108. data/spec/react/param_declaration_spec.rb +0 -269
  109. data/spec/react/react_spec.rb +0 -215
  110. data/spec/react/refs_callback_spec.rb +0 -56
  111. data/spec/react/server_spec.rb +0 -25
  112. data/spec/react/state_spec.rb +0 -55
  113. data/spec/react/test/dsl_spec.rb +0 -43
  114. data/spec/react/test/matchers/render_html_matcher_spec.rb +0 -83
  115. data/spec/react/test/rspec_spec.rb +0 -62
  116. data/spec/react/test/session_spec.rb +0 -88
  117. data/spec/react/test/utils_spec.rb +0 -28
  118. data/spec/react/top_level_component_spec.rb +0 -101
  119. data/spec/react/tutorial/tutorial_spec.rb +0 -36
  120. data/spec/react/validator_spec.rb +0 -124
  121. data/spec/reactive-ruby/component_loader_spec.rb +0 -77
  122. data/spec/reactive-ruby/isomorphic_helpers_spec.rb +0 -160
  123. data/spec/reactive-ruby/rails/asset_pipeline_spec.rb +0 -10
  124. data/spec/reactive-ruby/rails/component_mount_spec.rb +0 -66
  125. data/spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb +0 -35
  126. data/spec/spec_helper.rb +0 -149
  127. data/spec/support/react/spec_helpers.rb +0 -44
  128. data/spec/vendor/es5-shim.min.js +0 -6
  129. data/spec/vendor/jquery-2.2.4.min.js +0 -4
@@ -1,24 +0,0 @@
1
- # rubocop:disable Style/FileName
2
- # require 'reactrb/deep-compare' to get 0.9 deep compare behavior
3
- module React
4
- module Component
5
- module ShouldComponentUpdate
6
-
7
- def props_changed?(next_params)
8
- next_params != props
9
- end
10
-
11
- def call_needs_update(next_params, native_next_state)
12
- component = self
13
- next_params.define_singleton_method(:changed?) do
14
- next_params != props
15
- end
16
- next_state = Hash.new(native_next_state)
17
- next_state.define_singleton_method(:changed?) do
18
- component.native_state_changed?(native_next_state)
19
- end
20
- needs_update?(next_params, next_state)
21
- end
22
- end
23
- end
24
- end
@@ -1,11 +0,0 @@
1
- # rubocop:disable Style/FileName
2
- # require 'reactrb/new-event-name-convention' to remove missing param declaration "_onXXXX"
3
- if RUBY_ENGINE == 'opal'
4
- # removes generation of the deprecated "_onXXXX" event param syntax
5
- module React
6
- class Element
7
- def merge_deprecated_component_event_prop!(event_name)
8
- end
9
- end
10
- end
11
- end
data/logo1.png DELETED
Binary file
data/logo2.png DELETED
Binary file
data/logo3.png DELETED
Binary file
@@ -1,9 +0,0 @@
1
-
2
- For example assuming you are releasing fix to 0.8.18
3
-
4
- 1. Checkout 0-8-stable
5
- 2. Update tests, fix the bug and commit the changes.
6
- 3. Build & Release to RubyGems (Remember the version in version.rb should already be 0.8.19)
7
- 4. Create a tag 'v0.8.19' pointing to that commit.
8
- 5. Bump the version in 0-8-stable to 0.8.20 so it will be ready for the next patch level release.
9
- 6. Commit the version bump, and do a `git push --tags` so the new tag goes up
@@ -1,34 +0,0 @@
1
- require 'spec_helper'
2
-
3
- if ruby?
4
- class TestController < ActionController::Base; end
5
-
6
- RSpec.describe TestController, type: :controller do
7
- render_views
8
-
9
- describe '#render_component' do
10
- controller do
11
-
12
- layout "test_layout"
13
-
14
- def index
15
- render_component
16
- end
17
-
18
- def new
19
- render_component "Index", {}, layout: :explicit_layout
20
- end
21
- end
22
-
23
- it 'renders with the default layout' do
24
- get :index, no_prerender: true
25
- expect(response).to render_template(layout: :test_layout)
26
- end
27
-
28
- it "renders with a specified layout" do
29
- get :new, no_prerender: true
30
- expect(response).to render_template(layout: :explicit_layout)
31
- end
32
- end
33
- end
34
- end
@@ -1,11 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="UTF-8" />
5
- </head>
6
- <body>
7
- <%= javascript_include_tag 'vendor/es5-shim.min' %>
8
- <%= javascript_include_tag 'vendor/jquery-2.2.4.min' %>
9
- <%= javascript_include_tag @server.main %>
10
- </body>
11
- </html>
@@ -1,138 +0,0 @@
1
- require 'spec_helper'
2
-
3
- if opal?
4
- describe React::Callbacks do
5
- it 'defines callback' do
6
- stub_const 'Foo', Class.new
7
- Foo.class_eval do
8
- include React::Callbacks
9
- define_callback :before_dinner
10
- before_dinner :wash_hand
11
-
12
- def wash_hand
13
- end
14
- end
15
-
16
- instance = Foo.new
17
- expect(instance).to receive(:wash_hand)
18
- instance.run_callback(:before_dinner)
19
- end
20
-
21
- it 'defines multiple callbacks' do
22
- stub_const 'Foo', Class.new
23
- Foo.class_eval do
24
- include React::Callbacks
25
- define_callback :before_dinner
26
-
27
- before_dinner :wash_hand, :turn_off_laptop
28
-
29
- def wash_hand;end
30
-
31
- def turn_off_laptop;end
32
- end
33
-
34
- instance = Foo.new
35
- expect(instance).to receive(:wash_hand)
36
- expect(instance).to receive(:turn_off_laptop)
37
- instance.run_callback(:before_dinner)
38
- end
39
-
40
- context 'using Hyperloop::Context.reset!' do
41
- after(:all) do
42
- Hyperloop::Context.instance_variable_set(:@context, nil)
43
- end
44
- it 'clears callbacks on Hyperloop::Context.reset!' do
45
- Hyperloop::Context.reset!
46
- stub_const 'Foo', Class.new
47
- Foo.class_eval do
48
- include React::Callbacks
49
- define_callback :before_dinner
50
-
51
- before_dinner :wash_hand, :turn_off_laptop
52
-
53
- def wash_hands;end
54
-
55
- def turn_off_laptop;end
56
- end
57
- instance = Foo.new
58
- expect(instance).to receive(:wash_hand).once
59
- expect(instance).not_to receive(:turn_off_laptop)
60
-
61
- Hyperloop::Context.reset!
62
-
63
- instance.run_callback(:before_dinner)
64
- Foo.class_eval do
65
- before_dinner :wash_hand
66
- end
67
- instance.run_callback(:before_dinner)
68
- end
69
- end # moved elswhere cause its just hard to get anything to work in this environment
70
-
71
- it 'defines block callback' do
72
- stub_const 'Foo', Class.new
73
- Foo.class_eval do
74
- include React::Callbacks
75
- attr_accessor :a
76
- attr_accessor :b
77
-
78
- define_callback :before_dinner
79
-
80
- before_dinner do
81
- self.a = 10
82
- end
83
- before_dinner do
84
- self.b = 20
85
- end
86
- end
87
-
88
- foo = Foo.new
89
- foo.run_callback(:before_dinner)
90
- expect(foo.a).to eq(10)
91
- expect(foo.b).to eq(20)
92
- end
93
-
94
- it 'defines multiple callback group' do
95
- stub_const 'Foo', Class.new
96
- Foo.class_eval do
97
- include React::Callbacks
98
- define_callback :before_dinner
99
- define_callback :after_dinner
100
- attr_accessor :a
101
-
102
- before_dinner do
103
- self.a = 10
104
- end
105
- end
106
-
107
- foo = Foo.new
108
- foo.run_callback(:before_dinner)
109
- foo.run_callback(:after_dinner)
110
-
111
- expect(foo.a).to eq(10)
112
- end
113
-
114
- it 'receives args as callback' do
115
- stub_const 'Foo', Class.new
116
- Foo.class_eval do
117
- include React::Callbacks
118
- define_callback :before_dinner
119
- define_callback :after_dinner
120
-
121
- attr_accessor :lorem
122
-
123
- before_dinner do |a, b|
124
- self.lorem = "#{a}-#{b}"
125
- end
126
-
127
- after_dinner :eat_ice_cream
128
- def eat_ice_cream(a,b,c); end
129
- end
130
-
131
- foo = Foo.new
132
- expect(foo).to receive(:eat_ice_cream).with(4,5,6)
133
- foo.run_callback(:before_dinner, 1, 2)
134
- foo.run_callback(:after_dinner, 4, 5, 6)
135
- expect(foo.lorem).to eq('1-2')
136
- end
137
- end
138
- end
@@ -1,76 +0,0 @@
1
- require 'spec_helper'
2
-
3
- if opal?
4
- describe React::Children do
5
- let(:component) {
6
- Class.new do
7
- include React::Component
8
- def render
9
- div { 'lorem' }
10
- end
11
- end
12
- }
13
- let(:childs) { [React.create_element('a'), React.create_element('li')] }
14
- let(:element) { React.create_element(component) { childs } }
15
- let(:children) { described_class.new(`#{element.to_n}.props.children`) }
16
-
17
- before(:each) do
18
- React::Test::Utils.render_into_document(element)
19
- end
20
-
21
- it 'is enumerable' do
22
- nodes = children.map { |elem| elem.element_type }
23
- expect(nodes).to eq(['a', 'li'])
24
- end
25
-
26
- it 'returns an Enumerator when not providing a block' do
27
- nodes = children.each
28
- expect(nodes).to be_a(Enumerator)
29
- expect(nodes.size).to eq(2)
30
- end
31
-
32
- describe '#each' do
33
- it 'returns an array of elements' do
34
- nodes = children.each { |elem| elem.element_type }
35
- expect(nodes).to be_a(Array)
36
- expect(nodes.map(&:class)).to eq(childs.map(&:class))
37
- end
38
- end
39
-
40
- describe '#length' do
41
- it 'returns the number of child elements' do
42
- expect(children.length).to eq(2)
43
- end
44
- end
45
-
46
- describe 'with single child element' do
47
- let(:childs) { [React.create_element('a')] }
48
-
49
- it 'is enumerable containing single element' do
50
- nodes = children.map { |elem| elem.element_type }
51
- expect(nodes).to eq(['a'])
52
- end
53
-
54
- describe '#length' do
55
- it 'returns the number of child elements' do
56
- expect(children.length).to eq(1)
57
- end
58
- end
59
- end
60
-
61
- describe 'with no child element' do
62
- let(:element) { React.create_element(component) }
63
-
64
- it 'is enumerable containing no elements' do
65
- nodes = children.map { |elem| elem.element_type }
66
- expect(nodes).to eq([])
67
- end
68
-
69
- describe '#length' do
70
- it 'returns the number of child elements' do
71
- expect(children.length).to eq(0)
72
- end
73
- end
74
- end
75
- end
76
- end
@@ -1,32 +0,0 @@
1
- require 'spec_helper'
2
-
3
- if opal?
4
- RSpec.describe React::Component::Base, type: :component do
5
- after(:each) do
6
- React::API.clear_component_class_cache
7
- end
8
-
9
- it 'can be inherited to create a component class' do
10
- stub_const 'Foo', Class.new(React::Component::Base)
11
- Foo.class_eval do
12
- before_mount do
13
- @instance_data = ["working"]
14
- end
15
- def render
16
- @instance_data.first
17
- end
18
- end
19
- stub_const 'Bar', Class.new(Foo)
20
- Bar.class_eval do
21
- before_mount do
22
- @instance_data << "well"
23
- end
24
- def render
25
- @instance_data.join(" ")
26
- end
27
- end
28
- expect(Foo).to render_static_html("<span>working</span>")
29
- expect(Bar).to render_static_html("<span>working well</span>")
30
- end
31
- end
32
- end
@@ -1,884 +0,0 @@
1
- require 'spec_helper'
2
-
3
- if opal?
4
- describe React::Component, type: :component do
5
- after(:each) do
6
- React::API.clear_component_class_cache
7
- end
8
-
9
- it 'defines component spec methods' do
10
- stub_const 'Foo', Class.new
11
- Foo.class_eval do
12
- include React::Component
13
- def initialize(native = nil)
14
- end
15
-
16
- def render
17
- React.create_element('div')
18
- end
19
- end
20
-
21
- # Class Methods
22
- expect(Foo).to respond_to('initial_state')
23
- expect(Foo).to respond_to('default_props')
24
- expect(Foo).to respond_to('prop_types')
25
-
26
- # Instance method
27
- expect(Foo.new).to respond_to('component_will_mount')
28
- expect(Foo.new).to respond_to('component_did_mount')
29
- expect(Foo.new).to respond_to('component_will_receive_props')
30
- expect(Foo.new).to respond_to('should_component_update?')
31
- expect(Foo.new).to respond_to('component_will_update')
32
- expect(Foo.new).to respond_to('component_did_update')
33
- expect(Foo.new).to respond_to('component_will_unmount')
34
- end
35
-
36
- describe 'Life Cycle' do
37
- let(:element_to_render) { React.create_element(Foo) }
38
-
39
- before(:each) do
40
- stub_const 'Foo', Class.new
41
- Foo.class_eval do
42
- include React::Component
43
- def render
44
- React.create_element('div') { 'lorem' }
45
- end
46
- end
47
- end
48
-
49
- it 'invokes `before_mount` registered methods when `componentWillMount()`' do
50
- Foo.class_eval do
51
- before_mount :bar, :bar2
52
- def bar; end
53
- def bar2; end
54
- end
55
-
56
- expect_any_instance_of(Foo).to receive(:bar)
57
- expect_any_instance_of(Foo).to receive(:bar2)
58
-
59
- React::Test::Utils.render_into_document(element_to_render)
60
- end
61
-
62
- it 'invokes `after_mount` registered methods when `componentDidMount()`' do
63
- Foo.class_eval do
64
- after_mount :bar3, :bar4
65
- def bar3; end
66
- def bar4; end
67
- end
68
-
69
- expect_any_instance_of(Foo).to receive(:bar3)
70
- expect_any_instance_of(Foo).to receive(:bar4)
71
-
72
- React::Test::Utils.render_into_document(element_to_render)
73
- end
74
-
75
- it 'allows multiple class declared life cycle hooker' do
76
- stub_const 'FooBar', Class.new
77
- Foo.class_eval do
78
- before_mount :bar
79
- def bar; end
80
- end
81
-
82
- FooBar.class_eval do
83
- include React::Component
84
- after_mount :bar2
85
- def bar2; end
86
- def render
87
- React.create_element('div') { 'lorem' }
88
- end
89
- end
90
-
91
- expect_any_instance_of(Foo).to receive(:bar)
92
-
93
- React::Test::Utils.render_into_document(element_to_render)
94
- end
95
-
96
- it 'allows block for life cycle callback' do
97
- Foo.class_eval do
98
- before_mount do
99
- set_state({ foo: "bar" })
100
- end
101
- end
102
-
103
- instance = React::Test::Utils.render_into_document(element_to_render)
104
- expect(instance.state[:foo]).to be('bar')
105
- end
106
- end
107
-
108
- describe 'New style setter & getter' do
109
- before(:each) do
110
- stub_const 'Foo', Class.new
111
- Foo.class_eval do
112
- include React::Component
113
- def render
114
- div { state.foo }
115
- end
116
- end
117
- end
118
-
119
- it 'implicitly will create a state variable when first written' do
120
- Foo.class_eval do
121
- before_mount do
122
- state.foo! 'bar'
123
- end
124
- end
125
-
126
- expect(Foo).to render_static_html('<div>bar</div>')
127
- end
128
-
129
- it 'allows kernal method names like "format" to be used as state variable names' do
130
- Foo.class_eval do
131
- before_mount do
132
- state.format! 'yes'
133
- state.foo! state.format
134
- end
135
- end
136
-
137
- expect(Foo).to render_static_html('<div>yes</div>')
138
- end
139
-
140
- it 'returns an observer with the bang method and no arguments' do
141
- Foo.class_eval do
142
- before_mount do
143
- state.foo!(state.baz!.class.name)
144
- end
145
- end
146
-
147
- expect(Foo).to render_static_html('<div>React::Observable</div>')
148
- end
149
-
150
- it 'returns the current value of a state when written' do
151
- Foo.class_eval do
152
- before_mount do
153
- state.baz! 'bar'
154
- state.foo!(state.baz!('pow'))
155
- end
156
- end
157
-
158
- expect(Foo).to render_static_html('<div>bar</div>')
159
- end
160
-
161
- it 'can access an explicitly defined state`' do
162
- Foo.class_eval do
163
- define_state foo: :bar
164
- end
165
-
166
- expect(Foo).to render_static_html('<div>bar</div>')
167
- end
168
-
169
- end
170
-
171
- describe 'State setter & getter' do
172
- let(:element_to_render) { React.create_element(Foo) }
173
-
174
- before(:each) do
175
- stub_const 'Foo', Class.new
176
- Foo.class_eval do
177
- include React::Component
178
- def render
179
- React.create_element('div') { 'lorem' }
180
- end
181
- end
182
- end
183
-
184
- it 'defines setter using `define_state`' do
185
- Foo.class_eval do
186
- define_state :foo
187
- before_mount :set_up
188
- def set_up
189
- mutate.foo 'bar'
190
- end
191
- end
192
-
193
- instance = React::Test::Utils.render_into_document(element_to_render)
194
- expect(instance.state.foo).to be('bar')
195
- end
196
-
197
- it 'defines init state by passing a block to `define_state`' do
198
- Foo.class_eval do
199
- define_state(:foo) { 10 }
200
- end
201
-
202
- instance = React::Test::Utils.render_into_document(element_to_render)
203
- expect(instance.state.foo).to be(10)
204
- end
205
-
206
- it 'defines getter using `define_state`' do
207
- Foo.class_eval do
208
- define_state(:foo) { 10 }
209
- before_mount :bump
210
- def bump
211
- mutate.foo(state.foo + 20)
212
- end
213
- end
214
-
215
- instance = React::Test::Utils.render_into_document(element_to_render)
216
- expect(instance.state.foo).to be(30)
217
- end
218
-
219
- it 'defines multiple state accessors by passing array to `define_state`' do
220
- Foo.class_eval do
221
- define_state :foo, :foo2
222
- before_mount :set_up
223
- def set_up
224
- mutate.foo 10
225
- mutate.foo2 20
226
- end
227
- end
228
-
229
- instance = React::Test::Utils.render_into_document(element_to_render)
230
- expect(instance.state.foo).to be(10)
231
- expect(instance.state.foo2).to be(20)
232
- end
233
-
234
- it 'invokes `define_state` multiple times to define states' do
235
- Foo.class_eval do
236
- define_state(:foo) { 30 }
237
- define_state(:foo2) { 40 }
238
- end
239
-
240
- instance = React::Test::Utils.render_into_document(element_to_render)
241
- expect(instance.state.foo).to be(30)
242
- expect(instance.state.foo2).to be(40)
243
- end
244
-
245
- it 'can initialize multiple state variables with a block' do
246
- Foo.class_eval do
247
- define_state(:foo, :foo2) { 30 }
248
- end
249
-
250
- instance = React::Test::Utils.render_into_document(element_to_render)
251
- expect(instance.state.foo).to be(30)
252
- expect(instance.state.foo2).to be(30)
253
- end
254
-
255
- it 'can mix multiple state variables with initializers and a block' do
256
- Foo.class_eval do
257
- define_state(:x, :y, foo: 1, bar: 2) {3}
258
- end
259
- instance = React::Test::Utils.render_into_document(element_to_render)
260
- expect(instance.state.x).to be(3)
261
- expect(instance.state.y).to be(3)
262
- expect(instance.state.foo).to be(1)
263
- expect(instance.state.bar).to be(2)
264
- end
265
-
266
- it 'gets state in render method' do
267
- Foo.class_eval do
268
- define_state(:foo) { 10 }
269
- def render
270
- React.create_element('div') { state.foo }
271
- end
272
- end
273
-
274
- instance = React::Test::Utils.render_into_document(element_to_render)
275
- expect(`#{instance.dom_node}.textContent`).to eq('10')
276
- end
277
-
278
- it 'supports original `setState` as `set_state` method' do
279
- Foo.class_eval do
280
- before_mount do
281
- self.set_state(foo: 'bar')
282
- end
283
- end
284
-
285
- instance = renderToDocument(Foo)
286
- expect(instance.state[:foo]).to be('bar')
287
- end
288
-
289
- it 'supports original `replaceState` as `set_state!` method' do
290
- Foo.class_eval do
291
- before_mount do
292
- set_state(foo: 'bar')
293
- set_state!(bar: 'lorem')
294
- end
295
- end
296
-
297
- element = renderToDocument(Foo)
298
- puts "*************************************************************************************"
299
- puts "element.state[:foo] = #{element.state[:foo]}"
300
- puts "element.state[:bar] = #{element.state[:bar]}"
301
- puts "*************************************************************************************"
302
- expect(element.state[:foo]).to be_nil
303
- expect(element.state[:bar]).to eq('lorem')
304
- end
305
-
306
- it 'supports original `state` method' do
307
- Foo.class_eval do
308
- before_mount do
309
- self.set_state(foo: 'bar')
310
- end
311
-
312
- def render
313
- div { self.state[:foo] }
314
- end
315
- end
316
-
317
- expect(Foo).to render_static_html('<div>bar</div>')
318
- end
319
-
320
- it 'transforms state getter to Ruby object' do
321
- Foo.class_eval do
322
- define_state :foo
323
-
324
- before_mount do
325
- mutate.foo [{a: "Hello"}]
326
- end
327
-
328
- def render
329
- div { state.foo[0][:a] }
330
- end
331
- end
332
-
333
- expect(Foo).to render_static_html('<div>Hello</div>')
334
- end
335
- end
336
-
337
- describe 'Props' do
338
- describe 'this.props could be accessed through `params` method' do
339
- before do
340
- stub_const 'Foo', Class.new
341
- Foo.class_eval do
342
- include React::Component
343
- end
344
- end
345
-
346
- it 'reads from parent passed properties through `params`' do
347
- Foo.class_eval do
348
- def render
349
- React.create_element('div') { params[:prop] }
350
- end
351
- end
352
-
353
- element = renderToDocument(Foo, prop: 'foobar')
354
- expect(`#{element.dom_node}.textContent`).to eq('foobar')
355
- end
356
-
357
- it 'accesses nested params as orignal Ruby object' do
358
- Foo.class_eval do
359
- def render
360
- React.create_element('div') { params[:prop][0][:foo] }
361
- end
362
- end
363
-
364
- element = renderToDocument(Foo, prop: [{foo: 10}])
365
- expect(`#{element.dom_node}.textContent`).to eq('10')
366
- end
367
- end
368
-
369
- describe 'Props Updating', v13_only: true do
370
- before do
371
- stub_const 'Foo', Class.new
372
- Foo.class_eval do
373
- include React::Component
374
- end
375
- end
376
-
377
- it 'supports original `setProps` as method `set_props`' do
378
- Foo.class_eval do
379
- def render
380
- React.create_element('div') { params[:foo] }
381
- end
382
- end
383
-
384
- element = renderToDocument(Foo, {foo: 10})
385
- element.set_props(foo: 20)
386
- expect(`#{element.dom_node}.innerHTML`).to eq('20')
387
- end
388
-
389
- it 'supports original `replaceProps` as method `set_props!`' do
390
- Foo.class_eval do
391
- def render
392
- React.create_element('div') { params[:foo] ? 'exist' : 'null' }
393
- end
394
- end
395
-
396
- instance = renderToDocument(Foo, {foo: 10})
397
- instance.set_props!(bar: 20)
398
- expect(`#{instance.dom_node}.innerHTML`).to eq('null')
399
- end
400
- end
401
-
402
- describe 'Prop validation' do
403
- before do
404
- stub_const 'Foo', Class.new
405
- Foo.class_eval do
406
- include React::Component
407
- end
408
- end
409
-
410
- it 'specifies validation rules using `params` class method' do
411
- Foo.class_eval do
412
- params do
413
- requires :foo, type: String
414
- optional :bar
415
- end
416
- end
417
-
418
- expect(Foo.prop_types).to have_key(:_componentValidator)
419
- end
420
-
421
- it 'logs error in warning if validation failed' do
422
- stub_const 'Lorem', Class.new
423
- Foo.class_eval do
424
- params do
425
- requires :foo
426
- requires :lorem, type: Lorem
427
- optional :bar, type: String
428
- end
429
-
430
- def render; div; end
431
- end
432
-
433
- %x{
434
- var log = [];
435
- var org_warn_console = window.console.warn;
436
- var org_error_console = window.console.error;
437
- window.console.warn = window.console.error = function(str){log.push(str)}
438
- }
439
- renderToDocument(Foo, bar: 10, lorem: Lorem.new)
440
- `window.console.warn = org_warn_console; window.console.error = org_error_console;`
441
- expect(`log[0]`).to match(/Warning: Failed prop( type|Type): In component `Foo`\nRequired prop `foo` was not specified\nProvided prop `bar` could not be converted to String/)
442
- end
443
-
444
- it 'should not log anything if validation pass' do
445
- stub_const 'Lorem', Class.new
446
- Foo.class_eval do
447
- params do
448
- requires :foo
449
- requires :lorem, type: Lorem
450
- optional :bar, type: String
451
- end
452
-
453
- def render; div; end
454
- end
455
-
456
- %x{
457
- var log = [];
458
- var org_warn_console = window.console.warn;
459
- var org_error_console = window.console.error
460
- window.console.warn = window.console.error = function(str){log.push(str)}
461
- }
462
- renderToDocument(Foo, foo: 10, bar: '10', lorem: Lorem.new)
463
- `window.console.warn = org_warn_console; window.console.error = org_error_console;`
464
- expect(`log`).to eq([])
465
- end
466
- end
467
-
468
- describe 'Default props' do
469
- it 'sets default props using validation helper' do
470
- stub_const 'Foo', Class.new
471
- Foo.class_eval do
472
- include React::Component
473
- params do
474
- optional :foo, default: 'foo'
475
- optional :bar, default: 'bar'
476
- end
477
-
478
- def render
479
- div { params[:foo] + '-' + params[:bar]}
480
- end
481
- end
482
-
483
- expect(Foo).to render_static_html('<div>lorem-bar</div>').with_params(foo: 'lorem')
484
- expect(Foo).to render_static_html('<div>foo-bar</div>')
485
- end
486
- end
487
- end
488
-
489
- describe 'Anonymous Component' do
490
- it "will not generate spurious warning messages" do
491
- foo = Class.new(React::Component::Base)
492
- foo.class_eval do
493
- def render; "hello" end
494
- end
495
-
496
- %x{
497
- var log = [];
498
- var org_warn_console = window.console.warn;
499
- var org_error_console = window.console.error
500
- window.console.warn = window.console.error = function(str){log.push(str)}
501
- }
502
- renderToDocument(foo)
503
- `window.console.warn = org_warn_console; window.console.error = org_error_console;`
504
- expect(`log`).to eq([])
505
- end
506
- end
507
-
508
- describe 'Render Error Handling' do
509
- before(:each) do
510
- %x{
511
- window.test_log = [];
512
- window.org_warn_console = window.console.warn;
513
- window.org_error_console = window.console.error
514
- window.console.warn = window.console.error = function(str){window.test_log.push(str)}
515
- }
516
- end
517
- it "will generate a message if render returns something other than an Element or a String" do
518
- foo = Class.new(React::Component::Base)
519
- foo.class_eval do
520
- def render; Hash.new; end
521
- end
522
-
523
- renderToDocument(foo)
524
- `window.console.warn = window.org_warn_console; window.console.error = window.org_error_console;`
525
- expect(`test_log`.first).to match /Instead the Hash \{\} was returned/
526
- end
527
- it "will generate a message if render returns a Component class" do
528
- stub_const 'Foo', Class.new(React::Component::Base)
529
- foo = Class.new(React::Component::Base)
530
- foo.class_eval do
531
- def render; Foo; end
532
- end
533
-
534
- renderToDocument(foo)
535
- `window.console.warn = window.org_warn_console; window.console.error = window.org_error_console;`
536
- expect(`test_log`.first).to match /Did you mean Foo()/
537
- end
538
- it "will generate a message if more than 1 element is generated" do
539
- foo = Class.new(React::Component::Base)
540
- foo.class_eval do
541
- def render; "hello".span; "goodby".span; end
542
- end
543
-
544
- renderToDocument(foo)
545
- `window.console.warn = window.org_warn_console; window.console.error = window.org_error_console;`
546
- expect(`test_log`.first).to match /Instead 2 elements were generated/
547
- end
548
- it "will generate a message if the element generated is not the element returned" do
549
- foo = Class.new(React::Component::Base)
550
- foo.class_eval do
551
- def render; "hello".span; "goodby".span.delete; end
552
- end
553
-
554
- renderToDocument(foo)
555
- `window.console.warn = window.org_warn_console; window.console.error = window.org_error_console;`
556
- expect(`test_log`.first).to match /A different element was returned than was generated within the DSL/
557
- end
558
- end
559
-
560
- describe 'Event handling' do
561
- before do
562
- stub_const 'Foo', Class.new
563
- Foo.class_eval do
564
- include React::Component
565
- end
566
- end
567
-
568
- it 'works in render method' do
569
- Foo.class_eval do
570
- define_state(:clicked) { false }
571
-
572
- def render
573
- React.create_element('div').on(:click) do
574
- mutate.clicked true
575
- end
576
- end
577
- end
578
-
579
- element = React.create_element(Foo)
580
- instance = React::Test::Utils.render_into_document(element)
581
- React::Test::Utils.simulate(:click, instance)
582
- expect(instance.state.clicked).to eq(true)
583
- end
584
-
585
- it 'invokes handler on `this.props` using emit' do
586
- Foo.class_eval do
587
- param :_onFooSubmit, type: Proc
588
- after_mount :setup
589
-
590
- def setup
591
- puts "***************************** about to emit******************************"
592
- self.emit(:foo_submit, 'bar')
593
- puts "***************************** emitted!!! ********************************"
594
- rescue Exception => e
595
- puts "FAILED FAILED FAILED #{e}"
596
- end
597
-
598
- def render
599
- React.create_element('div')
600
- end
601
- end
602
-
603
- expect { |b|
604
- element = React.create_element(Foo).on(:foo_submit, &b)
605
- React::Test::Utils.render_into_document(element)
606
- }.to yield_with_args('bar')
607
- end
608
-
609
- it 'invokes handler with multiple params using emit' do
610
- Foo.class_eval do
611
- param :_onFooInvoked, type: Proc
612
- after_mount :setup
613
-
614
- def setup
615
- self.emit(:foo_invoked, [1,2,3], 'bar')
616
- end
617
-
618
- def render
619
- React.create_element('div')
620
- end
621
- end
622
-
623
- expect { |b|
624
- element = React.create_element(Foo).on(:foo_invoked, &b)
625
- React::Test::Utils.render_into_document(element)
626
- }.to yield_with_args([1,2,3], 'bar')
627
- end
628
- end
629
-
630
- describe '#refs' do
631
- before do
632
- stub_const 'Foo', Class.new
633
- Foo.class_eval do
634
- include React::Component
635
- end
636
- end
637
-
638
- it 'correctly assigns refs' do
639
- Foo.class_eval do
640
- def render
641
- React.create_element('input', type: :text, ref: :field)
642
- end
643
- end
644
-
645
- instance = renderToDocument(Foo)
646
- expect(instance.refs[:field]).not_to be_nil
647
- end
648
-
649
- it 'accesses refs through `refs` method' do
650
- Foo.class_eval do
651
- def render
652
- React.create_element('input', type: :text, ref: :field).on(:click) do
653
- refs[:field].value = 'some_stuff'
654
- end
655
- end
656
- end
657
-
658
- instance = React::Test::Utils.render_into_document(React.create_element(Foo))
659
- React::Test::Utils.simulate(:click, instance)
660
- expect(instance.refs[:field].value).to eq('some_stuff')
661
- end
662
-
663
- it "allows access the actual DOM node", v13_exclude: true do
664
- Foo.class_eval do
665
- after_mount do
666
- dom = refs[:my_div].to_n
667
- `dom.innerHTML = 'Modified'`
668
- end
669
-
670
- def render
671
- React.create_element('div', ref: :my_div) { "Original Content" }
672
- end
673
- end
674
-
675
- instance = renderToDocument(Foo)
676
- expect(`#{instance.dom_node}.innerHTML`).to eq('Modified')
677
- end
678
- end
679
-
680
- describe '#render' do
681
- it 'supports element building helpers' do
682
- stub_const 'Foo', Class.new
683
- Foo.class_eval do
684
- include React::Component
685
-
686
- def render
687
- div do
688
- span { params[:foo] }
689
- end
690
- end
691
- end
692
-
693
- stub_const 'Bar', Class.new
694
- Bar.class_eval do
695
- include React::Component
696
- def render
697
- div do
698
- present Foo, foo: 'astring'
699
- end
700
- end
701
- end
702
-
703
- expect(Bar).to render_static_html('<div><div><span>astring</span></div></div>')
704
- end
705
-
706
- it 'builds single node in top-level render without providing a block' do
707
- stub_const 'Foo', Class.new
708
- Foo.class_eval do
709
- include React::Component
710
-
711
- def render
712
- div
713
- end
714
- end
715
-
716
- expect(Foo).to render_static_html('<div></div>')
717
- end
718
-
719
- it 'redefines `p` to make method missing work' do
720
- stub_const 'Foo', Class.new
721
- Foo.class_eval do
722
- include React::Component
723
-
724
- def render
725
- div {
726
- p(class_name: 'foo')
727
- p
728
- div { 'lorem ipsum' }
729
- p(id: '10')
730
- }
731
- end
732
- end
733
-
734
- markup = '<div><p class="foo"></p><p></p><div>lorem ipsum</div><p id="10"></p></div>'
735
- expect(Foo).to render_static_html(markup)
736
- end
737
-
738
- it 'only overrides `p` in render context' do
739
- stub_const 'Foo', Class.new
740
- Foo.class_eval do
741
- include React::Component
742
-
743
- before_mount do
744
- p 'first'
745
- end
746
-
747
- after_mount do
748
- p 'second'
749
- end
750
-
751
- def render
752
- div
753
- end
754
- end
755
-
756
- expect(Kernel).to receive(:p).with('first')
757
- expect(Kernel).to receive(:p).with('second')
758
- renderToDocument(Foo)
759
- end
760
- end
761
-
762
- describe 'isMounted()' do
763
- it 'returns true if after mounted' do
764
- stub_const 'Foo', Class.new
765
- Foo.class_eval do
766
- include React::Component
767
-
768
- def render
769
- React.create_element('div')
770
- end
771
- end
772
-
773
- component = renderToDocument(Foo)
774
- expect(component.mounted?).to eq(true)
775
- end
776
- end
777
-
778
- describe '.params_changed?' do
779
-
780
- before(:each) do
781
- stub_const 'Foo', Class.new(React::Component::Base)
782
- Foo.define_method :needs_update? do |next_params, next_state|
783
- next_params.changed?
784
- end
785
- @foo = Foo.new(nil)
786
- end
787
-
788
- it "returns false if new and old params are the same" do
789
- @foo.instance_variable_set("@native", `{props: {value1: 1, value2: 2}}`)
790
- expect(@foo.should_component_update?(`{value2: 2, value1: 1}`, `null`)).to be_falsy
791
- end
792
-
793
- it "returns true if new and old params are have different values" do
794
- @foo.instance_variable_set("@native", `{props: {value1: 1, value2: 2}}`)
795
- expect(@foo.should_component_update?(`{value2: 2, value1: 2}`, `null`)).to be_truthy
796
- end
797
-
798
- it "returns true if new and old params are have different keys" do
799
- @foo.instance_variable_set("@native", `{props: {value1: 1, value2: 2}}`)
800
- expect(@foo.should_component_update?(`{value2: 2, value1: 1, value3: 3}`, `null`)).to be_truthy
801
- end
802
- end
803
-
804
- describe '#state_changed?' do
805
-
806
- empties = [`{}`, `undefined`, `null`, `false`]
807
-
808
- before(:each) do
809
- stub_const 'Foo', Class.new(React::Component::Base)
810
- Foo.define_method :needs_update? do |next_params, next_state|
811
- next_state.changed?
812
- end
813
- @foo = Foo.new(nil)
814
- end
815
-
816
- it "returns false if both new and old states are empty" do
817
- empties.each do |empty1|
818
- empties.each do |empty2|
819
- @foo.instance_variable_set("@native", `{state: #{empty1}}`)
820
- expect(@foo.should_component_update?(`{}`, empty2)).to be_falsy
821
- end
822
- end
823
- end
824
-
825
- it "returns true if old state is empty, but new state is not" do
826
- empties.each do |empty|
827
- @foo.instance_variable_set("@native", `{state: #{empty}}`)
828
- expect(@foo.should_component_update?(`{}`, `{foo: 12}`)).to be_truthy
829
- end
830
- end
831
-
832
- it "returns true if new state is empty, but old state is not" do
833
- empties.each do |empty|
834
- @foo.instance_variable_set("@native", `{state: {foo: 12}}`)
835
- expect(@foo.should_component_update?(`{}`, empty)).to be_truthy
836
- end
837
- end
838
-
839
- it "returns true if new state and old state have different time stamps" do
840
- @foo.instance_variable_set("@native", `{state: {'***_state_updated_at-***': 12}}`)
841
- expect(@foo.should_component_update?(`{}`, `{'***_state_updated_at-***': 13}`)).to be_truthy
842
- end
843
-
844
- it "returns false if new state and old state have the same time stamps" do
845
- @foo.instance_variable_set("@native", `{state: {'***_state_updated_at-***': 12}}`)
846
- expect(@foo.should_component_update?(`{}`, `{'***_state_updated_at-***': 12}`)).to be_falsy
847
- end
848
-
849
- end
850
-
851
- describe '#children' do
852
- before(:each) do
853
- stub_const 'Foo', Class.new
854
- Foo.class_eval do
855
- include React::Component
856
- def render
857
- React.create_element('div') { 'lorem' }
858
- end
859
- end
860
- end
861
-
862
- it 'returns React::Children collection with child elements' do
863
- ele = React.create_element(Foo) {
864
- [React.create_element('a'), React.create_element('li')]
865
- }
866
- instance = React::Test::Utils.render_into_document(ele)
867
-
868
- children = instance.children
869
-
870
- expect(children).to be_a(React::Children)
871
- expect(children.count).to eq(2)
872
- expect(children.map(&:element_type)).to eq(['a', 'li'])
873
- end
874
-
875
- it 'returns an empty Enumerator if there are no children' do
876
- ele = React.create_element(Foo)
877
- instance = React::Test::Utils.render_into_document(ele)
878
- nodes = instance.children.each
879
- expect(nodes.size).to eq(0)
880
- expect(nodes.count).to eq(0)
881
- end
882
- end
883
- end
884
- end