From 54ee3669e6d26663f46bcac584683c039b9031b4 Mon Sep 17 00:00:00 2001 From: Robert Mosolgo Date: Sat, 17 Oct 2015 00:08:17 -0400 Subject: [PATCH] fix(ViewHelper) create a new helper in case controller wasn't used --- lib/react/rails/view_helper.rb | 9 +- test/react/rails/react_rails_ujs_test.rb | 123 +++++++++++++++++++++ test/react/rails/view_helper_test.rb | 129 +++-------------------- 3 files changed, 144 insertions(+), 117 deletions(-) create mode 100644 test/react/rails/react_rails_ujs_test.rb diff --git a/lib/react/rails/view_helper.rb b/lib/react/rails/view_helper.rb index d3fc7dc4..fecb21fb 100644 --- a/lib/react/rails/view_helper.rb +++ b/lib/react/rails/view_helper.rb @@ -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 diff --git a/test/react/rails/react_rails_ujs_test.rb b/test/react/rails/react_rails_ujs_test.rb new file mode 100644 index 00000000..267adfcd --- /dev/null +++ b/test/react/rails/react_rails_ujs_test.rb @@ -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 diff --git a/test/react/rails/view_helper_test.rb b/test/react/rails/view_helper_test.rb index 41e2e0fe..6de0bd6a 100644 --- a/test/react/rails/view_helper_test.rb +++ b/test/react/rails/view_helper_test.rb @@ -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 = %{
} + 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