Skip to content

Commit 092fc13

Browse files
author
Robert Mosolgo
committed
Merge pull request #375 from rmosolgo/fallback-view-helper
fix(ViewHelper) create a new helper in case controller wasn't used
2 parents 22ffe30 + 54ee366 commit 092fc13

File tree

3 files changed

+144
-117
lines changed

3 files changed

+144
-117
lines changed

lib/react/rails/view_helper.rb

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,15 @@ module ViewHelper
99
# The default is {React::Rails::ComponentMount}
1010
mattr_accessor :helper_implementation_class
1111

12+
# Render a React component into the view
13+
# using the {helper_implementation_class}
14+
#
15+
# If called during a Rails controller-managed request, use the instance
16+
# created by the controller.
17+
#
18+
# Otherwise, make a new instance.
1219
def react_component(*args, &block)
13-
helper_obj = @__react_component_helper
20+
helper_obj = @__react_component_helper ||= helper_implementation_class.new
1421
helper_obj.react_component(*args, &block)
1522
end
1623
end
+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
require 'test_helper'
2+
3+
require 'capybara/rails'
4+
require 'capybara/poltergeist'
5+
6+
Capybara.javascript_driver = :poltergeist
7+
Capybara.app = Rails.application
8+
9+
# Useful for debugging.
10+
# Just put page.driver.debug in your test and it will
11+
# pause and throw up a browser
12+
Capybara.register_driver :poltergeist_debug do |app|
13+
Capybara::Poltergeist::Driver.new(app, :inspector => true)
14+
end
15+
Capybara.javascript_driver = :poltergeist_debug
16+
17+
class ReactRailsUJSTest < ActionDispatch::IntegrationTest
18+
include Capybara::DSL
19+
20+
setup do
21+
Capybara.current_driver = Capybara.javascript_driver
22+
end
23+
24+
test 'ujs object present on the global React object and has our methods' do
25+
visit '/pages/1'
26+
assert page.has_content?('Hello Bob')
27+
28+
# the exposed ujs object is present
29+
ujs_present = page.evaluate_script('typeof ReactRailsUJS === "object";')
30+
assert_equal(ujs_present, true)
31+
32+
# it contains the constants
33+
class_name_present = page.evaluate_script('ReactRailsUJS.CLASS_NAME_ATTR === "data-react-class";')
34+
assert_equal(class_name_present, true)
35+
props_present = page.evaluate_script('ReactRailsUJS.PROPS_ATTR === "data-react-props";')
36+
assert_equal(props_present, true)
37+
38+
#it contains the methods
39+
find_dom_nodes_present = page.evaluate_script('typeof ReactRailsUJS.findDOMNodes === "function";')
40+
assert_equal(find_dom_nodes_present, true)
41+
mount_components_present = page.evaluate_script('typeof ReactRailsUJS.mountComponents === "function";')
42+
assert_equal(mount_components_present, true)
43+
unmount_components_present = page.evaluate_script('typeof ReactRailsUJS.unmountComponents === "function";')
44+
assert_equal(unmount_components_present, true)
45+
end
46+
47+
test 'react_ujs works with rendered HTML' do
48+
visit '/pages/1'
49+
assert page.has_content?('Hello Bob')
50+
51+
page.click_button 'Goodbye'
52+
assert page.has_no_content?('Hello Bob')
53+
assert page.has_content?('Goodbye Bob')
54+
end
55+
56+
test 'react_ujs works with Turbolinks' do
57+
visit '/pages/1'
58+
assert page.has_content?('Hello Bob')
59+
60+
# Try clicking links.
61+
page.click_link('Alice')
62+
assert page.has_content?('Hello Alice')
63+
64+
page.click_link('Bob')
65+
assert page.has_content?('Hello Bob')
66+
67+
# Try going back.
68+
page.execute_script('history.back();')
69+
assert page.has_content?('Hello Alice')
70+
71+
wait_for_turbolinks_to_be_available()
72+
73+
# Try Turbolinks javascript API.
74+
page.execute_script('Turbolinks.visit("/pages/2");')
75+
assert page.has_content?('Hello Alice')
76+
77+
wait_for_turbolinks_to_be_available()
78+
79+
page.execute_script('Turbolinks.visit("/pages/1");')
80+
assert page.has_content?('Hello Bob')
81+
82+
# Component state is not persistent after clicking current page link.
83+
page.click_button 'Goodbye'
84+
assert page.has_content?('Goodbye Bob')
85+
86+
page.click_link('Bob')
87+
assert page.has_content?('Hello Bob')
88+
end
89+
90+
test 'react_ujs can unmount/mount using a selector reference' do
91+
visit '/pages/1'
92+
assert page.has_content?('Hello Bob')
93+
94+
page.click_link "Unmount at selector #test-component"
95+
assert page.has_no_content?('Hello Bob')
96+
97+
page.click_link "Mount at selector #test-component"
98+
assert page.has_content?('Hello Bob')
99+
end
100+
101+
test 'react_ujs can unmount/mount using a dom node context' do
102+
visit '/pages/1'
103+
assert page.has_content?('Hello Bob')
104+
105+
page.click_link "Unmount at node #test-component"
106+
assert page.has_no_content?('Hello Bob')
107+
108+
page.click_link "Mount at node #test-component"
109+
assert page.has_content?('Hello Bob')
110+
end
111+
112+
test 'react server rendering also gets mounted on client' do
113+
visit '/server/1'
114+
assert_match(/data-react-class=\"TodoList\"/, page.html)
115+
assert_match(/yep/, page.find("#status").text)
116+
end
117+
118+
test 'react server rendering does not include internal properties' do
119+
visit '/server/1'
120+
assert_no_match(/tag=/, page.html)
121+
assert_no_match(/prerender=/, page.html)
122+
end
123+
end

test/react/rails/view_helper_test.rb

+13-116
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,20 @@
1-
require 'test_helper'
1+
require "test_helper"
22

3-
require 'capybara/rails'
4-
require 'capybara/poltergeist'
5-
6-
Capybara.javascript_driver = :poltergeist
7-
Capybara.app = Rails.application
8-
9-
# Useful for debugging.
10-
# Just put page.driver.debug in your test and it will
11-
# pause and throw up a browser
12-
Capybara.register_driver :poltergeist_debug do |app|
13-
Capybara::Poltergeist::Driver.new(app, :inspector => true)
3+
# Provide direct access to the view helper methods
4+
class ViewHelperHelper
5+
extend React::Rails::ViewHelper
146
end
15-
Capybara.javascript_driver = :poltergeist_debug
16-
17-
class ViewHelperTest < ActionDispatch::IntegrationTest
18-
include Capybara::DSL
19-
20-
setup do
21-
Capybara.current_driver = Capybara.javascript_driver
22-
end
23-
24-
test 'ujs object present on the global React object and has our methods' do
25-
visit '/pages/1'
26-
assert page.has_content?('Hello Bob')
27-
28-
# the exposed ujs object is present
29-
ujs_present = page.evaluate_script('typeof ReactRailsUJS === "object";')
30-
assert_equal(ujs_present, true)
31-
32-
# it contains the constants
33-
class_name_present = page.evaluate_script('ReactRailsUJS.CLASS_NAME_ATTR === "data-react-class";')
34-
assert_equal(class_name_present, true)
35-
props_present = page.evaluate_script('ReactRailsUJS.PROPS_ATTR === "data-react-props";')
36-
assert_equal(props_present, true)
37-
38-
#it contains the methods
39-
find_dom_nodes_present = page.evaluate_script('typeof ReactRailsUJS.findDOMNodes === "function";')
40-
assert_equal(find_dom_nodes_present, true)
41-
mount_components_present = page.evaluate_script('typeof ReactRailsUJS.mountComponents === "function";')
42-
assert_equal(mount_components_present, true)
43-
unmount_components_present = page.evaluate_script('typeof ReactRailsUJS.unmountComponents === "function";')
44-
assert_equal(unmount_components_present, true)
45-
end
46-
47-
test 'react_ujs works with rendered HTML' do
48-
visit '/pages/1'
49-
assert page.has_content?('Hello Bob')
50-
51-
page.click_button 'Goodbye'
52-
assert page.has_no_content?('Hello Bob')
53-
assert page.has_content?('Goodbye Bob')
54-
end
55-
56-
test 'react_ujs works with Turbolinks' do
57-
visit '/pages/1'
58-
assert page.has_content?('Hello Bob')
59-
60-
# Try clicking links.
61-
page.click_link('Alice')
62-
assert page.has_content?('Hello Alice')
63-
64-
page.click_link('Bob')
65-
assert page.has_content?('Hello Bob')
66-
67-
# Try going back.
68-
page.execute_script('history.back();')
69-
assert page.has_content?('Hello Alice')
70-
71-
wait_for_turbolinks_to_be_available()
72-
73-
# Try Turbolinks javascript API.
74-
page.execute_script('Turbolinks.visit("/pages/2");')
75-
assert page.has_content?('Hello Alice')
76-
77-
wait_for_turbolinks_to_be_available()
78-
79-
page.execute_script('Turbolinks.visit("/pages/1");')
80-
assert page.has_content?('Hello Bob')
81-
82-
# Component state is not persistent after clicking current page link.
83-
page.click_button 'Goodbye'
84-
assert page.has_content?('Goodbye Bob')
85-
86-
page.click_link('Bob')
87-
assert page.has_content?('Hello Bob')
88-
end
89-
90-
test 'react_ujs can unmount/mount using a selector reference' do
91-
visit '/pages/1'
92-
assert page.has_content?('Hello Bob')
93-
94-
page.click_link "Unmount at selector #test-component"
95-
assert page.has_no_content?('Hello Bob')
96-
97-
page.click_link "Mount at selector #test-component"
98-
assert page.has_content?('Hello Bob')
99-
end
100-
101-
test 'react_ujs can unmount/mount using a dom node context' do
102-
visit '/pages/1'
103-
assert page.has_content?('Hello Bob')
104-
105-
page.click_link "Unmount at node #test-component"
106-
assert page.has_no_content?('Hello Bob')
107-
108-
page.click_link "Mount at node #test-component"
109-
assert page.has_content?('Hello Bob')
110-
end
1117

112-
test 'react server rendering also gets mounted on client' do
113-
visit '/server/1'
114-
assert_match(/data-react-class=\"TodoList\"/, page.html)
115-
assert_match(/yep/, page.find("#status").text)
8+
class ViewHelperTest < ActionView::TestCase
9+
test "view helper can be called directly" do
10+
expected_html = %{<div data-react-class="Component" data-react-props="{&quot;a&quot;:&quot;b&quot;}"></div>}
11+
rendered_html = ViewHelperHelper.react_component("Component", {a: "b"})
12+
assert_equal(expected_html, rendered_html)
11613
end
11714

118-
test 'react server rendering does not include internal properties' do
119-
visit '/server/1'
120-
assert_no_match(/tag=/, page.html)
121-
assert_no_match(/prerender=/, page.html)
15+
test "view helper can be used in stand-alone views" do
16+
@name = "React-Rails"
17+
render template: "pages/show"
18+
assert_includes(rendered, "React-Rails")
12219
end
12320
end

0 commit comments

Comments
 (0)