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

Fixes misreported HTML errors when input labels are changed by CSS #712

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
19 changes: 19 additions & 0 deletions integration_test/cases/browser/click_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,25 @@ defmodule Wallaby.Integration.Browser.ClickTest do

assert selected?(page, Query.css("#option2"))
end

for {function, button_type} <- [
{&Query.checkbox/1, "checkbox"},
{&Query.button/1, "button"},
{&Query.radio_button/1, "radio"}
] do
test "throw an error if label exists for #{button_type} but is not a case match", %{
page: page
} do
assert_raise Wallaby.QueryError,
~r/matched a label but that label does not find the button/,
fn ->
click(
page,
unquote(function).("misreporting html errors #{unquote(button_type)}")
)
end
end
end
end

describe "click/2 with radio buttons (choose replacement)" do
Expand Down
15 changes: 15 additions & 0 deletions integration_test/support/pages/forms.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ <h1>Forms</h1>
Option 1
</label>

<label style="text-transform: lowercase">
<input type="radio">
Misreporting HTML errors radio
</label>

<label style="text-transform: lowercase">
<input type="checkbox">
Misreporting HTML errors checkbox
</label>

<label style="text-transform: lowercase">
<input type="button">
Misreporting HTML errors button
</label>

<input id="option2" type="radio" name="optionsRadios" value="option2">

<textarea name="text" rows="8" cols="40"></textarea>
Expand Down
39 changes: 35 additions & 4 deletions lib/wallaby/browser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,7 @@ defmodule Wallaby.Browser do
if Enum.count(buttons) == 1 do
{:error, :button_with_bad_type}
else
{:ok, query}
validate_button_label(parent, query)
end
end

Expand All @@ -1411,9 +1411,7 @@ defmodule Wallaby.Browser do
if for_attr == nil do
:label_with_no_for
else
id_query = Query.css("[id='#{for_attr}']", count: :any)
matching_id_count = parent |> all(id_query) |> Enum.count()

matching_id_count = get_for_attr_id_count(parent, for_attr)
{:label_does_not_find_field, for_attr, matching_id_count}
end

Expand All @@ -1426,6 +1424,39 @@ defmodule Wallaby.Browser do

defp validate_html(_, query), do: {:ok, query}

defp validate_button_label(parent, query) do
labels = all(parent, Query.css("label", text: query.selector))

case labels do
[label] ->
for_attr = Element.attr(label, "for")
input_children = all(label, Query.css("input"))

error =
cond do
is_nil(for_attr) and Enum.empty?(input_children) ->
:label_with_no_for

not is_nil(for_attr) ->
matching_id_count = get_for_attr_id_count(parent, for_attr)
{:label_does_not_find_field, for_attr, matching_id_count}

true ->
:label_does_not_find_button
end

{:error, error}

_ ->
{:ok, query}
end
end

defp get_for_attr_id_count(parent, for_attr) do
id_query = Query.css("[id='#{for_attr}']", count: :any)
parent |> all(id_query) |> Enum.count()
end

defp validate_visibility(query, elements) do
case Query.visible?(query) do
:any ->
Expand Down
4 changes: 2 additions & 2 deletions lib/wallaby/query.ex
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ defmodule Wallaby.Query do
method: :radio_button,
selector: selector,
conditions: build_conditions(opts),
html_validation: :bad_label
html_validation: :button_type
}
end

Expand All @@ -268,7 +268,7 @@ defmodule Wallaby.Query do
method: :checkbox,
selector: selector,
conditions: build_conditions(opts),
html_validation: :bad_label
html_validation: :button_type
}
end

Expand Down
9 changes: 9 additions & 0 deletions lib/wallaby/query/error_message.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ defmodule Wallaby.Query.ErrorMessage do
"""
end

def message(%{selector: selector}, :label_does_not_find_button) do
"""
The text '#{selector}' matched a label but that label does not find the button.

You should ensure you are using the right query function and that the text matches the
label's raw HTML exactly (before any CSS transforms are applied).
"""
end

def message(%{selector: selector}, :button_with_bad_type) do
"""
The text '#{selector}' matched a button but the button has an invalid 'type' attribute.
Expand Down