Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
36 changes: 32 additions & 4 deletions lib/react_on_rails/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,17 @@ def react_component(component_name, options = {})
server_rendered_html = internal_result[:result]["html"]
console_script = internal_result[:result]["consoleReplayScript"]
render_options = internal_result[:render_options]
badge = pro_warning_badge_if_needed(render_options.force_load)

case server_rendered_html
when String
build_react_component_result_for_server_rendered_string(
html = build_react_component_result_for_server_rendered_string(
server_rendered_html: server_rendered_html,
component_specification_tag: internal_result[:tag],
console_script: console_script,
render_options: render_options
)
(badge + html).html_safe
when Hash
msg = <<~MSG
Use react_component_hash (not react_component) to return a Hash to your ruby view code. See
Expand Down Expand Up @@ -212,18 +214,21 @@ def react_component_hash(component_name, options = {})
server_rendered_html = internal_result[:result]["html"]
console_script = internal_result[:result]["consoleReplayScript"]
render_options = internal_result[:render_options]
badge = pro_warning_badge_if_needed(render_options.force_load)

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)
build_react_component_result_for_server_rendered_hash(
result = build_react_component_result_for_server_rendered_hash(
server_rendered_html: server_rendered_html,
component_specification_tag: internal_result[:tag],
console_script: console_script,
render_options: render_options
)
result[COMPONENT_HTML_KEY] = badge + result[COMPONENT_HTML_KEY]
result
else
msg = <<~MSG
Render-Function used by react_component_hash for #{component_name} is expected to return
Expand Down Expand Up @@ -251,6 +256,8 @@ def react_component_hash(component_name, options = {})
# waiting for the page to load.
def redux_store(store_name, props: {}, defer: false, force_load: nil)
force_load = ReactOnRails.configuration.force_load if force_load.nil?
badge = pro_warning_badge_if_needed(force_load)

redux_store_data = { store_name: store_name,
props: props,
force_load: force_load }
Expand All @@ -261,7 +268,7 @@ def redux_store(store_name, props: {}, defer: false, force_load: nil)
else
registered_stores << redux_store_data
result = render_redux_store_data(redux_store_data)
prepend_render_rails_context(result)
(badge + prepend_render_rails_context(result)).html_safe
end
end

Expand Down Expand Up @@ -440,7 +447,28 @@ def load_pack_for_generated_component(react_component_name, render_options)

# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity

private
def pro_warning_badge_if_needed(force_load)
return "".html_safe if !force_load && !ReactOnRails.configuration.force_load
return "".html_safe if ReactOnRails::Utils.react_on_rails_pro?

warning_message = "[REACT ON RAILS] The 'force_load' feature requires a React on Rails Pro license. " \
"Please visit https://shakacode.com/react-on-rails-pro to learn more."
puts warning_message
Rails.logger.warn warning_message

tooltip_text = "The 'force_load' feature requires a React on Rails Pro license. Click to learn more."

badge_html = <<~HTML
<a href="https://shakacode.com/react-on-rails-pro" target="_blank" rel="noopener noreferrer" title="#{tooltip_text}">
<div style="position: fixed; top: 0; right: 0; width: 180px; height: 180px; overflow: hidden; z-index: 9999; pointer-events: none;">
<div style="position: absolute; top: 50px; right: -40px; transform: rotate(45deg); background-color: rgba(220, 53, 69, 0.85); color: white; padding: 7px 40px; text-align: center; font-weight: bold; font-family: sans-serif; font-size: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.3); pointer-events: auto;">
React On Rails Pro Required
</div>
</div>
</a>
HTML
badge_html.strip.html_safe
end

def run_stream_inside_fiber
unless ReactOnRails::Utils.react_on_rails_pro?
Expand Down
183 changes: 182 additions & 1 deletion spec/dummy/spec/helpers/react_on_rails_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ class PlainReactOnRailsHelper
{ "HTTP_ACCEPT_LANGUAGE" => "en" }
)
}

allow(ReactOnRails::Utils).to receive_messages(
react_on_rails_pro?: true,
react_on_rails_pro_version: "4.0.0",
rsc_support_enabled?: false
)
end

let(:hash) do
Expand Down Expand Up @@ -370,10 +376,139 @@ def helper.append_javascript_pack_tag(name, **options)
it { is_expected.to include force_load_script }
end
end

describe "with Pro license warning" do
let(:badge_html_string) { "React On Rails Pro Required" }

before do
allow(Rails.logger).to receive(:warn)
end

context "when Pro license is NOT installed and force_load is true" do
subject(:react_app) { react_component("App", props: props, force_load: true) }

before do
allow(ReactOnRails::Utils).to receive(:react_on_rails_pro?).and_return(false)
end

it { is_expected.to include(badge_html_string) }

