Permalink
Browse files

automatically detect field types

  • Loading branch information...
1 parent 0250c85 commit 2b26511f0aa1745f680bdad2437d5a857cbc3610 Michael Stämpfli committed Apr 23, 2012
View
35 lib/corner_stones/form.rb
@@ -1,8 +1,12 @@
+require 'corner_stones/form/field_selector'
+
require 'corner_stones/form/with_inline_errors'
module CornerStones
class Form
+ class UnknownFieldError < RuntimeError; end
+
include Capybara::DSL
def initialize(scope, options = {})
@@ -25,42 +29,15 @@ def submit(submit_options = {})
def fill_in_with(attributes)
within @scope do
attributes.each do |name, value|
- if select_fields.include?(name)
- select(value, :from => name)
- elsif autocomplete_fields.include?(name)
- autocomplete(value, :in => name)
- elsif file_fields.include?(name)
- attach_file(name, value)
- else
- fill_in(name, :with => value)
- end
+ field = FieldSelector.find(name, :autocomplete_fields => autocomplete_fields)
+ field.set value
end
end
end
- def autocomplete(value, options)
- autocomplete_id = find_field(options[:in])[:id]
- fill_in(options[:in], :with => value)
- page.execute_script %Q{ $('##{autocomplete_id}').trigger("focus") }
- page.execute_script %Q{ $('##{autocomplete_id}').trigger("keydown") }
- wait_until do
- result = page.evaluate_script %Q{ $('.ui-menu-item a:contains("#{value}")').size() }
- result > 0
- end
- page.execute_script %Q{ $('.ui-menu-item a:contains("#{value}")').trigger("mouseenter").trigger("click"); }
- end
-
- def select_fields
- @options.fetch(:select_fields) { [] }
- end
-
def autocomplete_fields
@options.fetch(:autocomplete_fields) { [] }
end
-
- def file_fields
- @options.fetch(:file_fields) { [] }
- end
end
end
View
23 lib/corner_stones/form/field_selector.rb
@@ -0,0 +1,23 @@
+require 'corner_stones/form/fields/text_field'
+require 'corner_stones/form/fields/select_field'
+require 'corner_stones/form/fields/file_field'
+require 'corner_stones/form/fields/checkbox'
+require 'corner_stones/form/fields/autocomplete_field'
+
+module CornerStones
+ class Form
+ module FieldSelector
+ FIELDS = [Fields::AutocompleteField, Fields::TextField, Fields::SelectField, Fields::FileField, Fields::Checkbox]
+
+ def self.find(name, options = {})
+ field_class = if options[:autocomplete_fields].include?(name)
+ Fields::AutocompleteField
+ else
+ FIELDS.detect {|selector| selector.handles?(name)}
+ end
+ raise UnknownFieldError, "don't know how to fill the field #{name}" if field_class.nil?
+ field_class.new(name)
+ end
+ end
+ end
+end
View
27 lib/corner_stones/form/fields/autocomplete_field.rb
@@ -0,0 +1,27 @@
+require 'corner_stones/form/fields/base'
+
+module CornerStones
+ class Form
+ module Fields
+ class AutocompleteField < TextField
+ def self.handles?(name)
+ all(:xpath, XPath::HTML.fillable_field(name)).any? do |field|
+ field[:class] =~ /ui-autocomplete-input/
+ end
+ end
+
+ def set(value)
+ autocomplete_id = find_field(@locator)[:id]
+ super
+ page.execute_script %Q{ $('##{autocomplete_id}').trigger("focus") }
+ page.execute_script %Q{ $('##{autocomplete_id}').trigger("keydown") }
+ wait_until do
+ result = page.evaluate_script %Q{ $('.ui-menu-item a:contains("#{value}")').size() }
+ result > 0
+ end
+ page.execute_script %Q{ $('.ui-menu-item a:contains("#{value}")').trigger("mouseenter").trigger("click"); }
+ end
+ end
+ end
+ end
+end
View
16 lib/corner_stones/form/fields/base.rb
@@ -0,0 +1,16 @@
+module CornerStones
+ class Form
+ module Fields
+ class Base
+ def self.inherited(base)
+ base.send :include, Capybara::DSL
+ base.extend Capybara::DSL
+ end
+
+ def initialize(locator)
+ @locator = locator
+ end
+ end
+ end
+ end
+end
View
21 lib/corner_stones/form/fields/checkbox.rb
@@ -0,0 +1,21 @@
+require 'corner_stones/form/fields/base'
+
+module CornerStones
+ class Form
+ module Fields
+ class Checkbox < Base
+ def self.handles?(name)
+ !first(:xpath, XPath::HTML.checkbox(name)).nil?
+ end
+
+ def set(value)
+ if [true, 'yes', 'ja', '1', 1].include?(value)
+ check @locator
+ else
+ uncheck @locator
+ end
+ end
+ end
+ end
+ end
+end
View
17 lib/corner_stones/form/fields/file_field.rb
@@ -0,0 +1,17 @@
+require 'corner_stones/form/fields/base'
+
+module CornerStones
+ class Form
+ module Fields
+ class FileField < Base
+ def self.handles?(name)
+ !first(:xpath, XPath::HTML.file_field(name)).nil?
+ end
+
+ def set(value)
+ attach_file @locator, value
+ end
+ end
+ end
+ end
+end
View
17 lib/corner_stones/form/fields/select_field.rb
@@ -0,0 +1,17 @@
+require 'corner_stones/form/fields/base'
+
+module CornerStones
+ class Form
+ module Fields
+ class SelectField < Base
+ def self.handles?(name)
+ !first(:xpath, XPath::HTML.select(name)).nil?
+ end
+
+ def set(value)
+ select value, :from => @locator
+ end
+ end
+ end
+ end
+end
View
17 lib/corner_stones/form/fields/text_field.rb
@@ -0,0 +1,17 @@
+require 'corner_stones/form/fields/base'
+
+module CornerStones
+ class Form
+ module Fields
+ class TextField < Base
+ def self.handles?(name)
+ !first(:xpath, XPath::HTML.fillable_field(name)).nil?
+ end
+
+ def set(value)
+ fill_in @locator, :with => value
+ end
+ end
+ end
+ end
+end
View
26 spec/integration/corner_stones/form_spec.rb
@@ -24,24 +24,29 @@
<label for="file">File</label>
<input name="file" id="file" type="file">
+ <label for="check">Checkbox</label>
+ <input name="check" id="check" type="checkbox" value="1">
+
<input type="submit" name="button" value="Save">
<input type="submit" name="button" value="Save Article">
</form>
HTML
- subject { CornerStones::Form.new('.article-form', :select_fields => ['Author'], :file_fields => ['File']) }
+ subject { CornerStones::Form.new('.article-form') }
it 'allows you to fill in the form' do
subject.fill_in_with('Title' => 'Domain Driven Design',
'Author' => 'Eric Evans',
'Body' => '...',
- 'File' => 'spec/files/hadoken.png')
+ 'File' => 'spec/files/hadoken.png',
+ 'Checkbox' => true)
find('#title').value.must_equal 'Domain Driven Design'
find('#author').value.must_equal '2'
find('#body').value.must_equal '...'
find('#file').value.must_equal 'spec/files/hadoken.png'
+ find('#check').value.must_equal '1'
end
it 'allows you to submit the form' do
@@ -62,12 +67,13 @@
'Title' => 'Domain Driven Design',
'Author' => 'Eric Evans',
'Body' => 'Some Content...',
- 'File' => 'spec/files/hadoken.png'})
+ 'File' => 'spec/files/hadoken.png',
+ 'Checkbox' => true})
current_path.must_equal '/articles'
page.driver.request.post?.must_equal true
- page.driver.request.params.must_equal({"title" => "Domain Driven Design", "author" => "2", "body" => "Some Content...", "file" => "hadoken.png", 'button' => 'Save'})
+ page.driver.request.params.must_equal({"title" => "Domain Driven Design", "author" => "2", "body" => "Some Content...", "file" => "hadoken.png", 'check' => '1', 'button' => 'Save'})
end
it 'allows you to process (fill_in_with + submit) the form using an alternate button' do
@@ -79,6 +85,18 @@
page.driver.request.params['button'].must_equal('Save Article')
end
+ describe 'form with an unknown field type' do
+ given_the_html <<-HTML
+ <form action="/articles" method="post" class="form-with-errors article-form">
+ <label for="unknown">Unknown</label>
+ <a id="unknown">Link</a>
+ </form>
+HTML
+ it 'raises an error when filling the form' do
+ assert_raises(CornerStones::Form::UnknownFieldError) { subject.fill_in_with('Unknown' => '123456') }
+ end
+ end
+
describe 'mixins' do
describe 'form errors' do

0 comments on commit 2b26511

Please sign in to comment.