hyper-react 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +26 -4
  3. data/Appraisals +3 -2
  4. data/CHANGELOG.md +19 -0
  5. data/README.md +3 -3
  6. data/config.ru +2 -1
  7. data/gemfiles/opal_0.10_react_13.gemfile +13 -0
  8. data/gemfiles/opal_0.10_react_14.gemfile +13 -0
  9. data/gemfiles/opal_0.10_react_15.gemfile +13 -0
  10. data/gemfiles/opal_0.8_react_15.gemfile +1 -1
  11. data/gemfiles/opal_0.9_react_15.gemfile +1 -1
  12. data/hyper-react.gemspec +1 -1
  13. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +0 -1
  14. data/lib/hyper-react.rb +2 -1
  15. data/lib/react/api.rb +3 -2
  16. data/lib/react/component/class_methods.rb +2 -2
  17. data/lib/react/component/props_wrapper.rb +2 -2
  18. data/lib/react/element.rb +1 -1
  19. data/lib/react/ext/opal-jquery/element.rb +26 -0
  20. data/lib/react/state.rb +6 -5
  21. data/lib/react/test/matchers/render_html_matcher.rb +5 -0
  22. data/lib/react/test/session.rb +14 -23
  23. data/lib/react/test/utils.rb +25 -0
  24. data/lib/react/top_level.rb +12 -28
  25. data/lib/react/top_level_render.rb +29 -0
  26. data/lib/reactive-ruby/isomorphic_helpers.rb +2 -2
  27. data/lib/reactive-ruby/version.rb +1 -1
  28. data/spec/index.html.erb +1 -0
  29. data/spec/react/children_spec.rb +1 -1
  30. data/spec/react/component/base_spec.rb +2 -2
  31. data/spec/react/component_spec.rb +74 -73
  32. data/spec/react/dsl_spec.rb +24 -21
  33. data/spec/react/element_spec.rb +7 -7
  34. data/spec/react/event_spec.rb +2 -2
  35. data/spec/react/native_library_spec.rb +20 -24
  36. data/spec/react/observable_spec.rb +36 -1
  37. data/spec/react/opal_jquery_extensions_spec.rb +48 -46
  38. data/spec/react/param_declaration_spec.rb +8 -8
  39. data/spec/react/react_spec.rb +41 -28
  40. data/spec/react/test/rspec_spec.rb +1 -1
  41. data/spec/react/test/session_spec.rb +8 -20
  42. data/spec/react/test/utils_spec.rb +11 -28
  43. data/spec/react/top_level_component_spec.rb +7 -2
  44. data/spec/react/tutorial/tutorial_spec.rb +2 -2
  45. data/spec/reactive-ruby/component_loader_spec.rb +10 -4
  46. data/spec/reactive-ruby/isomorphic_helpers_spec.rb +6 -1
  47. data/spec/spec_helper.rb +2 -0
  48. data/spec/support/react/spec_helpers.rb +1 -21
  49. metadata +12 -6
@@ -12,7 +12,7 @@ describe 'the param macro', type: :component do
12
12
  end
13
13
  end
14
14
 
15
- expect(Foo).to render('<div>biz</div>').with_params(bar: 'biz')
15
+ expect(Foo).to render_static_html('<div>biz</div>').with_params(bar: 'biz')
16
16
  end
17
17
 
18
18
  it "can create and access a required param" do
@@ -25,7 +25,7 @@ describe 'the param macro', type: :component do
25
25
  end
26
26
  end
27
27
 
28
- expect(Foo).to render('<div>bar</div>').with_params(foo: :bar)
28
+ expect(Foo).to render_static_html('<div>bar</div>').with_params(foo: :bar)
29
29
  end
30
30
 
31
31
  it "can create and access an optional params" do
@@ -42,7 +42,7 @@ describe 'the param macro', type: :component do
42
42
  end
43
43
  end
44
44
 
45
- expect(Foo).to render('<div>bar1-no_bar2-bar3-no_bar4</div>').with_params(foo1: :bar1, foo3: :bar3)
45
+ expect(Foo).to render_static_html('<div>bar1-no_bar2-bar3-no_bar4</div>').with_params(foo1: :bar1, foo3: :bar3)
46
46
  end
