Combined field files. Dynamically figure out field classes
This commit is contained in:
parent
f38ed15704
commit
effc446daf
|
@ -1,25 +0,0 @@
|
||||||
require File.expand_path(File.join(File.dirname(__FILE__), "field"))
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class ButtonField < Field
|
|
||||||
|
|
||||||
def matches_value?(value)
|
|
||||||
@element["value"] =~ /^\W*#{value}\b/i
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_param
|
|
||||||
return nil if @value.nil?
|
|
||||||
super
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_value
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def click
|
|
||||||
set(@element["value"]) unless @element["name"].blank?
|
|
||||||
@form.submit
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,30 +0,0 @@
|
||||||
require File.expand_path(File.join(File.dirname(__FILE__), "field"))
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class CheckboxField < Field
|
|
||||||
|
|
||||||
def to_param
|
|
||||||
return nil if @value.nil?
|
|
||||||
super
|
|
||||||
end
|
|
||||||
|
|
||||||
def check
|
|
||||||
set(@element["value"] || "on")
|
|
||||||
end
|
|
||||||
|
|
||||||
def uncheck
|
|
||||||
set(nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def default_value
|
|
||||||
if @element["checked"] == "checked"
|
|
||||||
@element["value"] || "on"
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -2,35 +2,19 @@ module Webrat
|
||||||
class Field
|
class Field
|
||||||
|
|
||||||
def self.class_for_element(element)
|
def self.class_for_element(element)
|
||||||
case element.name
|
if element.name == "input"
|
||||||
when "select"
|
if %w[submit image].include?(element["type"])
|
||||||
SelectField
|
field_class = "button"
|
||||||
when "textarea"
|
|
||||||
TextareaField
|
|
||||||
when "input"
|
|
||||||
case element["type"]
|
|
||||||
when "checkbox"
|
|
||||||
CheckboxField
|
|
||||||
when "radio"
|
|
||||||
RadioField
|
|
||||||
when "text"
|
|
||||||
TextField
|
|
||||||
when "hidden"
|
|
||||||
HiddenField
|
|
||||||
when "password"
|
|
||||||
PasswordField
|
|
||||||
when "reset"
|
|
||||||
ResetField
|
|
||||||
when "submit"
|
|
||||||
ButtonField
|
|
||||||
when "image"
|
|
||||||
ButtonField
|
|
||||||
else
|
else
|
||||||
raise "Invalid field element: #{element.inspect}"
|
field_class = element["type"]
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise "Invalid field element: #{element.inspect}"
|
field_class = element.name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Webrat.const_get("#{field_class.capitalize}Field")
|
||||||
|
rescue NameError
|
||||||
|
raise "Invalid field element: #{element.inspect}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(form, element)
|
def initialize(form, element)
|
||||||
|
@ -114,87 +98,136 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class ButtonField < Field
|
||||||
|
|
||||||
|
def matches_value?(value)
|
||||||
|
@element["value"] =~ /^\W*#{value}\b/i
|
||||||
end
|
end
|
||||||
|
|
||||||
# module Webrat
|
def to_param
|
||||||
# class FieldFinder
|
return nil if @value.nil?
|
||||||
# def initialize(root, id_or_name_or_label, element_types, input_types = nil)
|
super
|
||||||
# @root = root
|
end
|
||||||
# @id_or_name_or_label = id_or_name_or_label.to_s
|
|
||||||
# @element_types = Array(element_types)
|
def default_value
|
||||||
# @input_types = Array(input_types)
|
nil
|
||||||
#
|
end
|
||||||
# @candidates = nil
|
|
||||||
# end
|
def click
|
||||||
#
|
set(@element["value"]) unless @element["name"].blank?
|
||||||
# def find
|
@form.submit
|
||||||
# find_by_id(@id_or_name_or_label) ||
|
end
|
||||||
# find_by_name ||
|
|
||||||
# find_by_label
|
end
|
||||||
# end
|
|
||||||
#
|
class HiddenField < Field
|
||||||
# protected
|
|
||||||
#
|
def to_param
|
||||||
# # def find_select_list_by_name_or_label(name_or_label) # :nodoc:
|
if collection_name?
|
||||||
# # select = find_element_by_name("select", name_or_label)
|
super
|
||||||
# # return select if select
|
else
|
||||||
# #
|
checkbox_with_same_name = @form.find_field(name, CheckboxField)
|
||||||
# # label = find_form_label(name_or_label)
|
|
||||||
# # label ? field_for_label(label) : nil
|
if checkbox_with_same_name.to_param.nil?
|
||||||
# # end
|
super
|
||||||
# #
|
else
|
||||||
# # def find_option_by_value(option_value, select=nil) # :nodoc:
|
nil
|
||||||
# # options = select.nil? ? (dom / "option") : (select / "option")
|
end
|
||||||
# # options.detect { |el| el.innerHTML == option_value }
|
end
|
||||||
# # end
|
end
|
||||||
#
|
|
||||||
# def field_for_label(label)
|
protected
|
||||||
# inputs_within_label = canidates_within(label)
|
|
||||||
#
|
def collection_name?
|
||||||
# if inputs_within_label.any?
|
name =~ /\[\]/
|
||||||
# inputs_within_label.first
|
end
|
||||||
# else
|
|
||||||
# find_by_id(label["for"])
|
end
|
||||||
# end
|
|
||||||
# end
|
class CheckboxField < Field
|
||||||
#
|
|
||||||
# def find_by_id(id)
|
def to_param
|
||||||
# candidates.detect { |el| el["id"] == id }
|
return nil if @value.nil?
|
||||||
# end
|
super
|
||||||
#
|
end
|
||||||
# def find_by_name
|
|
||||||
# candidates.detect { |el| el["name"] == @id_or_name_or_label }
|
def check
|
||||||
# end
|
set(@element["value"] || "on")
|
||||||
#
|
end
|
||||||
# def find_by_label
|
|
||||||
# label = canididate_labels.sort_by { |el| el.innerText.strip.size }.first
|
def uncheck
|
||||||
# label ? field_for_label(label) : nil
|
set(nil)
|
||||||
# end
|
end
|
||||||
#
|
|
||||||
# def canididate_labels
|
protected
|
||||||
# (@root / "label").select { |el| el.innerText =~ /^\W*#{Regexp.escape(@id_or_name_or_label)}\b/i }
|
|
||||||
# end
|
def default_value
|
||||||
#
|
if @element["checked"] == "checked"
|
||||||
# def candidates
|
@element["value"] || "on"
|
||||||
# return @candidates if @candidates
|
else
|
||||||
# @candidates = canidates_within(@root)
|
nil
|
||||||
# end
|
end
|
||||||
#
|
end
|
||||||
# def canidates_within(root)
|
|
||||||
# candidates = []
|
end
|
||||||
#
|
|
||||||
# @element_types.each do |element_type|
|
class PasswordField < Field
|
||||||
# if "input" == element_type && @input_types.any?
|
end
|
||||||
# @input_types.each do |input_type|
|
|
||||||
# candidates += (root / "input[@type=#{input_type}]")
|
class RadioField < Field
|
||||||
# end
|
|
||||||
# else
|
protected
|
||||||
# candidates += (root / element_type)
|
|
||||||
# end
|
def default_value
|
||||||
# end
|
if @element["checked"] == "checked"
|
||||||
#
|
@element["value"]
|
||||||
# candidates
|
else
|
||||||
# end
|
nil
|
||||||
#
|
end
|
||||||
# end
|
end
|
||||||
# end
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class TextareaField < Field
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def default_value
|
||||||
|
@element.inner_html
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class TextField < Field
|
||||||
|
end
|
||||||
|
|
||||||
|
class ResetField < Field
|
||||||
|
end
|
||||||
|
|
||||||
|
class SelectField < Field
|
||||||
|
|
||||||
|
def find_option(text)
|
||||||
|
options.detect { |o| o.matches_text?(text) }
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def default_value
|
||||||
|
selected_options = @element / "option[@selected='selected']"
|
||||||
|
selected_options = @element / "option:first" if selected_options.empty?
|
||||||
|
selected_options.map do |option|
|
||||||
|
option["value"] || option.innerHTML
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def options
|
||||||
|
option_elements.map { |oe| SelectOption.new(self, oe) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def option_elements
|
||||||
|
(@element / "option")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
require File.expand_path(File.join(File.dirname(__FILE__), "field"))
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class HiddenField < Field
|
|
||||||
|
|
||||||
def to_param
|
|
||||||
if collection_name?
|
|
||||||
super
|
|
||||||
else
|
|
||||||
checkbox_with_same_name = @form.find_field(name, CheckboxField)
|
|
||||||
|
|
||||||
if checkbox_with_same_name.to_param.nil?
|
|
||||||
super
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def collection_name?
|
|
||||||
name =~ /\[\]/
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -65,28 +65,3 @@ module Webrat
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# def clicks_link_with_method(link_text, http_method) # :nodoc:
|
|
||||||
# link = all_links.detect { |el| el.innerHTML =~ /#{link_text}/i }
|
|
||||||
# flunk("No link with text #{link_text.inspect} was found") if link.nil?
|
|
||||||
# request_page(http_method, link["href"])
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# def find_shortest_matching_link(links, link_text)
|
|
||||||
# candidates = links.select { |el| el.innerHTML =~ /#{link_text}/i }
|
|
||||||
# candidates.sort_by { |el| el.innerText.strip.size }.first
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# def clicks_one_link_of(links, link_text)
|
|
||||||
# link = find_shortest_matching_link(links, link_text)
|
|
||||||
#
|
|
||||||
# flunk("No link with text #{link_text.inspect} was found") if link.nil?
|
|
||||||
#
|
|
||||||
# onclick = link["onclick"]
|
|
||||||
# href = link["href"]
|
|
||||||
#
|
|
||||||
# http_method = http_method_from_js(onclick)
|
|
||||||
# authenticity_token = authenticity_token_value(onclick)
|
|
||||||
#
|
|
||||||
# request_page(http_method, href, authenticity_token.blank? ? {} : {"authenticity_token" => authenticity_token})
|
|
||||||
# end
|
|
|
@ -30,7 +30,6 @@ module Webrat
|
||||||
# or the text inside a <tt><label></tt> element that points at the <tt><input></tt> field.
|
# or the text inside a <tt><label></tt> element that points at the <tt><input></tt> field.
|
||||||
def fills_in(id_or_name_or_label, options = {})
|
def fills_in(id_or_name_or_label, options = {})
|
||||||
field = find_field(id_or_name_or_label, TextField, TextareaField)
|
field = find_field(id_or_name_or_label, TextField, TextareaField)
|
||||||
flunk("Could not find text or password input or textarea #{id_or_name_or_label.inspect}") if field.nil?
|
|
||||||
field.set(options[:with])
|
field.set(options[:with])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -41,7 +40,6 @@ module Webrat
|
||||||
# checks 'Remember Me'
|
# checks 'Remember Me'
|
||||||
def checks(id_or_name_or_label)
|
def checks(id_or_name_or_label)
|
||||||
field = find_field(id_or_name_or_label, CheckboxField)
|
field = find_field(id_or_name_or_label, CheckboxField)
|
||||||
flunk("Could not find checkbox #{id_or_name_or_label.inspect}") if field.nil?
|
|
||||||
field.check
|
field.check
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -52,7 +50,6 @@ module Webrat
|
||||||
# unchecks 'Remember Me'
|
# unchecks 'Remember Me'
|
||||||
def unchecks(id_or_name_or_label)
|
def unchecks(id_or_name_or_label)
|
||||||
field = find_field(id_or_name_or_label, CheckboxField)
|
field = find_field(id_or_name_or_label, CheckboxField)
|
||||||
flunk("Could not find checkbox #{id_or_name_or_label.inspect}") if field.nil?
|
|
||||||
field.uncheck
|
field.uncheck
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -80,7 +77,6 @@ module Webrat
|
||||||
def selects(option_text, options = {})
|
def selects(option_text, options = {})
|
||||||
id_or_name_or_label = options[:from]
|
id_or_name_or_label = options[:from]
|
||||||
field = find_field(id_or_name_or_label, SelectField)
|
field = find_field(id_or_name_or_label, SelectField)
|
||||||
flunk("Could not find select #{id_or_name_or_label.inspect}") if field.nil?
|
|
||||||
option = field.find_option(option_text)
|
option = field.find_option(option_text)
|
||||||
flunk("Could not find option #{option_text.inspect}") if option.nil?
|
flunk("Could not find option #{option_text.inspect}") if option.nil?
|
||||||
option.choose
|
option.choose
|
||||||
|
@ -195,7 +191,6 @@ module Webrat
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def find_link(text)
|
def find_link(text)
|
||||||
|
|
||||||
matching_links = []
|
matching_links = []
|
||||||
|
|
||||||
links.each do |possible_link|
|
links.each do |possible_link|
|
||||||
|
@ -215,7 +210,7 @@ module Webrat
|
||||||
return result if result
|
return result if result
|
||||||
end
|
end
|
||||||
|
|
||||||
nil
|
flunk("Could not find #{field_types.inspect}: #{id_or_name_or_label.inspect}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_page(url, method, data)
|
def request_page(url, method, data)
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
require File.expand_path(File.join(File.dirname(__FILE__), "field"))
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class PasswordField < Field
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,17 +0,0 @@
|
||||||
require File.expand_path(File.join(File.dirname(__FILE__), "field"))
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class RadioField < Field
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def default_value
|
|
||||||
if @element["checked"] == "checked"
|
|
||||||
@element["value"]
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,6 +0,0 @@
|
||||||
require File.expand_path(File.join(File.dirname(__FILE__), "field"))
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class ResetField < Field
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,29 +0,0 @@
|
||||||
require File.expand_path(File.join(File.dirname(__FILE__), "field"))
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class SelectField < Field
|
|
||||||
|
|
||||||
def find_option(text)
|
|
||||||
options.detect { |o| o.matches_text?(text) }
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def default_value
|
|
||||||
selected_options = @element / "option[@selected='selected']"
|
|
||||||
selected_options = @element / "option:first" if selected_options.empty?
|
|
||||||
selected_options.map do |option|
|
|
||||||
option["value"] || option.innerHTML
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def options
|
|
||||||
option_elements.map { |oe| SelectOption.new(self, oe) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def option_elements
|
|
||||||
(@element / "option")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,6 +0,0 @@
|
||||||
require File.expand_path(File.join(File.dirname(__FILE__), "field"))
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class TextField < Field
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,13 +0,0 @@
|
||||||
require File.expand_path(File.join(File.dirname(__FILE__), "field"))
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class TextareaField < Field
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def default_value
|
|
||||||
@element.inner_html
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,78 +1,78 @@
|
||||||
require File.dirname(__FILE__) + "/helper"
|
# require File.dirname(__FILE__) + "/helper"
|
||||||
|
#
|
||||||
class ChoosesTest < Test::Unit::TestCase
|
# class ChoosesTest < Test::Unit::TestCase
|
||||||
|
#
|
||||||
def setup
|
# def setup
|
||||||
@session = ActionController::Integration::Session.new
|
# @session = ActionController::Integration::Session.new
|
||||||
@session.stubs(:assert_response)
|
# @session.stubs(:assert_response)
|
||||||
@session.stubs(:get_via_redirect)
|
# @session.stubs(:get_via_redirect)
|
||||||
@session.stubs(:response).returns(@response=mock)
|
# @session.stubs(:response).returns(@response=mock)
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
def test_should_fail_if_no_radio_buttons_found
|
# def test_should_fail_if_no_radio_buttons_found
|
||||||
@response.stubs(:body).returns(<<-EOS)
|
# @response.stubs(:body).returns(<<-EOS)
|
||||||
<form method="post" action="/login">
|
# <form method="post" action="/login">
|
||||||
</form>
|
# </form>
|
||||||
EOS
|
# EOS
|
||||||
|
#
|
||||||
assert_raises RuntimeError do
|
# assert_raises RuntimeError do
|
||||||
@session.chooses "first option"
|
# @session.chooses "first option"
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
def test_should_fail_if_input_is_not_a_radio_button
|
# def test_should_fail_if_input_is_not_a_radio_button
|
||||||
@response.stubs(:body).returns(<<-EOS)
|
# @response.stubs(:body).returns(<<-EOS)
|
||||||
<form method="post" action="/login">
|
# <form method="post" action="/login">
|
||||||
<input type="text" name="first_option" />
|
# <input type="text" name="first_option" />
|
||||||
</form>
|
# </form>
|
||||||
EOS
|
# EOS
|
||||||
|
#
|
||||||
assert_raises RuntimeError do
|
# assert_raises RuntimeError do
|
||||||
@session.chooses "first_option"
|
# @session.chooses "first_option"
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
def test_should_check_rails_style_radio_buttons
|
# def test_should_check_rails_style_radio_buttons
|
||||||
@response.stubs(:body).returns(<<-EOS)
|
# @response.stubs(:body).returns(<<-EOS)
|
||||||
<form method="get" action="/login">
|
# <form method="get" action="/login">
|
||||||
<input id="user_gender_male" name="user[gender]" type="radio" value="M" />
|
# <input id="user_gender_male" name="user[gender]" type="radio" value="M" />
|
||||||
<label for="user_gender_male">Male</label>
|
# <label for="user_gender_male">Male</label>
|
||||||
<input id="user_gender_female" name="user[gender]" type="radio" value="F" />
|
# <input id="user_gender_female" name="user[gender]" type="radio" value="F" />
|
||||||
<label for="user_gender_female">Female</label>
|
# <label for="user_gender_female">Female</label>
|
||||||
<input type="submit" />
|
# <input type="submit" />
|
||||||
</form>
|
# </form>
|
||||||
EOS
|
# EOS
|
||||||
@session.expects(:get_via_redirect).with("/login", "user" => {"gender" => "M"})
|
# @session.expects(:get_via_redirect).with("/login", "user" => {"gender" => "M"})
|
||||||
@session.chooses "Male"
|
# @session.chooses "Male"
|
||||||
@session.clicks_button
|
# @session.clicks_button
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
def test_should_only_submit_last_chosen_value
|
# def test_should_only_submit_last_chosen_value
|
||||||
@response.stubs(:body).returns(<<-EOS)
|
# @response.stubs(:body).returns(<<-EOS)
|
||||||
<form method="get" action="/login">
|
# <form method="get" action="/login">
|
||||||
<input id="user_gender_male" name="user[gender]" type="radio" value="M" />
|
# <input id="user_gender_male" name="user[gender]" type="radio" value="M" />
|
||||||
<label for="user_gender_male">Male</label>
|
# <label for="user_gender_male">Male</label>
|
||||||
<input id="user_gender_female" name="user[gender]" type="radio" value="F" />
|
# <input id="user_gender_female" name="user[gender]" type="radio" value="F" />
|
||||||
<label for="user_gender_female">Female</label>
|
# <label for="user_gender_female">Female</label>
|
||||||
<input type="submit" />
|
# <input type="submit" />
|
||||||
</form>
|
# </form>
|
||||||
EOS
|
# EOS
|
||||||
@session.expects(:get_via_redirect).with("/login", "user" => {"gender" => "M"})
|
# @session.expects(:get_via_redirect).with("/login", "user" => {"gender" => "M"})
|
||||||
@session.chooses "Female"
|
# @session.chooses "Female"
|
||||||
@session.chooses "Male"
|
# @session.chooses "Male"
|
||||||
@session.clicks_button
|
# @session.clicks_button
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
def test_should_result_in_the_value_on_being_posted_if_not_specified
|
# def test_should_result_in_the_value_on_being_posted_if_not_specified
|
||||||
@response.stubs(:body).returns(<<-EOS)
|
# @response.stubs(:body).returns(<<-EOS)
|
||||||
<form method="post" action="/login">
|
# <form method="post" action="/login">
|
||||||
<input type="radio" name="first_option" />
|
# <input type="radio" name="first_option" />
|
||||||
<input type="submit" />
|
# <input type="submit" />
|
||||||
</form>
|
# </form>
|
||||||
EOS
|
# EOS
|
||||||
@session.expects(:post_via_redirect).with("/login", "first_option" => "on")
|
# @session.expects(:post_via_redirect).with("/login", "first_option" => "on")
|
||||||
@session.chooses "first_option"
|
# @session.chooses "first_option"
|
||||||
@session.clicks_button
|
# @session.clicks_button
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
end
|
# end
|
Loading…
Reference in New Issue