@@ -9,15 +9,43 @@ defmodule TestDispatch.Form do
99 def find_inputs ( form , { :entity , _ } = entity_tuple ) ,
1010 do: find_input_fields ( form , entity_tuple )
1111
12+ def find_inputs ( form , { :button_text , button_text } ) do
13+ button = find_buttons ( form , button_text )
14+
15+ if button ,
16+ do: [ button | find_default_inputs ( form ) ] ,
17+ else: find_default_inputs ( form )
18+ end
19+
1220 def find_inputs ( form , _ ) do
21+ find_default_inputs ( form )
22+ end
23+
24+ defp find_default_inputs ( form ) do
1325 fields = find_input_fields ( form , "" )
1426 selects = find_selects ( form , "" )
1527 textareas = find_textareas ( form , "" )
1628 radio_buttons = find_radio_buttons ( form , "" )
17-
1829 Enum . uniq ( fields ++ selects ++ textareas ++ radio_buttons )
1930 end
2031
32+ def find_buttons ( form , button_text ) ,
33+ do:
34+ find_submit_input ( form , button_text ) ||
35+ find_submit_button ( form , button_text )
36+
37+ defp find_submit_button ( form , button_text ) do
38+ form
39+ |> Floki . find ( "button[type=submit]" )
40+ |> Enum . find ( & contains_button_text? ( & 1 , button_text ) )
41+ end
42+
43+ defp find_submit_input ( form , button_text ) do
44+ form
45+ |> Floki . find ( "input[type=submit]" )
46+ |> Enum . find ( & contains_button_text? ( & 1 , button_text ) )
47+ end
48+
2149 def find_radio_buttons ( form , "" ) do
2250 radios = Floki . find ( form , "input[type=radio]" )
2351
@@ -72,6 +100,9 @@ defmodule TestDispatch.Form do
72100 new_nested_list = update_nested_input_values ( acc_nested_list , tuple , nested_attr )
73101
74102 Map . put ( acc , key , new_nested_list )
103+
104+ { } ->
105+ acc
75106 end
76107 end )
77108 end
@@ -80,11 +111,13 @@ defmodule TestDispatch.Form do
80111 value = input |> elem ( 0 ) |> _input_to_tuple ( [ input ] )
81112
82113 case input |> key_for_input ( entity_tuple ) |> resolve_nested ( ) do
114+ nil -> { }
83115 { key , index , nested_key } -> { key , index , { nested_key , value } }
84116 key -> { key , value }
85117 end
86118 end
87119
120+ defp _input_to_tuple ( "button" , input ) , do: Floki . text ( input )
88121 defp _input_to_tuple ( "textarea" , input ) , do: Floki . text ( input )
89122 defp _input_to_tuple ( "input" , input ) , do: floki_attribute ( input , "value" )
90123
@@ -102,6 +135,8 @@ defmodule TestDispatch.Form do
102135 String . replace_prefix ( key , "#{ entity } _" , "" )
103136 end
104137
138+ defp key_for_input ( { "button" , _ , _ } = input , _ ) , do: floki_attribute ( input , "name" )
139+
105140 defp key_for_input ( input , _ ) do
106141 id = floki_attribute ( input , "id" )
107142
@@ -110,6 +145,8 @@ defmodule TestDispatch.Form do
110145 else: id
111146 end
112147
148+ defp resolve_nested ( nil ) , do: nil
149+
113150 defp resolve_nested ( key ) do
114151 case Regex . split ( ~r{ _\d *_} , key , include_captures: true ) do
115152 [ key , capture , nested_key ] ->
@@ -171,13 +208,27 @@ defmodule TestDispatch.Form do
171208 "The provided conn had the status #{ status } that doesn't fall into the 2xx range"
172209 )
173210
174- def find_form_by ( form , nil ) , do: { List . last ( form ) , nil }
211+ def find_form_by ( forms , nil ) , do: { List . last ( forms ) , nil }
175212
176- def find_form_by ( form , entity_or_test_selector ) do
177- test_selector_result = Enum . find ( form , & find_test_selector ( & 1 , entity_or_test_selector ) )
213+ def find_form_by ( forms , button_text: button_text ) do
214+ form = Enum . find ( forms , & contains_button_text? ( & 1 , button_text ) )
215+
216+ if form ,
217+ do: { form , :button_text } ,
218+ else:
219+ raise ( """
220+ No form found for the given button text: #{ button_text }
221+ Found the button texts:
222+
223+ #{ all_buttons ( forms ) }
224+ """ )
225+ end
226+
227+ def find_form_by ( forms , entity_or_test_selector ) do
228+ test_selector_result = Enum . find ( forms , & find_test_selector ( & 1 , entity_or_test_selector ) )
178229
179230 entity_result =
180- Enum . find ( form , & ( & 1 |> Floki . find ( "*[id^=#{ entity_or_test_selector } _]" ) |> Enum . any? ( ) ) )
231+ Enum . find ( forms , & ( & 1 |> Floki . find ( "*[id^=#{ entity_or_test_selector } _]" ) |> Enum . any? ( ) ) )
181232
182233 cond do
183234 is_tuple ( test_selector_result ) ->
@@ -204,4 +255,29 @@ defmodule TestDispatch.Form do
204255 |> html_response ( status )
205256 |> Floki . parse_document! ( )
206257 end
258+
259+ defp contains_button_text? ( form , button_text ) do
260+ input_submit =
261+ form
262+ |> Floki . find ( "input[type=submit]" )
263+ |> Enum . any? ( & ( text ( & 1 ) == button_text ) )
264+
265+ button_submit =
266+ form
267+ |> Floki . find ( "button[type=submit]" )
268+ |> Enum . any? ( & ( text ( & 1 ) == button_text ) )
269+
270+ input_submit || button_submit
271+ end
272+
273+ def text ( html_tree ) ,
274+ do: html_tree |> Floki . text ( ) |> String . replace ( ~r/ \s +/ , " " ) |> String . trim ( )
275+
276+ defp all_buttons ( html_tree ) do
277+ all_submit_buttons = html_tree |> Floki . find ( "button[type=submit]" )
278+ all_submit_inputs = html_tree |> Floki . find ( "input[type=submit]" )
279+
280+ ( all_submit_inputs ++ all_submit_buttons )
281+ |> Enum . map ( & ( text ( [ & 1 ] ) <> "\n " ) )
282+ end
207283end
0 commit comments