module HyperSpec module Internal module ComponentMount private TEST_CODE_KEY = 'hyper_spec_prerender_test_code.js'.freeze # rubocop:disable Metrics/MethodLength def add_block_with_helpers(component_name, opts, block) return unless block || @_hyperspec_private_client_code || component_name.nil? block_with_helpers = <<-RUBY module ComponentHelpers def self.js_eval(s) `eval(s)` end def self.dasherize(s) res = %x{ s.replace(/[-_\\s]+/g, '-') .replace(/([A-Z\\d]+)([A-Z][a-z])/g, '$1-$2') .replace(/([a-z\\d])([A-Z])/g, '$1-$2') .toLowerCase() } res end def self.add_class(class_name, styles={}) style = styles.collect { |attr, value| "\#{dasherize(attr)}:\#{value}" }.join("; ") cs = class_name.to_s %x{ var style_el = document.createElement("style"); var css = "." + cs + " { " + style + " }"; style_el.type = "text/css"; if (style_el.styleSheet){ style_el.styleSheet.cssText = css; } else { style_el.appendChild(document.createTextNode(css)); } document.head.appendChild(style_el); } end end #{test_dummy} #{@_hyperspec_private_client_code} #{"#{add_locals('', block)}\n#{Unparser.unparse(Parser::CurrentRuby.parse(block.source).children.last)}" if block} RUBY @_hyperspec_private_client_code = nil opts[:code] = opal_compile(block_with_helpers) end # rubocop:enable Metrics/MethodLength def build_test_url_for(controller = nil, ping = nil) id = ping ? 'ping' : Controller.test_id "/#{route_root_for(controller)}/#{id}" end def insure_page_loaded(only_if_code_or_html_exists = nil) return if only_if_code_or_html_exists && !@_hyperspec_private_client_code && !@_hyperspec_private_html_block # if we are not resetting between examples, or think its mounted # then look for Opal, but if we can't find it, then ping to clear and try again if !HyperSpec.reset_between_examples? || page.instance_variable_get('@hyper_spec_mounted') r = evaluate_script('Opal && true') rescue nil return if r page.visit build_test_url_for(nil, true) rescue nil end load_page end def internal_mount(component_name, params, opts, &block) # TODO: refactor this test_url = build_test_url_for(opts.delete(:controller)) add_block_with_helpers(component_name, opts, block) send_params_to_controller_via_cache(test_url, component_name, params, opts) setup_prerendering(opts) page.instance_variable_set('@hyper_spec_mounted', false) visit test_url wait_for_ajax unless opts[:no_wait] page.instance_variable_set('@hyper_spec_mounted', true) Lolex.init(self, client_options[:time_zone], client_options[:clock_resolution]) end def prerendering?(opts) %i[both server_only].include?(opts[:render_on]) end def send_params_to_controller_via_cache(test_url, component_name, params, opts) component_name ||= 'Hyperstack::Internal::Component::TestDummy' if test_dummy Controller.cache_write( test_url, [component_name, params, @_hyperspec_private_html_block, opts] ) @_hyperspec_private_html_block = nil end # test_code_key = "hyper_spec_prerender_test_code.js" # if defined? ::Hyperstack::Component # @@original_server_render_files ||= ::Rails.configuration.react.server_renderer_options[:files] # if opts[:render_on] == :both || opts[:render_on] == :server_only # unless opts[:code].blank? # ComponentTestHelpers.cache_write(test_code_key, opts[:code]) # ::Rails.configuration.react.server_renderer_options[:files] = @@original_server_render_files + [test_code_key] # ::React::ServerRendering.reset_pool # make sure contexts are reloaded so they dont use code from cache, as the rails filewatcher doesnt look for cache changes # else # ComponentTestHelpers.cache_delete(test_code_key) # ::Rails.configuration.react.server_renderer_options[:files] = @@original_server_render_files # ::React::ServerRendering.reset_pool # make sure contexts are reloaded so they dont use code from cache, as the rails filewatcher doesnt look for cache changes # end # end # end def setup_prerendering(opts) return unless defined?(::Hyperstack::Component) && prerendering?(opts) @@original_server_render_files ||= ::Rails.configuration.react.server_renderer_options[:files] ::Rails.configuration.react.server_renderer_options[:files] = @@original_server_render_files if opts[:code].blank? Controller.cache_delete(TEST_CODE_KEY) else Controller.cache_write(TEST_CODE_KEY, opts[:code]) ::Rails.configuration.react.server_renderer_options[:files] += [TEST_CODE_KEY] end ::React::ServerRendering.reset_pool # make sure contexts are reloaded so they dont use code from cache, as the rails filewatcher # doesnt look for cache changes end def test_dummy return unless defined? ::Hyperstack::Component <<-RUBY class Hyperstack::Internal::Component::TestDummy include Hyperstack::Component render {} end RUBY end end end end