Skip to content
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

Alternative fix for 652 #692

Closed
wants to merge 3 commits into from
Closed
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
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ GEM
net-smtp (0.3.3)
net-protocol
nio4r (2.5.8)
nokogiri (1.16.2-arm64-darwin)
racc (~> 1.4)
nokogiri (1.16.2-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.16.2-x86_64-linux)
Expand Down Expand Up @@ -202,6 +204,7 @@ GEM
zeitwerk (2.6.8)

PLATFORMS
arm64-darwin-22
x86_64-darwin-19
x86_64-darwin-22
x86_64-darwin-23
Expand Down
1 change: 0 additions & 1 deletion lib/stimulus_reflex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
require "stimulus_reflex/configuration"
require "stimulus_reflex/callbacks"
require "stimulus_reflex/html/document"
require "stimulus_reflex/html/document_fragment"
require "stimulus_reflex/request_parameters"
require "stimulus_reflex/reflex"
require "stimulus_reflex/reflex_data"
Expand Down
2 changes: 1 addition & 1 deletion lib/stimulus_reflex/broadcasters/selector_broadcaster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def broadcast(_, data = {})
selectors, html = morph
updates = create_update_collection(selectors, html)
updates.each do |update|
document = StimulusReflex::HTML::DocumentFragment.new(update.html)
document = StimulusReflex::HTML::Document.new(update.html)
match = document.match(update.selector)
if match.present?
operations << [update.selector, StimulusReflex.config.morph_operation]
Expand Down
19 changes: 1 addition & 18 deletions lib/stimulus_reflex/html/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,9 @@ module HTML
class Document
DEFAULT_HTML_WITHOUT_FORMAT = Nokogiri::XML::Node::SaveOptions::DEFAULT_HTML & ~Nokogiri::XML::Node::SaveOptions::FORMAT

delegate :element, to: :@document

def document_element
@document&.root
end

def outer_html
document_element ? document_element.to_html(save_with: DEFAULT_HTML_WITHOUT_FORMAT) : ""
end
alias_method :to_html, :outer_html

def inner_html
document_element ? document_element.inner_html(save_with: DEFAULT_HTML_WITHOUT_FORMAT) : ""
end

def initialize(html)
@document = parsing_class.parse(html.to_s)
@matches = {
"body" => Match.new(@document.at_css("body"))
}
@matches = {}
end

def empty?
Expand Down
13 changes: 0 additions & 13 deletions lib/stimulus_reflex/html/document_fragment.rb

This file was deleted.

56 changes: 56 additions & 0 deletions test/broadcasters/broadcaster_test_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,62 @@ def assert_broadcast_on(stream, data, &block)
assert message, "No messages sent with #{data} to #{stream}"
end

def assert_morph(selector:, input_html:, output_html:)
broadcaster = StimulusReflex::SelectorBroadcaster.new(@reflex)
broadcaster.append_morph(selector, input_html)

expected = {
"cableReady" => true,
"operations" => [
{
"selector" => selector,
"html" => output_html,
"payload" => {},
"childrenOnly" => true,
"permanentAttributeName" => nil,
"stimulusReflex" => {
"some" => "data",
"morph" => "selector"
},
"reflexId" => "666",
"operation" => "morph"
}
],
"version" => CableReady::VERSION
}

assert_broadcast_on @reflex.stream_name, expected do
broadcaster.broadcast nil, some: :data
end
end

def assert_inner_html(selector:, input_html:, output_html:)
broadcaster = StimulusReflex::SelectorBroadcaster.new(@reflex)
broadcaster.append_morph(selector, input_html)

expected = {
"cableReady" => true,
"operations" => [
{
"selector" => selector,
"html" => output_html,
"payload" => {},
"stimulusReflex" => {
"some" => "data",
"morph" => "selector"
},
"reflexId" => "666",
"operation" => "innerHtml"
}
],
"version" => CableReady::VERSION
}

assert_broadcast_on @reflex.stream_name, expected do
broadcaster.broadcast nil, some: :data
end
end

setup do
stub_connection(session_id: SecureRandom.uuid)
def connection.env
Expand Down
145 changes: 145 additions & 0 deletions test/broadcasters/selector_broadcaster_examples_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# frozen_string_literal: true

require_relative "broadcaster_test_case"

module StimulusReflex
class SelectorBroadcasterExamplesTest < StimulusReflex::BroadcasterTestCase
test "morphs the contents of an element when selected by id" do
assert_morph(
selector: "#container",
input_html: '<div id="container"><h1 id="title">Home#index</h1></div>',
output_html: '<h1 id="title">Home#index</h1>'
)

