Skip to content

fix(ViewHelper) create a new helper in case controller wasn't used #375

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 21, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/react/rails/view_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ module ViewHelper
# The default is {React::Rails::ComponentMount}
mattr_accessor :helper_implementation_class

# Render a React component into the view
# using the {helper_implementation_class}
#
# If called during a Rails controller-managed request, use the instance
# created by the controller.
#
# Otherwise, make a new instance.
def react_component(*args, &block)
helper_obj = @__react_component_helper
helper_obj = @__react_component_helper ||= helper_implementation_class.new
helper_obj.react_component(*args, &block)
end
end
Expand Down
123 changes: 123 additions & 0 deletions test/react/rails/react_rails_ujs_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
require 'test_helper'

require 'capybara/rails'
require 'capybara/poltergeist'

Capybara.javascript_driver = :poltergeist
Capybara.app = Rails.application

# Useful for debugging.
# Just put page.driver.debug in your test and it will
# pause and throw up a browser
Capybara.register_driver :poltergeist_debug do |app|
Capybara::Poltergeist::Driver.new(app, :inspector => true)
end
Capybara.javascript_driver = :poltergeist_debug

class ReactRailsUJSTest < ActionDispatch::IntegrationTest
include Capybara::DSL

setup do
Capybara.current_driver = Capybara.javascript_driver
end

test 'ujs object present on the global React object and has our methods' do
visit '/pages/1'
assert page.has_content?('Hello Bob')

# the exposed ujs object is present
ujs_present = page.evaluate_script('typeof ReactRailsUJS === "object";')
assert_equal(ujs_present, true)

# it contains the constants
class_name_present = page.evaluate_script('ReactRailsUJS.CLASS_NAME_ATTR === "data-react-class";')
assert_equal(class_name_present, true)
props_present = page.evaluate_script('ReactRailsUJS.PROPS_ATTR === "data-react-props";')
assert_equal(props_present, true)

#it contains the methods
find_dom_nodes_present = page.evaluate_script('typeof ReactRailsUJS.findDOMNodes === "function";')
assert_equal(find_dom_nodes_present, true)
mount_components_present = page.evaluate_script('typeof ReactRailsUJS.mountComponents === "function";')
assert_equal(mount_components_present, true)
unmount_components_present = page.evaluate_script('typeof ReactRailsUJS.unmountComponents === "function";')
assert_equal(unmount_components_present, true)
end

test 'react_ujs works with rendered HTML' do
visit '/pages/1'
assert page.has_content?('Hello Bob')

page.click_button 'Goodbye'
assert page.has_no_content?('Hello Bob')
assert page.has_content?('Goodbye Bob')
end

test 'react_ujs works with Turbolinks' do
visit '/pages/1'
assert page.has_content?('Hello Bob')

# Try clicking links.
page.click_link('Alice')
assert page.has_content?('Hello Alice')

page.click_link('Bob')
assert page.has_content?('Hello Bob')

# Try going back.
page.execute_script('history.back();')
assert page.has_content?('Hello Alice')

wait_for_turbolinks_to_be_available()

# Try Turbolinks javascript API.
page.execute_script('Turbolinks.visit("/pages/2");')
assert page.has_content?('Hello Alice')

wait_for_turbolinks_to_be_available()

page.execute_script('Turbolinks.visit("/pages/1");')
assert page.has_content?('Hello Bob')

# Component state is not persistent after clicking current page link.
page.click_button 'Goodbye'
assert page.has_content?('Goodbye Bob')

page.click_link('Bob')
assert page.has_content?('Hello Bob')
end

test 'react_ujs can unmount/mount using a selector reference' do
visit '/pages/1'
assert page.has_content?('Hello Bob')

page.click_link "Unmount at selector #test-component"
assert page.has_no_content?('Hello Bob')

page.click_link "Mount at selector #test-component"
assert page.has_content?('Hello Bob')
end

test 'react_ujs can unmount/mount using a dom node context' do
visit '/pages/1'
assert page.has_content?('Hello Bob')

page.click_link "Unmount at node #test-component"
assert page.has_no_content?('Hello Bob')

page.click_link "Mount at node #test-component"
assert page.has_content?('Hello Bob')
end