47
47
 
48
48
  it 'can specify validation rules with the type option' do
@@ -66,7 +66,7 @@ describe 'the param macro', type: :component do
66
66
  end
67
67
  end
68
68
 
69
- expect(Foo).to render('<div>12-string</div>').with_params(foo1: 12, foo2: "string")
69
+ expect(Foo).to render_static_html('<div>12-string</div>').with_params(foo1: 12, foo2: "string")
70
70
  end
71
71
 
72
72
  it 'logs error in warning if validation failed' do
@@ -167,7 +167,7 @@ describe 'the param macro', type: :component do
167
167
  end
168
168
 
169
169
  params = { foo: "", bar: { bazwoggle: 1 }, baz: [{ bazwoggle: 2 }] }
170
- expect(Foo).to render('<span>1, 2</span>').with_params(params)
170
+ expect(Foo).to render_static_html('<span>1, 2</span>').with_params(params)
171
171
  expect(`window.dummy_log[0]`).to match(/Warning: Failed prop( type|Type): In component `Foo`\nProvided prop `foo` could not be converted to BazWoggle/)
172
172
  end
173
173
 
@@ -190,7 +190,7 @@ describe 'the param macro', type: :component do
190
190
  "#{params.foo.kind}"
191
191
  end
192
192
  end
193
- expect(React.render_to_static_markup(React.create_element(Foo, foo: {bazwoggle: 1}))).to eq('<span>2</span>')
193
+ expect(Foo).to render_static_html('<span>2</span>').with_params(foo: {bazwoggle: 1})
194
194
  end
195
195
 
196
196
  it "even if contains an embedded native object" do
@@ -235,7 +235,7 @@ describe 'the param macro', type: :component do
235
235
  params.foo
236
236
  end
237
237
  end
238
- expect(Foo).to render('<span>works!</span>').with_params(foo: lambda { 'works!' })
238
+ expect(Foo).to render_static_html('<span>works!</span>').with_params(foo: lambda { 'works!' })
239
239
  end
240
240
 
241
241
  it "will create a 'bang' (i.e. update) method if the type is React::Observable" do
@@ -250,7 +250,7 @@ describe 'the param macro', type: :component do
250
250
  end
251
251
  current_state = ""
252
252
  observer = React::Observable.new(current_state) { |new_state| current_state = new_state }
253
- expect(Foo).to render('<span>ha!</span>').with_params(foo: observer)
253
+ expect(Foo).to render_static_html('<span>ha!</span>').with_params(foo: observer)
254
254
  expect(current_state).to eq("ha!")
255
255
  end
256
256
  end
@@ -6,28 +6,28 @@ RSpec.describe React, type: :component do
6
6
  React::API.clear_component_class_cache
7
7
  end
8
8
 
9
- describe "is_valid_element" do
9
+ describe "is_valid_element?" do
10
10
  it "should return true if passed a valid element" do
11
11
  element = React::Element.new(`React.createElement('div')`)
12
- expect(React.is_valid_element(element)).to eq(true)
12
+ expect(React.is_valid_element?(element)).to eq(true)
13
13
  end
14
14
 
15
15
  it "should return false is passed a non React element" do
16
16
  element = React::Element.new(`{}`)
17
- expect(React.is_valid_element(element)).to eq(false)
17
+ expect(React.is_valid_element?(element)).to eq(false)
18
18
  end
19
19
  end
20
20
 
21
21
  describe "create_element" do
22
22
  it "should create a valid element with only tag" do
23
23
  element = React.create_element('div')
24
- expect(React.is_valid_element(element)).to eq(true)
24
+ expect(React.is_valid_element?(element)).to eq(true)
25
25
  end
26
26
 
27
27
  context "with block" do
28
28
  it "should create a valid element with text as only child when block yield String" do
29
29
  element = React.create_element('div') { "lorem ipsum" }
30
- expect(React.is_valid_element(element)).to eq(true)
30
+ expect(React.is_valid_element?(element)).to eq(true)
31
31
  expect(element.props.children).to eq("lorem ipsum")
