diff --git a/CHANGELOG.md b/CHANGELOG.md index ca81a1d5a..57643115f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,14 @@ Changes since last non-beta release. *Please add entries here for your pull requests that are not yet released.* +### [11.0.1] - 2018-04-23 + +#### Added +- `react_component` allows logging_on_server specified at the component level. [PR 1068](https://github.com/shakacode/react_on_rails/pull/1068) by [justin808](https://github.com/justin808). + +#### Fixed +- Missing class when throwing some error messages. [PR 1068](https://github.com/shakacode/react_on_rails/pull/1068) by [justin808](https://github.com/justin808). + ### [11.0.0] - 2018-04-21 ## MIGRATION for v11 @@ -24,7 +32,7 @@ Changes since last non-beta release. - Removed ReactOnRails::Utils.server_bundle_file_name and ReactOnRails::Utils.bundle_file_name. - No longer logging the `railsContext` when server logging. - Rails.env is provided in the default railsContext, as suggested in [issue #697](https://github.com/shakacode/react_on_rails/issues/697). -[PR 1018](https://github.com/shakacode/react_on_rails/pull/1065) by [justin808](https://github.com/justin808). +[PR 1065](https://github.com/shakacode/react_on_rails/pull/1065) by [justin808](https://github.com/justin808). #### Fixes - More exact version checking. We keep the react_on_rails gem and the react-on-rails node package at diff --git a/README.md b/README.md index 5d20736b2..c32e8dd83 100644 --- a/README.md +++ b/README.md @@ -523,13 +523,17 @@ react_component(component_name, ``` + **component_name:** Can be a React component, created using an ES6 class or a generator function that returns a React component (or, only on the server side, an object with shape { redirectLocation, error, renderedHtml }), or a "renderer function" that manually renders a React component to the dom (client side only). -+ **options:** +All options except `props, id, html_options` will inherit from your `react_on_rails.rb` initializer, as described [here](./docs/basics/configuration.md). + ++ **general options:** + **props:** Ruby Hash which contains the properties to pass to the react object, or a JSON string. If you pass a string, we'll escape it for you. + **prerender:** enable server-side rendering of a component. Set to false when debugging! + **id:** Id for the div, will be used to attach the React component. This will get assigned automatically if you do not provide an id. Must be unique. + **html_options:** Any other HTML options get placed on the added div for the component. For example, you can set a class (or inline style) on the outer div so that it behaves like a span, with the styling of `display:inline-block`. + **trace:** set to true to print additional debugging information in the browser. Defaults to true for development, off otherwise. Only on the **client side** will you will see the `railsContext` and your props. - + **replay_console:** Default is true. False will disable echoing server-rendering logs to the browser. While this can make troubleshooting server rendering difficult, so long as you have the default configuration of `logging_on_server` set to true, you'll still see the errors on the server. ++ **options if prerender (server rendering) is true:** + + **replay_console:** Default is true. False will disable echoing server-rendering logs to the browser. While this can make troubleshooting server rendering difficult, so long as you have the configuration of `logging_on_server` set to true, you'll still see the errors on the server. + + **logging_on_server:** Default is true. True will log JS console messages and errors to the server. + **raise_on_prerender_error:** Default is false. True will throw an error on the server side rendering. Your controller will have to handle the error. ### redux_store diff --git a/lib/react_on_rails.rb b/lib/react_on_rails.rb index 1ed12b8e0..4ad8b8951 100644 --- a/lib/react_on_rails.rb +++ b/lib/react_on_rails.rb @@ -10,7 +10,7 @@ require "react_on_rails/configuration" require "react_on_rails/server_rendering_pool" require "react_on_rails/engine" -require "react_on_rails/react_component/options" +require "react_on_rails/react_component/render_options" require "react_on_rails/version_syntax_converter" require "react_on_rails/test_helper" require "react_on_rails/git_utils" diff --git a/lib/react_on_rails/configuration.rb b/lib/react_on_rails/configuration.rb index d47dcffc0..3d86703a2 100644 --- a/lib/react_on_rails/configuration.rb +++ b/lib/react_on_rails/configuration.rb @@ -9,6 +9,8 @@ def self.configure end DEFAULT_GENERATED_ASSETS_DIR = File.join(%w[public webpack], Rails.env).freeze + DEFAULT_SERVER_RENDER_TIMEOUT = 20 + DEFAULT_POOL_SIZE = 1 def self.setup_config_values ensure_webpack_generated_files_exists @@ -112,8 +114,8 @@ def self.configuration raise_on_prerender_error: false, trace: Rails.env.development?, development_mode: Rails.env.development?, - server_renderer_pool_size: 1, - server_renderer_timeout: 20, + server_renderer_pool_size: DEFAULT_POOL_SIZE, + server_renderer_timeout: DEFAULT_SERVER_RENDER_TIMEOUT, skip_display_none: nil, # skip_display_none is deprecated webpack_generated_files: %w[manifest.json], diff --git a/lib/react_on_rails/react_component/options.rb b/lib/react_on_rails/react_component/render_options.rb similarity index 66% rename from lib/react_on_rails/react_component/options.rb rename to lib/react_on_rails/react_component/render_options.rb index 496d1d5a5..528999737 100644 --- a/lib/react_on_rails/react_component/options.rb +++ b/lib/react_on_rails/react_component/render_options.rb @@ -4,24 +4,22 @@ module ReactOnRails module ReactComponent - class Options + class RenderOptions include Utils::Required NO_PROPS = {}.freeze - def initialize(name: required("name"), options: required("options")) - @name = name + def initialize(react_component_name: required("react_component_name"), options: required("options")) + @react_component_name = react_component_name.camelize @options = options end + attr_reader :react_component_name + def props options.fetch(:props) { NO_PROPS } end - def name - @name.camelize - end - def dom_id @dom_id ||= options.fetch(:id) { generate_unique_dom_id } end @@ -46,12 +44,20 @@ def raise_on_prerender_error retrieve_key(:raise_on_prerender_error) end + def logging_on_server + retrieve_key(:logging_on_server) + end + + def to_s + "{ react_component_name = #{react_component_name}, options = #{options}" + end + private attr_reader :options def generate_unique_dom_id - "#{@name}-react-component-#{SecureRandom.uuid}" + "#{react_component_name}-react-component-#{SecureRandom.uuid}" end def retrieve_key(key) diff --git a/lib/react_on_rails/react_on_rails_helper.rb b/lib/react_on_rails/react_on_rails_helper.rb index 63eb6d35b..7f01b6301 100644 --- a/lib/react_on_rails/react_on_rails_helper.rb +++ b/lib/react_on_rails/react_on_rails_helper.rb @@ -98,17 +98,17 @@ def env_stylesheet_link_tag(args = {}) # raise_on_prerender_error: Default to false. True will raise exception on server # if the JS code throws # Any other options are passed to the content tag, including the id. - def react_component(component_name, raw_options = {}) - internal_result = internal_react_component(component_name, raw_options) - server_rendered_html = internal_result["result"]["html"] - console_script = internal_result["result"]["consoleReplayScript"] + def react_component(component_name, options = {}) + internal_result = internal_react_component(component_name, options) + server_rendered_html = internal_result[:result]["html"] + console_script = internal_result[:result]["consoleReplayScript"] if server_rendered_html.is_a?(String) build_react_component_result_for_server_rendered_string( server_rendered_html: server_rendered_html, - component_specification_tag: internal_result["tag"], + component_specification_tag: internal_result[:tag], console_script: console_script, - options: internal_result["options"] + render_options: internal_result[:render_options] ) elsif server_rendered_html.is_a?(Hash) msg = <<-MSG.strip_heredoc @@ -116,7 +116,7 @@ def react_component(component_name, raw_options = {}) https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/client/app/startup/ReactHelmetServerApp.jsx for an example of the necessary javascript configuration." MSG - raise ReactOnRailsPro::Error, msg + raise ReactOnRails::Error, msg else msg = <<-MSG.strip_heredoc @@ -126,17 +126,17 @@ def react_component(component_name, raw_options = {}) https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/client/app/startup/ReactHelmetServerApp.jsx for an example of the necessary javascript configuration." MSG - raise ReactOnRailsPro::Error, msg + raise ReactOnRails::Error, msg end end - def react_component_hash(component_name, raw_options = {}) - internal_result = internal_react_component(component_name, raw_options) - server_rendered_html = internal_result["result"]["html"] - console_script = internal_result["result"]["consoleReplayScript"] + def react_component_hash(component_name, options = {}) + internal_result = internal_react_component(component_name, options) + server_rendered_html = internal_result[:result]["html"] + console_script = internal_result[:result]["consoleReplayScript"] - if server_rendered_html.is_a?(String) && internal_result["result"]["hasErrors"] - server_rendered_html = { COMPONENT_HTML_KEY => internal_result["result"]["html"] } + if server_rendered_html.is_a?(String) && internal_result[:result]["hasErrors"] + server_rendered_html = { COMPONENT_HTML_KEY => internal_result[:result]["html"] } end if server_rendered_html.is_a?(Hash) @@ -144,7 +144,7 @@ def react_component_hash(component_name, raw_options = {}) server_rendered_html: server_rendered_html, component_specification_tag: internal_result["tag"], console_script: console_script, - options: internal_result["options"] + render_options: internal_result[:render_options] ) else msg = <<-MSG.strip_heredoc @@ -152,7 +152,7 @@ def react_component_hash(component_name, raw_options = {}) https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/client/app/startup/ReactHelmetServerApp.jsx for an example of the necessary javascript configuration. MSG - raise ReactOnRailsPro::Error, msg + raise ReactOnRails::Error, msg end end @@ -199,8 +199,12 @@ def sanitized_props_string(props) # Helper method to take javascript expression and returns the output from evaluating it. # If you have more than one line that needs to be executed, wrap it in an IIFE. # JS exceptions are caught and console messages are handled properly. + # Options include:{ prerender:, trace:, raise_on_prerender_error: } def server_render_js(js_expression, options = {}) - wrapper_js = <<-JS.strip_heredoc + render_options = ReactOnRails::ReactComponent::RenderOptions + .new(react_component_name: "generic-js", options: options) + + js_code = <<-JS.strip_heredoc (function() { var htmlResult = ''; var consoleReplayScript = ''; @@ -228,15 +232,16 @@ def server_render_js(js_expression, options = {}) })() JS - result = ReactOnRails::ServerRenderingPool.server_render_js_with_console_logging(wrapper_js) + result = ReactOnRails::ServerRenderingPool + .server_render_js_with_console_logging(js_code, render_options) html = result["html"] console_log_script = result["consoleLogScript"] - raw("#{html}#{replay_console_option(options[:replay_console_option]) ? console_log_script : ''}") + raw("#{html}#{render_options.replay_console ? console_log_script : ''}") rescue ExecJS::ProgramError => err raise ReactOnRails::PrerenderError, component_name: "N/A (server_render_js called)", err: err, - js_code: wrapper_js + js_code: js_code end def json_safe_and_pretty(hash_or_string) @@ -257,16 +262,16 @@ def build_react_component_result_for_server_rendered_string( server_rendered_html: required("server_rendered_html"), component_specification_tag: required("component_specification_tag"), console_script: required("console_script"), - options: required("options") + render_options: required("render_options") ) - content_tag_options = options.html_options - content_tag_options[:id] = options.dom_id + content_tag_options = render_options.html_options + content_tag_options[:id] = render_options.dom_id rendered_output = content_tag(:div, server_rendered_html.html_safe, content_tag_options) - result_console_script = options.replay_console ? console_script : "" + result_console_script = render_options.replay_console ? console_script : "" result = compose_react_component_html_with_spec_and_console( component_specification_tag, rendered_output, result_console_script ) @@ -278,20 +283,20 @@ def build_react_component_result_for_server_rendered_hash( server_rendered_html: required("server_rendered_html"), component_specification_tag: required("component_specification_tag"), console_script: required("console_script"), - options: required("options") + render_options: required("render_options") ) - content_tag_options = options.html_options - content_tag_options[:id] = options.dom_id + content_tag_options = render_options.html_options + content_tag_options[:id] = render_options.dom_id unless server_rendered_html[COMPONENT_HTML_KEY] - raise ReactOnRailsPro::Error, "server_rendered_html hash expected to contain \"#{COMPONENT_HTML_KEY}\" key." + raise ReactOnRails::Error, "server_rendered_html hash expected to contain \"#{COMPONENT_HTML_KEY}\" key." end rendered_output = content_tag(:div, server_rendered_html[COMPONENT_HTML_KEY].html_safe, content_tag_options) - result_console_script = options.replay_console ? console_script : "" + result_console_script = render_options.replay_console ? console_script : "" result = compose_react_component_html_with_spec_and_console( component_specification_tag, rendered_output, result_console_script ) @@ -335,7 +340,7 @@ def prepend_render_rails_context(render_value) "#{rails_context_content}\n#{render_value}".html_safe end - def internal_react_component(component_name, raw_options = {}) + def internal_react_component(react_component_name, options = {}) # Create the JavaScript and HTML to allow either client or server rendering of the # react_component. # @@ -343,27 +348,27 @@ def internal_react_component(component_name, raw_options = {}) # (re-hydrate the data). This enables react rendered on the client to see that the # server has already rendered the HTML. - options = ReactOnRails::ReactComponent::Options.new(name: component_name, options: raw_options) + render_options = ReactOnRails::ReactComponent::RenderOptions.new(react_component_name: react_component_name, + options: options) # Setup the page_loaded_js, which is the same regardless of prerendering or not! # The reason is that React is smart about not doing extra work if the server rendering did its job. component_specification_tag = content_tag(:script, - json_safe_and_pretty(options.props).html_safe, + json_safe_and_pretty(render_options.props).html_safe, type: "application/json", class: "js-react-on-rails-component", - "data-component-name" => options.name, - "data-trace" => (options.trace ? true : nil), - "data-dom-id" => options.dom_id) + "data-component-name" => render_options.react_component_name, + "data-trace" => (render_options.trace ? true : nil), + "data-dom-id" => render_options.dom_id) # Create the HTML rendering part - result = server_rendered_react_component_html(options.props, - options.name, - options.dom_id, - prerender: options.prerender, - trace: options.trace, - raise_on_prerender_error: options.raise_on_prerender_error) - - { "options" => options, "tag" => component_specification_tag, "result" => result } + result = server_rendered_react_component(render_options) + + { + render_options: render_options, + tag: component_specification_tag, + result: result + } end def render_redux_store_data(redux_store_data) @@ -379,15 +384,12 @@ def props_string(props) props.is_a?(String) ? props : props.to_json end - # Returns Array [0]: html, [1]: script to console log - # NOTE, these are NOT html_safe! - def server_rendered_react_component_html( - props, react_component_name, dom_id, - prerender: required("prerender"), - trace: required("trace"), - raise_on_prerender_error: required("raise_on_prerender_error") - ) - return { "html" => "", "consoleReplayScript" => "" } unless prerender + # Returns object with values that are NOT html_safe! + def server_rendered_react_component(render_options) + return { "html" => "", "consoleReplayScript" => "" } unless render_options.prerender + + react_component_name = render_options.react_component_name + props = render_options.props # On server `location` option is added (`location = request.fullpath`) # React Router needs this to match the current route @@ -411,42 +413,44 @@ def server_rendered_react_component_html( # Read more here: http://timelessrepo.com/json-isnt-a-javascript-subset # rubocop:disable Layout/IndentHeredoc - wrapper_js = <<-JS + js_code = <<-JS (function() { var railsContext = #{rails_context(server_side: true).to_json}; #{initialize_redux_stores} var props = #{props_string(props).gsub("\u2028", '\u2028').gsub("\u2029", '\u2029')}; return ReactOnRails.serverRenderReactComponent({ name: '#{react_component_name}', - domNodeId: '#{dom_id}', + domNodeId: '#{render_options.dom_id}', props: props, - trace: #{trace}, + trace: #{render_options.trace}, railsContext: railsContext }); })() JS # rubocop:enable Layout/IndentHeredoc - result = ReactOnRails::ServerRenderingPool.server_render_js_with_console_logging(wrapper_js) + begin + result = ReactOnRails::ServerRenderingPool.server_render_js_with_console_logging(js_code, render_options) + rescue StandardError => err + # This error came from the renderer + raise ReactOnRails::PrerenderError, component_name: react_component_name, + # Sanitize as this might be browser logged + props: sanitized_props_string(props), + err: err, + js_code: js_code + end - if result["hasErrors"] && raise_on_prerender_error + if result["hasErrors"] && render_options.raise_on_prerender_error # We caught this exception on our backtrace handler raise ReactOnRails::PrerenderError, component_name: react_component_name, # Sanitize as this might be browser logged props: sanitized_props_string(props), err: nil, - js_code: wrapper_js, + js_code: js_code, console_messages: result["consoleReplayScript"] end result - rescue ExecJS::ProgramError => err - # This error came from execJs - raise ReactOnRails::PrerenderError, component_name: react_component_name, - # Sanitize as this might be browser logged - props: sanitized_props_string(props), - err: err, - js_code: wrapper_js end def initialize_redux_stores diff --git a/lib/react_on_rails/server_rendering_pool.rb b/lib/react_on_rails/server_rendering_pool.rb index a27fc5056..7856f2b9a 100644 --- a/lib/react_on_rails/server_rendering_pool.rb +++ b/lib/react_on_rails/server_rendering_pool.rb @@ -21,8 +21,11 @@ def pool end end - delegate :server_render_js_with_console_logging, :reset_pool_if_server_bundle_was_modified, - :reset_pool, to: :pool + delegate :reset_pool_if_server_bundle_was_modified, :reset_pool, to: :pool + + def server_render_js_with_console_logging(js_code, render_options) + @pool.exec_server_render_js(js_code, render_options) + end private diff --git a/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb b/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb index cff556ca9..8cb5c9746 100644 --- a/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +++ b/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb @@ -5,61 +5,65 @@ module ReactOnRails module ServerRenderingPool class RubyEmbeddedJavaScript - def self.reset_pool - options = { - size: ReactOnRails.configuration.server_renderer_pool_size, - timeout: ReactOnRails.configuration.server_renderer_timeout - } - @js_context_pool = ConnectionPool.new(options) { create_js_context } - end - - def self.reset_pool_if_server_bundle_was_modified - return unless ReactOnRails.configuration.development_mode + class << self + def reset_pool + options = { + size: ReactOnRails.configuration.server_renderer_pool_size, + timeout: ReactOnRails.configuration.server_renderer_timeout + } + @js_context_pool = ConnectionPool.new(options) { create_js_context } + end - file_mtime = File.mtime(ReactOnRails::Utils.server_bundle_js_file_path) - @server_bundle_timestamp ||= file_mtime - return if @server_bundle_timestamp == file_mtime + def reset_pool_if_server_bundle_was_modified + return unless ReactOnRails.configuration.development_mode - @server_bundle_timestamp = file_mtime + file_mtime = File.mtime(ReactOnRails::Utils.server_bundle_js_file_path) + @server_bundle_timestamp ||= file_mtime + return if @server_bundle_timestamp == file_mtime - ReactOnRails::ServerRenderingPool.reset_pool - end + @server_bundle_timestamp = file_mtime - # js_code: JavaScript expression that returns a string. - # Returns a Hash: - # html: string of HTML for direct insertion on the page by evaluating js_code - # consoleReplayScript: script for replaying console - # hasErrors: true if server rendering errors - # Note, js_code does not have to be based on React. - # js_code MUST RETURN json stringify Object - # Calling code will probably call 'html_safe' on return value before rendering to the view. - def self.server_render_js_with_console_logging(js_code) - if ReactOnRails.configuration.trace - @file_index ||= 1 - trace_js_code_used("Evaluating code to server render.", js_code, - "tmp/server-generated-#{@file_index % 10}.js") - @file_index += 1 + ReactOnRails::ServerRenderingPool.reset_pool end - json_string = eval_js(js_code) - result = JSON.parse(json_string) - - if ReactOnRails.configuration.logging_on_server - console_script = result["consoleReplayScript"] - console_script_lines = console_script.split("\n") - console_script_lines = console_script_lines[2..-2] - re = /console\.(log|error)\.apply\(console, \["\[SERVER\] (?.*)"\]\);/ - if console_script_lines - console_script_lines.each do |line| - match = re.match(line) - Rails.logger.info { "[react_on_rails] #{match[:msg]}" } if match + + # js_code: JavaScript expression that returns a string. + # render_options: lib/react_on_rails/react_component/render_options.rb + # Using these options: + # trace: saves the executed JS to a file, used in development + # logging_on_server: put on server logs, not just in browser console + # + # Returns a Hash: + # html: string of HTML for direct insertion on the page by evaluating js_code + # consoleReplayScript: script for replaying console + # hasErrors: true if server rendering errors + # Note, js_code does not have to be based on React. + # js_code MUST RETURN json stringify Object + # Calling code will probably call 'html_safe' on return value before rendering to the view. + def exec_server_render_js(js_code, render_options, js_evaluator = nil) + js_evaluator ||= self + if render_options.trace + @file_index ||= 1 + trace_js_code_used("Evaluating code to server render.", js_code, + "tmp/server-generated-#{@file_index % 10}.js") + @file_index += 1 + end + json_string = js_evaluator.eval_js(js_code) + result = JSON.parse(json_string) + + if render_options.logging_on_server + console_script = result["consoleReplayScript"] + console_script_lines = console_script.split("\n") + console_script_lines = console_script_lines[2..-2] + re = /console\.(log|error)\.apply\(console, \["\[SERVER\] (?.*)"\]\);/ + if console_script_lines + console_script_lines.each do |line| + match = re.match(line) + Rails.logger.info { "[react_on_rails] #{match[:msg]}" } if match + end end end + result end - result - end - - class << self - private def trace_js_code_used(msg, js_code, file_name = "tmp/server-generated.js", force: false) return unless ReactOnRails.configuration.trace || force @@ -156,8 +160,7 @@ def execjs_timer_polyfills def undefined_for_exec_js_logging(function_name) if ReactOnRails.configuration.trace - "console.error('[React on Rails Rendering] #{function_name} is not defined for execJS. See "\ - "https://github.com/sstephenson/execjs#faq. Note babel-polyfill may call this.');\n"\ + "console.error('[React on Rails Rendering] #{function_name} is not defined for server rendering.');\n"\ " console.error(getStackTrace().join('\\n'));" else "" diff --git a/lib/react_on_rails/utils.rb b/lib/react_on_rails/utils.rb index 1280c07f1..effce2b87 100644 --- a/lib/react_on_rails/utils.rb +++ b/lib/react_on_rails/utils.rb @@ -114,7 +114,7 @@ def self.rails_version_less_than_4_1_1 module Required def required(arg_name) - raise ReactOnRailsPro::Error, "#{arg_name} is required" + raise ReactOnRails::Error, "#{arg_name} is required" end end diff --git a/spec/dummy/Gemfile.lock b/spec/dummy/Gemfile.lock index 4b3dfaca9..38734cf7a 100644 --- a/spec/dummy/Gemfile.lock +++ b/spec/dummy/Gemfile.lock @@ -7,7 +7,7 @@ GIT PATH remote: ../.. specs: - react_on_rails (11.0.0.beta.1) + react_on_rails (11.0.0) addressable connection_pool execjs (~> 2.5) diff --git a/spec/react_on_rails/react_component/options_spec.rb b/spec/react_on_rails/react_component/render_options_spec.rb similarity index 83% rename from spec/react_on_rails/react_component/options_spec.rb rename to spec/react_on_rails/react_component/render_options_spec.rb index 2a47b9207..dc512a564 100644 --- a/spec/react_on_rails/react_component/options_spec.rb +++ b/spec/react_on_rails/react_component/render_options_spec.rb @@ -2,7 +2,7 @@ require_relative "../spec_helper" -describe ReactOnRails::ReactComponent::Options do +describe ReactOnRails::ReactComponent::RenderOptions do CONFIGURABLE_OPTIONS = %i[ prerender trace @@ -10,9 +10,9 @@ raise_on_prerender_error ].freeze - def the_attrs(name: "App", options: {}) + def the_attrs(react_component_name: "App", options: {}) { - name: name, + react_component_name: react_component_name, options: options } end @@ -48,25 +48,25 @@ def the_attrs(name: "App", options: {}) end end - describe "#name" do - it "returns name with correct format" do - name = "some_app" - attrs = the_attrs(name: name) + describe "#react_component_name" do + it "returns react_component_name with correct format" do + react_component_name = "some_app" + attrs = the_attrs(react_component_name: react_component_name) opts = described_class.new(attrs) - expect(opts.name).to eq "SomeApp" + expect(opts.react_component_name).to eq "SomeApp" end end describe "#dom_id" do context "without id option" do it "returns a unique identifier" do - attrs = the_attrs(name: "some_app") + attrs = the_attrs(react_component_name: "SomeApp") opts = described_class.new(attrs) expect(SecureRandom).to receive(:uuid).and_return("123456789") - expect(opts.dom_id).to eq "some_app-react-component-123456789" + expect(opts.dom_id).to eq "SomeApp-react-component-123456789" end it "is memoized" do