-
-
Notifications
You must be signed in to change notification settings - Fork 52
Open
Description
I have a component receiving a Rails form builder (e.g. created by form_for) as an argument. When trying to write tests for it, I can't manage to receive the complete output generated by calling methods on the form builder.
The component seems to only capture method calls directly wrapped within another element (e.g. a span { .. }).
Here's a test to reproduce it:
# frozen_string_literal: true
test "Rails form builder" do
component = Class.new(Phlex::HTML) do
attr_reader :form
def initialize(form)
@form = form
end
define_method :view_template do
span do
form.text_field :name
end
form.button "Submit"
form.label :age do |label|
strong { label.translation }
end
form.fields_for :a do |fields|
fields.text_field :b
end
form.fields :c do |fields|
fields.text_field :d
end
end
end
Cat = Data.define(:name, :age, :a, :c)
form_builder = ActionView::Helpers::FormBuilder.new(
:cat,
Cat.new(name: "Ella", age: 3, a: nil, c: nil),
controller.view_context,
{}
)
output = render(component.new(form_builder))
assert_equivalent_html output, <<~HTML
<input type="text" name="name" value="Ella">
<button name="button" type="submit">Submit</button>
<label>
<strong>Age</strong>
</label>
<input type="text" name="[a][b]" id="_a_b">
<input type="text" name="[c][d]">
HTML
endThis is the test output:
Actual Expected
1 <span> .
2 <input type="text" value="Ella" name="cat[name]" id="cat_name"> 1 <input type="text" name="name" value="Ella">
. 2 <button name="button" type="submit">
. 3 Submit
3 </span> 4 </button>
. 5 <label>
4 <strong> 6 <strong>
5 Age 7 Age
6 </strong> 8 </strong>
9 </label>
10 <input type="text" name="[a][b]" id="_a_b">
11 <input type="text" name="[c][d]">
If I remove the span element, the name text field is not rendered as well.
Note that this is only a testing issue - the component works fine in a normal request flow.
I'll add a couple of crazy, desperate things I tried below.
Using `Phlex::Rails::Builder`
# frozen_string_literal: true
test "Rails form builder" do
component = Class.new(Phlex::HTML) do
attr_reader :form
def initialize(form)
@form = form
end
define_method :view_template do
span do
form.text_field :name
end
form.button "Submit"
form.label :age do |label|
strong { label.translation }
end
form.fields_for :a do |fields|
fields.text_field :b
end
form.fields :c do |fields|
fields.text_field :d
end
end
end
Cat = Data.define(:name, :age, :a, :c)
form_builder = Phlex::Rails::Builder.new(
ActionView::Helpers::FormBuilder.new(
:cat,
Cat.new(name: "Ella", age: 3, a: nil, c: nil),
controller.view_context,
{}
),
component: Class.new(Phlex::HTML).new
).tap do |builder|
state = Phlex::SGML::State.new(
user_context: {},
output_buffer: +"",
fragments: nil
)
builder.instance_variable_set(:@_state, state)
end
output = render(component.new(form_builder))
assert_equivalent_html output, <<~HTML
<input type="text" name="name" value="Ella">
<button name="button" type="submit">Submit</button>
<label>
<strong>Age</strong>
</label>
<input type="text" name="[a][b]" id="_a_b">
<input type="text" name="[c][d]">
HTML
endNot using `render`, but `call` with a buffer
# frozen_string_literal: true
test "Rails form builder" do
component = Class.new(Phlex::HTML) do
attr_reader :form
def initialize(form)
@form = form
end
define_method :view_template do
span do
form.text_field :name
end
form.button "Submit"
form.label :age do |label|
strong { label.translation }
end
form.fields_for :a do |fields|
fields.text_field :b
end
form.fields :c do |fields|
fields.text_field :d
end
end
end
Cat = Data.define(:name, :age, :a, :c)
form_builder = Phlex::Rails::Builder.new(
ActionView::Helpers::FormBuilder.new(
:cat,
Cat.new(name: "Ella", age: 3, a: nil, c: nil),
view_context,
{}
),
component: Class.new(Phlex::HTML).new
).tap do |builder|
state = Phlex::SGML::State.new(
user_context: {},
output_buffer: +"",
fragments: nil
)
builder.instance_variable_set(:@_state, state)
end
buffer = StringIO.new
output = component.new(form_builder).call(buffer).string
assert_equivalent_html output, <<~HTML
<input type="text" name="name" value="Ella">
<button name="button" type="submit">Submit</button>
<label>
<strong>Age</strong>
</label>
<input type="text" name="[a][b]" id="_a_b">
<input type="text" name="[c][d]">
HTML
endMetadata
Metadata
Assignees
Labels
No labels