32
32
  end
33
33
 
@@ -35,7 +35,7 @@ RSpec.describe React, type: :component do
35
35
  element = React.create_element('div') do
36
36
  [React.create_element('span'), React.create_element('span'), React.create_element('span')]
37
37
  end
38
- expect(React.is_valid_element(element)).to eq(true)
38
+ expect(React.is_valid_element?(element)).to eq(true)
39
39
  expect(element.props.children.length).to eq(3)
40
40
  end
41
41
 
@@ -43,8 +43,9 @@ RSpec.describe React, type: :component do
43
43
  element = React.create_element('div') do
44
44
  [React.create_element('span'), React.create_element('span'), React.create_element('span')]
45
45
  end
46
- instance = renderElementToDocument(element)
47
- expect(Element[instance].children.length).to eq(3)
46
+ dom_node = React::Test::Utils.render_into_document(element)
47
+
48
+ expect(`#{dom_node}.children.length`).to eq(3)
48
49
  end
49
50
  end
50
51
 
@@ -52,29 +53,37 @@ RSpec.describe React, type: :component do
52
53
  before do
53
54
  stub_const 'Foo', Class.new
54
55
  Foo.class_eval do
56
+ def initialize(native)
57
+ @native = native
58
+ end
59
+
55
60
  def render
56
61
  React.create_element("div") { "lorem" }
57
62
  end
63
+
64
+ def props
65
+ Hash.new(`#@native.props`)
66
+ end
58
67
  end
59
68
  end
60
69
 
61
70
  it "should render element with only one children correctly" do
62
71
  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")
72
+ instance = React::Test::Utils.render_into_document(element)
73
+ expect(instance.props[:children]).not_to be_a(Array)
74
+ expect(instance.props[:children][:type]).to eq("span")
66
75
  end
67
76
 
68
77
  it "should render element with more than one children correctly" do
69
78
  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)
79
+ instance = React::Test::Utils.render_into_document(element)
80
+ expect(instance.props[:children]).to be_a(Array)
81
+ expect(instance.props[:children].length).to eq(2)
73
82
  end
74
83
 
75
84
  it "should create a valid element provided class defined `render`" do
76
85
  element = React.create_element(Foo)
77
- expect(React.is_valid_element(element)).to eq(true)
86
+ expect(React.is_valid_element?(element)).to eq(true)
78
87
  end
79
88
 
80
89
  it "should allow creating with properties" do
@@ -102,14 +111,14 @@ RSpec.describe React, type: :component do
102
111
  end
103
112
  end
104
113
 
105
- expect(Foo).to render("<div>20</div>")
114
+ expect(Foo).to render_static_html("<div>20</div>")
106
115
  end
107
116
 
108
117
  it "should match the instance cycle to ReactComponent life cycle" do
109
118
  `var count = 0;`
110
119
 
111
120
  Foo.class_eval do
112
- def initialize
121
+ def initialize(native)
113
122
  `count = count + 1;`
114
123
  end
115
124
  def render
@@ -117,8 +126,8 @@ RSpec.describe React, type: :component do
117
126
  end
118
127
  end
119
128
 
120
- renderToDocument(Foo)
121
- renderToDocument(Foo)
129
+ React::Test::Utils.render_into_document(React.create_element(Foo))
130
+ React::Test::Utils.render_into_document(React.create_element(Foo))
122
131
 
123
132
  expect(`count`).to eq(2)
124
133
  end
@@ -172,19 +181,23 @@ RSpec.describe React, type: :component do
172
181
  React.render(React.create_element('span') { "lorem" }, div)
173
182
  end
174
183
 
175
- it "should return a React::Component::API compatible object" do
176
- div = `document.createElement("div")`
177
- component = React.render(React.create_element('span') { "lorem" }, div)
178
- React::Component::API.public_instance_methods(true).each do |method_name|
179
- expect(component).to respond_to(method_name)
184
+ it "returns the actual ruby instance" do
185
+ stub_const 'Foo', Class.new
186
+ Foo.class_eval do
187
+ def render
188
+ React.create_element("div") { "lorem" }
189
+ end
180
190
  end