it "logs a warning" do
react_app
expect(Rails.logger).to have_received(:warn).with(a_string_matching(/The 'force_load' feature requires/))
end
end

context "when Pro license is NOT installed and global force_load is true" do
subject(:react_app) { react_component("App", props: props) }

before do
allow(ReactOnRails::Utils).to receive(:react_on_rails_pro?).and_return(false)
end

around do |example|
ReactOnRails.configure { |config| config.force_load = true }
example.run
ReactOnRails.configure { |config| config.force_load = false }
end

it { is_expected.to include(badge_html_string) }
end

context "when Pro license is NOT installed and force_load is false" do
subject(:react_app) { react_component("App", props: props, force_load: false) }

before do
allow(ReactOnRails::Utils).to receive(:react_on_rails_pro?).and_return(false)
end

it { is_expected.not_to include(badge_html_string) }

it "does not log a warning" do
react_app
expect(Rails.logger).not_to have_received(:warn)
end
end

context "when Pro license IS installed and force_load is true" do
subject(:react_app) { react_component("App", props: props, force_load: true) }

before do
allow(ReactOnRails::Utils).to receive_messages(
react_on_rails_pro?: true,
react_on_rails_pro_version: "4.0.0"
)
end

it { is_expected.not_to include(badge_html_string) }

it "does not log a warning" do
react_app
expect(Rails.logger).not_to have_received(:warn)
end
end
end
end

describe "#react_component_hash" do
subject(:react_app) { react_component_hash("App", props: props) }

let(:props) { { name: "My Test Name" } }

before do
allow(SecureRandom).to receive(:uuid).and_return(0)
allow(ReactOnRails::ServerRenderingPool).to receive(:server_render_js_with_console_logging).and_return(
"html" => { "componentHtml" => "<div>Test</div>", "title" => "Test Title" },
"consoleReplayScript" => ""
)
allow(ReactOnRails::ServerRenderingJsCode).to receive(:js_code_renderer)
.and_return(ReactOnRails::ServerRenderingJsCode)
end

it "returns a hash with component and other keys" do
expect(react_app).to be_a(Hash)
expect(react_app).to have_key("componentHtml")
expect(react_app).to have_key("title")
end

context "with Pro license warning" do
let(:badge_html_string) { "React On Rails Pro Required" }

before do
allow(Rails.logger).to receive(:warn)
end

context "when Pro license is NOT installed and force_load is true" do
subject(:react_app) { react_component_hash("App", props: props, force_load: true) }

before do
allow(ReactOnRails::Utils).to receive(:react_on_rails_pro?).and_return(false)
end

it "adds badge to componentHtml" do
expect(react_app["componentHtml"]).to include(badge_html_string)
end
end

context "when Pro license IS installed and force_load is true" do
subject(:react_app) { react_component_hash("App", props: props, force_load: true) }

before do
allow(ReactOnRails::Utils).to receive_messages(
react_on_rails_pro?: true,
react_on_rails_pro_version: "4.0.0"
)
end

it "does not add badge to componentHtml" do
expect(react_app["componentHtml"]).not_to include(badge_html_string)
end
end
end
end

describe "#redux_store" do
subject(:store) { redux_store("reduxStore", props: props) }
subject(:store) { redux_store("reduxStore", props: props, force_load: true) }

let(:props) do
{ name: "My Test Name" }
Expand All @@ -394,6 +529,52 @@ def helper.append_javascript_pack_tag(name, **options)
it {
expect(expect(store).target).to script_tag_be_included(react_store_script)
}

context "with Pro license warning" do
let(:badge_html_string) { "React On Rails Pro Required" }

before do
allow(Rails.logger).to receive(:warn)
end

context "when Pro license is NOT installed and force_load is true" do
subject(:store) { redux_store("reduxStore", props: props, force_load: true) }

before do
allow(ReactOnRails::Utils).to receive(:react_on_rails_pro?).and_return(false)
end

it { is_expected.to include(badge_html_string) }

it "logs a warning" do
store
expect(Rails.logger).to have_received(:warn).with(a_string_matching(/The 'force_load' feature requires/))
end
end

context "when Pro license is NOT installed and force_load is false" do
subject(:store) { redux_store("reduxStore", props: props, force_load: false) }

before do
allow(ReactOnRails::Utils).to receive(:react_on_rails_pro?).and_return(false)
end

it { is_expected.not_to include(badge_html_string) }
end

context "when Pro license IS installed and force_load is true" do
subject(:store) { redux_store("reduxStore", props: props, force_load: true) }

before do
allow(ReactOnRails::Utils).to receive_messages(
react_on_rails_pro?: true,
react_on_rails_pro_version: "4.0.0"
)
end

it { is_expected.not_to include(badge_html_string) }
end
end
end

describe "#server_render_js", :js, type: :system do
Expand Down
Loading