assert_morph(
selector: "#title",
input_html: '<div id="container"><h1 id="title">Home#index</h1></div>',
output_html: "Home#index"
)
end

test "morphs the contents of an element when selected by tag" do
# extract the body
assert_morph(
selector: "body",
input_html: '<body id="body"><h1>Home#index</h1><p>Wassup</p></body>',
output_html: "<h1>Home#index</h1><p>Wassup</p>"
)
end

test "should properly handle a tr without the parent table" do
# note: this doesn't work
# assert_morph(
# selector: "#foo",
# input_html: "<div id='foo'><tr><td>1</td><td>2</td></tr></div>",
# output_html: "<tr><td>1</td><td>2</td></tr>"
# )

assert_inner_html(
selector: "#not-there",
input_html: "<tr><td>1</td><td>2</td></tr>",
output_html: "<tr><td>1</td><td>2</td></tr>"
)
end

test "should properly handle a td without the parent table or td" do
assert_inner_html(
selector: "#not-there",
input_html: "<td>1</td>",
output_html: "<td>1</td>"
)
end

test "should properly parse <tr>" do
assert_inner_html(
selector: "#not-there",
input_html: '<tr data-foo="1" id="123" class="abc"><td>1</td><td>2</td></tr>',
output_html: '<tr data-foo="1" id="123" class="abc"><td>1</td><td>2</td></tr>'
)
end

test "should properly parse <td>" do
assert_inner_html(
selector: "#not-there",
input_html: "<td>1</td>",
output_html: "<td>1</td>"
)
end

test "should properly parse <th>" do
assert_inner_html(
selector: "#not-there",
input_html: "<th>1</th>",
output_html: "<th>1</th>"
)
end

test "should properly parse <thead>" do
assert_inner_html(
selector: "#not-there",
input_html: "<thead><tr><th>1</th><th>2</th></tr></thead>",
output_html: "<thead><tr><th>1</th><th>2</th></tr></thead>"
)
end

test "should properly parse <tbody>" do
assert_inner_html(
selector: "#not-there",
input_html: "<tbody><tr><th>1</th><th>2</th></tr></tbody>",
output_html: "<tbody><tr><th>1</th><th>2</th></tr></tbody>"
)
end

test "should properly parse <tfoot>" do
assert_inner_html(
selector: "#not-there",
input_html: "<tfoot><tr><th>1</th><th>2</th></tr></tfoot>",
output_html: "<tfoot><tr><th>1</th><th>2</th></tr></tfoot>"
)
end

test "should properly parse <ul>" do
assert_inner_html(
selector: "#not-there",
input_html: "<ul><li>1</li></ul>",
output_html: "<ul><li>1</li></ul>"
)
end

test "should properly parse <li>" do
assert_inner_html(
selector: "#not-there",
input_html: "<li>1</li>",
output_html: "<li>1</li>"
)
end

test "should properly parse self-closing tags" do
assert_morph(
selector: "#foo",
input_html: "<div id='foo'><input><span>keep me!</span></div>",
output_html: "<input><span>keep me!</span>",
)

assert_inner_html(
selector: "foo",
input_html: "<input><span>keep me!</span>",
output_html: "<input><span>keep me!</span>",
)
end

test "should properly parse self-closing tags with ->" do
assert_morph(
selector: "#foo",
input_html: "<div id='foo'><input data-action='input->autocomplete#search'><span>keep me!</span></div>",
output_html: "<input data-action=\"input->autocomplete#search\"><span>keep me!</span>",
)

assert_inner_html(
selector: "foo",
input_html: "<input data-action='input->autocomplete#search'><span>keep me!</span>",
output_html: "<input data-action='input->autocomplete#search'><span>keep me!</span>",
)
end
end
end
4 changes: 1 addition & 3 deletions test/broadcasters/selector_broadcaster_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,7 @@ class SelectorBroadcasterTest < StimulusReflex::BroadcasterTestCase
"operations" => [
{
"selector" => "html",
# Nokogiri automatically adds a `<meta>` tag for the encoding
# See. https://github.com/sparklemotion/nokogiri/blob/6ea1449926ce97648bb2f7401c9e4fdcb0e261ba/lib/nokogiri/html4/document.rb#L34-L35
"html" => "<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><title>Test</title></head><body><div><div>bar</div><div>baz</div></div></body>",
"html" => "<head><title>Test</title></head><body><div><div>bar</div><div>baz</div></div></body>",
"payload" => {},
"childrenOnly" => true,
"permanentAttributeName" => nil,
Expand Down
Loading
Loading