191
+
192
+ div = `document.createElement("div")`
193
+ instance = React.render(React.create_element(Foo), div)
194
+ expect(instance).to be_a(Foo)
181
195
  end
182
196
 
183
- pending "should return nil to prevent abstraction leakage" do
197
+ it "returns the actual DOM node" do
184
198
  div = `document.createElement("div")`
185
- expect {
186
- React.render(React.create_element('span') { "lorem" }, div)
187
- }.to be_nil
199
+ node = React.render(React.create_element('span') { "lorem" }, div)
200
+ expect(`#{node}.nodeType`).to eq(1)
188
201
  end
189
202
  end
190
203
 
@@ -23,7 +23,7 @@ if opal?
23
23
  end
24
24
 
25
25
  it 'includes rspec matchers' do
26
- expect(Greeter).to render(
26
+ expect(Greeter).to render_static_html(
27
27
  '<span>Hello world</span>'
28
28
  ).with_params(message: 'world')
29
29
  end
@@ -41,31 +41,19 @@ if opal?
41
41
  end
42
42
  end
43
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
44
  describe '#html' do
60
45
  it 'returns the component rendered to static html' do
61
46
  subject.mount(Greeter, message: 'world')
62
47
  expect(subject.html).to eq('<span>Hello world</span>')
63
48
  end
64
49
 
65
- it 'returns the updated static html' do
50
+ async 'returns the updated static html' do
66
51
  subject.mount(Greeter)
67
- subject.update_params(message: 'moon')
68
- expect(subject.html).to eq('<span>Hello moon</span>')
52
+ subject.update_params(message: 'moon') do
53
+ run_async {
54
+ expect(subject.html).to eq('<span>Hello moon</span>')
55
+ }
56
+ end
69
57
  end
70
58
  end
71
59
 
@@ -89,11 +77,11 @@ if opal?
89
77
  end
90
78
  end
91
79
 
92
- describe '#force_update' do
80
+ describe 'instance#force_update!' do
93
81
  it 'causes the component to render' do
94
82
  instance = subject.mount(Greeter)
95
83
  expect(instance).to receive(:render)
96
- subject.force_update!
84
+ subject.instance.force_update!
97
85
  end
98
86
  end
99
87
  end
@@ -1,45 +1,28 @@
1
1
  require 'spec_helper'
2
2
 
3
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
4
  RSpec.describe React::Test::Utils do
25
5
  it 'simulates' do
26
6
  stub_const 'Foo', Class.new
27
7
  Foo.class_eval do
28
8
  include React::Component
29
9
 
30
- def hello
31
- @hello
32
- end
33
-
34
10
  def render
35
- @hello = 'hello'
36
11
  div { 'Click Me' }.on(:click) { |e| click(e) }
37
12
  end
38
13
  end
39
14
 
40
- instance = renderToDocument(Foo)
41
- expect_any_instance_of(Foo).to receive(:click)
42
- described_class.simulate(:click, instance)
15
+ instance = React::Test::Utils.render_into_document(React.create_element(Foo))
16
+ expect(instance).to receive(:click)
17
+ described_class.simulate(:click, instance.dom_node)
18
+ end
19
+
20
+ describe "render_into_document" do
21
+ it "works with native element" do
22
+ expect {
23
+ described_class.render_into_document(React.create_element('div'))
24
+ }.to_not raise_error
25
+ end
43
26
  end
44
27
  end
45
28
  end
@@ -39,8 +39,13 @@ class Component1
39
39
  end
40
40
 
41
41
  def render_top_level(controller, component_name)
42
- render_to_html(React::TopLevelRailsComponent, controller: controller,
43
- component_name: component_name, render_params: {})
42
+ params = {
43
+ controller: controller,
44
+ component_name: component_name,
45
+ render_params: {}
46
+ }
47
+ element = React.create_element(React::TopLevelRailsComponent, params)
48
+ React.render_to_static_markup(element)
44
49
  end
45
50
 
46
51
  describe React::TopLevelRailsComponent do
@@ -10,7 +10,7 @@ end
10
10
 
11
11
  describe 'An Example from the react.rb doc', type: :component do
12
12
  it 'produces the correct result' do
13
- expect(HelloMessage).to render('<div>Hello World!</div>')
13
+ expect(HelloMessage).to render_static_html('<div>Hello World!</div>')
14
14
  end
15
15
  end
16
16
 
@@ -24,7 +24,7 @@ end
24
24
 
25
25
  describe 'Adding state to a component (second tutorial example)', type: :component do
26
26
  it "produces the correct result" do
27
- expect(HelloMessage2).to render('<div>Hello @catmando</div>')
27
+ expect(HelloMessage2).to render_static_html('<div>Hello @catmando</div>')
28
28
  end
29
29
 
30
30
  it 'renders to the document' do
@@ -3,15 +3,21 @@ require 'spec_helper'
3
3
  if ruby?
4
4
  RSpec.describe ReactiveRuby::ComponentLoader do
5
5
  GLOBAL_WRAPPER = <<-JS
6
- var global = global || this;
7
- var self = self || this;
8
- var window = window || this;
6
+ #{React::ServerRendering::ExecJSRenderer::GLOBAL_WRAPPER}
9
7
  var console = {
10
8
  warn: function(s) { }
11
9
  };
12
10
  JS
13
11
 
14
- let(:js) { ::Rails.application.assets['components'].to_s }
12
+ let(:js) do
13
+ if ::Rails.application.assets['react-server.js'] &&
14
+ !::Rails.application.assets['react-server.js'].to_s.start_with?("// A placeholder file")
15
+ react_source = ::Rails.application.assets['react-server.js']
16
+ else
17
+ react_source = ::Rails.application.assets['react.js']
18
+ end
19
+ ::Rails.application.assets['components'].to_s + react_source.to_s
20
+ end
15
21
  let(:context) { ExecJS.compile(GLOBAL_WRAPPER + js) }
16
22
  let(:v8_context) { ReactiveRuby::ServerRendering.context_instance_for(context) }
17
23
 
@@ -77,7 +77,12 @@ if ruby?
77
77
  end
78
78
 
79
79
  def react_context
80
- test_context('components')
80
+ if ::Rails.application.assets['react-server.js'] &&
81
+ !::Rails.application.assets['react-server.js'].to_s.start_with?("// A placeholder file")
82
+ test_context(['components', 'react-server.js'])
83
+ else
84
+ test_context(['components', 'react.js'])
85
+ end
81
86
  end
82
87
 
83
88
  let(:v8_context) { TestV8Context.new }
@@ -18,6 +18,8 @@ if RUBY_ENGINE == 'opal'
18
18
  require 'react/react-source'
19
19
  require 'hyper-react'
20
20
  require 'react/test/rspec'
21
+ require 'react/test/utils'
22
+ require 'react/top_level_render'
21
23
 
22
24
  require File.expand_path('../support/react/spec_helpers', __FILE__)
23
25
 
@@ -3,29 +3,9 @@ module React
3
3
  module SpecHelpers
4
4
  `var ReactTestUtils = React.addons.TestUtils`
5
5
 
6
- def render_to_html(type, options = {})
7
- element = React.create_element(type, options)
8
- React.render_to_static_markup(element)
9
- end
10
-
11
6
  def renderToDocument(type, options = {})
12
7
  element = React.create_element(type, options)
13
- renderElementToDocument(element)
14
- end
15
-
16
- def renderElementToDocument(element)
17
- instance = Native(`ReactTestUtils.renderIntoDocument(#{element.to_n})`)
18
- instance.class.include(React::Component::API)
19
- instance
20
- end
21
-
22
- def simulateEvent(event, element, params = {})
23
- simulator = Native(`ReactTestUtils.Simulate`)
24
- simulator[event.to_s].call(element.dom_node, params)
25
- end
26
-
27
- def isElementOfType(element, type)
28
- `React.addons.TestUtils.isElementOfType(#{element.to_n}, #{type.cached_component_class})`
8
+ React::Test::Utils.render_into_document(element)
29
9
  end
30
10
 
31
11
  def build_element(type, options)