test 'react server rendering also gets mounted on client' do
visit '/server/1'
assert_match(/data-react-class=\"TodoList\"/, page.html)
assert_match(/yep/, page.find("#status").text)
end

test 'react server rendering does not include internal properties' do
visit '/server/1'
assert_no_match(/tag=/, page.html)
assert_no_match(/prerender=/, page.html)
end
end
129 changes: 13 additions & 116 deletions test/react/rails/view_helper_test.rb
Original file line number Diff line number Diff line change
@@ -1,123 +1,20 @@
require 'test_helper'
require "test_helper"

require 'capybara/rails'
require 'capybara/poltergeist'

Capybara.javascript_driver = :poltergeist
Capybara.app = Rails.application

# Useful for debugging.
# Just put page.driver.debug in your test and it will
# pause and throw up a browser
Capybara.register_driver :poltergeist_debug do |app|
Capybara::Poltergeist::Driver.new(app, :inspector => true)
# Provide direct access to the view helper methods
class ViewHelperHelper
extend React::Rails::ViewHelper
end
Capybara.javascript_driver = :poltergeist_debug

class ViewHelperTest < ActionDispatch::IntegrationTest
include Capybara::DSL

setup do
Capybara.current_driver = Capybara.javascript_driver
end

test 'ujs object present on the global React object and has our methods' do
visit '/pages/1'
assert page.has_content?('Hello Bob')

# the exposed ujs object is present
ujs_present = page.evaluate_script('typeof ReactRailsUJS === "object";')
assert_equal(ujs_present, true)

# it contains the constants
class_name_present = page.evaluate_script('ReactRailsUJS.CLASS_NAME_ATTR === "data-react-class";')
assert_equal(class_name_present, true)
props_present = page.evaluate_script('ReactRailsUJS.PROPS_ATTR === "data-react-props";')
assert_equal(props_present, true)

#it contains the methods
find_dom_nodes_present = page.evaluate_script('typeof ReactRailsUJS.findDOMNodes === "function";')
assert_equal(find_dom_nodes_present, true)
mount_components_present = page.evaluate_script('typeof ReactRailsUJS.mountComponents === "function";')
assert_equal(mount_components_present, true)
unmount_components_present = page.evaluate_script('typeof ReactRailsUJS.unmountComponents === "function";')
assert_equal(unmount_components_present, true)
end

test 'react_ujs works with rendered HTML' do
visit '/pages/1'
assert page.has_content?('Hello Bob')

page.click_button 'Goodbye'
assert page.has_no_content?('Hello Bob')
assert page.has_content?('Goodbye Bob')
end

test 'react_ujs works with Turbolinks' do
visit '/pages/1'
assert page.has_content?('Hello Bob')

# Try clicking links.
page.click_link('Alice')
assert page.has_content?('Hello Alice')

page.click_link('Bob')
assert page.has_content?('Hello Bob')

# Try going back.
page.execute_script('history.back();')
assert page.has_content?('Hello Alice')

wait_for_turbolinks_to_be_available()

# Try Turbolinks javascript API.
page.execute_script('Turbolinks.visit("/pages/2");')
assert page.has_content?('Hello Alice')

wait_for_turbolinks_to_be_available()

page.execute_script('Turbolinks.visit("/pages/1");')
assert page.has_content?('Hello Bob')

# Component state is not persistent after clicking current page link.
page.click_button 'Goodbye'
assert page.has_content?('Goodbye Bob')

page.click_link('Bob')
assert page.has_content?('Hello Bob')
end

test 'react_ujs can unmount/mount using a selector reference' do
visit '/pages/1'
assert page.has_content?('Hello Bob')

page.click_link "Unmount at selector #test-component"
assert page.has_no_content?('Hello Bob')

page.click_link "Mount at selector #test-component"
assert page.has_content?('Hello Bob')
end

test 'react_ujs can unmount/mount using a dom node context' do
visit '/pages/1'
assert page.has_content?('Hello Bob')

page.click_link "Unmount at node #test-component"
assert page.has_no_content?('Hello Bob')

page.click_link "Mount at node #test-component"
assert page.has_content?('Hello Bob')
end

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

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