formulaic 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CONTRIBUTING.md +39 -0
- data/Gemfile +1 -1
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +115 -17
- data/Rakefile +1 -1
- data/formulaic.gemspec +23 -14
- data/lib/formulaic.rb +10 -0
- data/lib/formulaic/dsl.rb +11 -0
- data/lib/formulaic/form.rb +45 -0
- data/lib/formulaic/inputs.rb +5 -0
- data/lib/formulaic/inputs/array_input.rb +9 -0
- data/lib/formulaic/inputs/boolean_input.rb +13 -0
- data/lib/formulaic/inputs/date_input.rb +18 -0
- data/lib/formulaic/inputs/input.rb +24 -0
- data/lib/formulaic/inputs/string_input.rb +19 -0
- data/lib/formulaic/label.rb +51 -0
- data/lib/formulaic/version.rb +3 -0
- data/spec/features/fill_in_user_form_spec.rb +62 -0
- data/spec/fixtures/user_form.html +171 -0
- data/spec/formulaic/dsl_spec.rb +17 -0
- data/spec/formulaic/form_spec.rb +7 -0
- data/spec/formulaic/label_spec.rb +31 -0
- data/spec/spec_helper.rb +38 -0
- metadata +107 -10
- data/lib/formualic.rb +0 -5
- data/lib/formualic/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6bef13aba12616219a2a8e5f254c3298ec6c00c8
|
4
|
+
data.tar.gz: c1eb43ca79ac45e3b9121f402dc1b74ff99ca809
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16362b7ff583f4a85b68608d21eb77b605045a28b3305ba01fe8b0bc84e74155498991ca1d6d6a9b03a507929a59d7f4a0fa401d9c8064446a33c5ad5de8c032
|
7
|
+
data.tar.gz: 756dcffdc59c4219e50f717b08f0f41a5e70930e50cb4cc6d094c020909f64776ace0638c7ebafc1b7b15560ef8e4d36e94edb1b99c40202b90f666845cfec94
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
formulaic
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.0.0-p195
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
We love pull requests. Here's a quick guide:
|
4
|
+
|
5
|
+
1. Fork the repo.
|
6
|
+
2. Run the tests. We only take pull requests with passing tests, and it's great
|
7
|
+
to know that you have a clean slate: `bundle && rake`
|
8
|
+
3. Add a test for your change. Only refactoring and documentation changes
|
9
|
+
require no new tests. If you are adding functionality or fixing a bug, we need
|
10
|
+
a test!
|
11
|
+
4. Make the test pass.
|
12
|
+
5. Make sure your changes adhere to the [thoughtbot Style
|
13
|
+
Guide](https://github.com/thoughtbot/guides/tree/master/style)
|
14
|
+
6. Push to your fork and submit a pull request.
|
15
|
+
7. At this point you're waiting on us. We like to at least comment on, if not
|
16
|
+
accept, pull requests within three business days (and, typically, one business
|
17
|
+
day). [We may suggest some changes or improvements or
|
18
|
+
alternatives](https://github.com/thoughtbot/guides/tree/master/code-review).
|
19
|
+
|
20
|
+
## Increase your chances of getting merged
|
21
|
+
|
22
|
+
Some things that will increase the chance that your pull request is accepted,
|
23
|
+
taken straight from the Ruby on Rails guide:
|
24
|
+
|
25
|
+
* Use Rails idioms and helpers
|
26
|
+
* Include tests that fail without your code, and pass with it
|
27
|
+
* Update the documentation: that surrounding your change, examples elsewhere,
|
28
|
+
guides, and whatever else is affected by your contribution
|
29
|
+
* Syntax:
|
30
|
+
* Two spaces, no tabs.
|
31
|
+
* No trailing whitespace. Blank lines should not have any space.
|
32
|
+
* Make sure your [source files end with newline
|
33
|
+
characters](http://stackoverflow.com/questions/729692/why-should-files-end-with-a-newline#answer-729725).
|
34
|
+
* Prefer `&&`/`||` over `and`/`or`.
|
35
|
+
* `MyClass.my_method(my_arg)` not `my_method( my_arg )` or
|
36
|
+
`my_method my_arg`.
|
37
|
+
* `a = b` and not `a=b`.
|
38
|
+
* Follow the conventions you see used in the source already.
|
39
|
+
* And in case we didn't emphasize it enough: *We love tests!*
|
data/Gemfile
CHANGED
data/{LICENSE.txt → LICENSE}
RENAMED
data/README.md
CHANGED
@@ -1,29 +1,127 @@
|
|
1
|
-
#
|
1
|
+
# Formulaic
|
2
2
|
|
3
|
-
|
3
|
+
Remove the tedium of formulaic form filling with Capybara.
|
4
4
|
|
5
|
-
|
5
|
+
Formulaic allows you to specify a hash of attributes to be input rather than
|
6
|
+
procedurally calling Capybara’s DSL methods.
|
6
7
|
|
7
|
-
|
8
|
+
## Usage
|
8
9
|
|
9
|
-
|
10
|
+
```ruby
|
11
|
+
feature 'New user registration' do
|
12
|
+
scenario 'succesfull sign up' do
|
13
|
+
visit sign_in_path
|
10
14
|
|
11
|
-
|
15
|
+
fill_form(:user, { name: 'Caleb', email: 'caleb@thoughtbot.com', 'Terms of Service': true })
|
16
|
+
click_on submit(:user)
|
12
17
|
|
13
|
-
|
18
|
+
expect(page).to have_content t('user.create.success')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
```
|
14
22
|
|
15
|
-
Or install it yourself as:
|
16
23
|
|
17
|
-
|
24
|
+
### `fill_form`
|
18
25
|
|
19
|
-
|
26
|
+
```ruby
|
27
|
+
fill_form(model_name, attributes)
|
28
|
+
```
|
29
|
+
|
30
|
+
`fill_form` provides an interface to completely filling out a form. Provide the
|
31
|
+
`model_name` as a symbol and `attributes` as a hash of
|
32
|
+
`column name => database value` or `label string => database value`.
|
33
|
+
|
34
|
+
If an `attributes` key is a `String`, it will be used as the literal label.
|
35
|
+
For `Symbol` we will attempt to translate, fall back to `human_attribute_name`
|
36
|
+
if available, then call `to_s`.
|
37
|
+
|
38
|
+
### `input`
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
input(model_name, field)
|
42
|
+
```
|
43
|
+
|
44
|
+
`input` gives an easy way to find the translated text of an input. It is
|
45
|
+
primarily used internally to fill `<input>`s, but is provided in the public API
|
46
|
+
as it could be useful.
|
47
|
+
|
48
|
+
### `submit`
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
submit(model_name, action = :create)
|
52
|
+
```
|
53
|
+
|
54
|
+
`submit` functions like [`input`](#input), but finds the translation for the
|
55
|
+
submit button of the form. `model_name` should be the same as what you provide
|
56
|
+
to [`fill_form`](#fill\_form). Typically, the return value of `submit` will be
|
57
|
+
passed directly to Capybara’s `click_on` method.
|
58
|
+
|
59
|
+
If you are submitting a form that is not for the `create` action, you may need
|
60
|
+
to pass the `action`:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
submit(:user, :update)
|
64
|
+
```
|
65
|
+
|
66
|
+
The `model_name` and `action` should match up to the
|
67
|
+
`helpers.submit.<model_name>.<action>` translations.
|
68
|
+
|
69
|
+
### Integration with RSpec:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
# spec/spec_helper.rb
|
73
|
+
|
74
|
+
RSpec.configure do |config|
|
75
|
+
config.include Formulaic::Dsl
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
### Integration with [FactoryGirl](https://github.com/thoughtbot/factory_girl)
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
fill_form(:user, attributes_for(:user))
|
83
|
+
```
|
84
|
+
|
85
|
+
You may have attributes included in your `User` factory that don’t pretain to
|
86
|
+
sign up:
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
fill_form(:user, attributes_for(:user).slice(sign_up_attributes))
|
90
|
+
|
91
|
+
# ...
|
92
|
+
def sign_up_attributes
|
93
|
+
[:name, :email, :terms_of_service]
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
## Known Limitations
|
98
|
+
|
99
|
+
* Formulaic currently supports the following mappings from the `#class` of the
|
100
|
+
attribute values to Capybara method calls:
|
101
|
+
|
102
|
+
| Classes | Formulaic’s action |
|
103
|
+
| --------------------------------------|-------------------------------|
|
104
|
+
| `String` | `fill_in` |
|
105
|
+
| `Date`, `ActiveSupport::TimeWithZone` | `select` year, month, and day |
|
106
|
+
| `TrueClass` | `check` |
|
107
|
+
| `FalseClass` | `uncheck` |
|
108
|
+
| `Array` | `check` each array member, which should all be strings |
|
109
|
+
|
110
|
+
* Formulaic is currently tied to `simple_form` translations and field structure.
|
111
|
+
If you pass a string for the attribute, we’ll try to fill the input that
|
112
|
+
relates to that label. We would be happy to work with you to add support for
|
113
|
+
other form builders.
|
114
|
+
* Formulaic currently does not support forms with duplicate labels, as it is
|
115
|
+
designed to be as similar as possible to a user completing a form—it looks at
|
116
|
+
the labels to determine where to fill what data.
|
117
|
+
* Formulaic can’t figure out how to fill fields with HTML labels:
|
118
|
+
`page.fill_in('<strong>Text</strong> here', with: 'something')` doesn’t work
|
119
|
+
with Capybara. The usual workaround is to pass a CSS selector.
|
20
120
|
|
21
|
-
|
121
|
+
## About
|
22
122
|
|
23
|
-
|
123
|
+
Formulaic is maintained by [Caleb Thompson](http://github.com/calebthompson).
|
124
|
+
It was written by [thoughtbot](http://thoughtbot.com) with the help of our
|
125
|
+
[contributors](http://github.com/thoughtbot/formulaic/contributors).
|
24
126
|
|
25
|
-
|
26
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
127
|
+
[![Ralph](http://thoughtbot.com/assets/thoughtbot-logo.png)](http://thoughtbot.com)
|
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
data/formulaic.gemspec
CHANGED
@@ -1,23 +1,32 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require '
|
4
|
+
require 'formulaic/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
-
spec.version =
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.
|
12
|
-
spec.
|
13
|
-
|
14
|
-
|
7
|
+
spec.name = 'formulaic'
|
8
|
+
spec.version = Formulaic::VERSION
|
9
|
+
spec.authors = ['Caleb Thompson']
|
10
|
+
spec.email = ['caleb@calebthompson.io']
|
11
|
+
spec.summary = 'Simplify form filling with Capybara'
|
12
|
+
spec.description = <<-DESCRIPTION.sub(/^ +/, '')
|
13
|
+
Removes the tedium of formulaic form filling with Capybara by allowing you
|
14
|
+
to specify a hash of attributes to be input rather than procedurally calling
|
15
|
+
Capybara’s DSL methods.
|
16
|
+
DESCRIPTION
|
17
|
+
spec.homepage = 'https://github.com/thoughtbot/formulaic'
|
18
|
+
spec.license = 'MIT'
|
15
19
|
|
16
20
|
spec.files = `git ls-files`.split($/)
|
17
|
-
spec.
|
18
|
-
spec.
|
19
|
-
spec.require_paths = ["lib"]
|
21
|
+
spec.test_files = spec.files.grep(%r{^spec/})
|
22
|
+
spec.require_paths = ['lib']
|
20
23
|
|
21
|
-
spec.
|
22
|
-
spec.
|
24
|
+
spec.add_dependency 'capybara'
|
25
|
+
spec.add_dependency 'i18n'
|
26
|
+
spec.add_dependency 'activesupport'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
29
|
+
spec.add_development_dependency 'rake'
|
30
|
+
spec.add_development_dependency 'rspec'
|
31
|
+
spec.add_development_dependency 'pry'
|
23
32
|
end
|
data/lib/formulaic.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'active_support/time_with_zone'
|
2
|
+
|
3
|
+
module Formulaic
|
4
|
+
class Form
|
5
|
+
ATTRIBUTE_INPUT_MAP = {
|
6
|
+
ActiveSupport::TimeWithZone => Formulaic::Inputs::DateInput,
|
7
|
+
Date => Formulaic::Inputs::DateInput,
|
8
|
+
Array => Formulaic::Inputs::ArrayInput,
|
9
|
+
String => Formulaic::Inputs::StringInput,
|
10
|
+
TrueClass => Formulaic::Inputs::BooleanInput,
|
11
|
+
FalseClass => Formulaic::Inputs::BooleanInput,
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def initialize(model_name, attributes)
|
15
|
+
@inputs = build_inputs(model_name, attributes)
|
16
|
+
@session = session
|
17
|
+
end
|
18
|
+
|
19
|
+
def fill
|
20
|
+
@inputs.each { |input| input.fill }
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :session, :model_name, :inputs
|
26
|
+
|
27
|
+
def build_inputs(model_name, attributes)
|
28
|
+
attributes.map do |field, value|
|
29
|
+
build_input(model_name, field, value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_input(model_name, field, value)
|
34
|
+
input_class_for(value).new(model_name, field, value)
|
35
|
+
end
|
36
|
+
|
37
|
+
def input_class_for(value)
|
38
|
+
ATTRIBUTE_INPUT_MAP.fetch(value.class) do
|
39
|
+
raise InvalidAttributeTypeError.new("Formulaic does not know how to fill in a #{value.class} value")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class InvalidAttributeTypeError < StandardError; end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Formulaic
|
2
|
+
module Inputs
|
3
|
+
class DateInput < Input
|
4
|
+
def fill
|
5
|
+
select_date(value, from: input(model_name, field))
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def select_date(date, options)
|
11
|
+
field = find_field(options[:from].to_s)["id"].gsub(/_1i/, "")
|
12
|
+
select date.year.to_s, from: "#{field}_1i"
|
13
|
+
select Date::MONTHNAMES[date.month], from: "#{field}_2i"
|
14
|
+
select date.day.to_s, from: "#{field}_3i"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
require 'capybara/dsl'
|
3
|
+
|
4
|
+
module Formulaic
|
5
|
+
module Inputs
|
6
|
+
class Input
|
7
|
+
include Capybara::DSL
|
8
|
+
|
9
|
+
def initialize(model_name, field, value)
|
10
|
+
@model_name = model_name
|
11
|
+
@field = field
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def input(model_name, field, action = :create)
|
18
|
+
Label.new(model_name, field, action).to_str
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :model_name, :field, :value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Formulaic
|
2
|
+
module Inputs
|
3
|
+
class StringInput < Input
|
4
|
+
def fill
|
5
|
+
if %w(text email password textarea).any? { |type| page.has_field?(input_text, type: type) }
|
6
|
+
fill_in(input_text, with: value)
|
7
|
+
elsif page.has_field?(input_text, type: 'radio')
|
8
|
+
choose(value)
|
9
|
+
else
|
10
|
+
select(value, from: input_text)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def input_text
|
15
|
+
@input_text ||= input(model_name, field)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Formulaic
|
2
|
+
class Label
|
3
|
+
def initialize(model_name, attribute, action = :create)
|
4
|
+
@model_name = model_name
|
5
|
+
@attribute = attribute
|
6
|
+
@action = action
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_str
|
10
|
+
if attribute.is_a?(String)
|
11
|
+
attribute
|
12
|
+
else
|
13
|
+
translate || human_attribute_name || attribute.to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
alias_method :to_s, :to_str
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :model_name, :attribute, :action
|
21
|
+
|
22
|
+
def translate
|
23
|
+
I18n.t(lookup_paths.first, scope: :'simple_form.labels', default: lookup_paths).presence
|
24
|
+
end
|
25
|
+
|
26
|
+
def human_attribute_name
|
27
|
+
if class_exists?(model_name.to_s.classify)
|
28
|
+
model_class = model_name.to_s.classify.constantize
|
29
|
+
if model_class.respond_to?(:human_attribute_name)
|
30
|
+
model_class.human_attribute_name(attribute.to_s)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def lookup_paths
|
36
|
+
[
|
37
|
+
:"#{model_name}.#{action}.#{attribute}",
|
38
|
+
:"#{model_name}.#{attribute}",
|
39
|
+
:"defaults.#{action}.#{attribute}",
|
40
|
+
:"defaults.#{attribute}",
|
41
|
+
'',
|
42
|
+
]
|
43
|
+
end
|
44
|
+
|
45
|
+
def class_exists?(class_name)
|
46
|
+
Object.const_defined?(model_name.to_s.classify)
|
47
|
+
rescue NameError
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Fill in user form' do
|
4
|
+
|
5
|
+
before(:all) { load_translations }
|
6
|
+
|
7
|
+
it 'finds and fills text fields' do
|
8
|
+
visit 'user_form'
|
9
|
+
form = Formulaic::Form.new(:user, name: 'George')
|
10
|
+
|
11
|
+
form.fill
|
12
|
+
|
13
|
+
expect(input(:user, :name).value).to eq 'George'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'finds and fills a password field' do
|
17
|
+
visit 'user_form'
|
18
|
+
form = Formulaic::Form.new(:user, password: 'supersecr3t')
|
19
|
+
|
20
|
+
form.fill
|
21
|
+
|
22
|
+
expect(input(:user, :password).value).to eq 'supersecr3t'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'finds and fills a textarea' do
|
26
|
+
visit 'user_form'
|
27
|
+
form = Formulaic::Form.new(:user, bio: 'blah blah blah')
|
28
|
+
|
29
|
+
form.fill
|
30
|
+
|
31
|
+
expect(input(:user, :bio).value).to eq 'blah blah blah'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'finds and fills a date field' do
|
35
|
+
visit 'user_form'
|
36
|
+
form = Formulaic::Form.new(:user, date_of_birth: Date.new(1980, 1, 2))
|
37
|
+
|
38
|
+
form.fill
|
39
|
+
|
40
|
+
expect(page.find('#user_date_of_birth_1i').value).to eq('1980')
|
41
|
+
expect(page.find('#user_date_of_birth_2i').value).to eq('1')
|
42
|
+
expect(page.find('#user_date_of_birth_3i').value).to eq('2')
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'finds and checks a boolean field' do
|
46
|
+
visit 'user_form'
|
47
|
+
form = Formulaic::Form.new(:user, terms_of_service: true)
|
48
|
+
|
49
|
+
form.fill
|
50
|
+
|
51
|
+
expect(input(:user, :terms_of_service)).to be_checked
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'selects a string if there is no input' do
|
55
|
+
visit 'user_form'
|
56
|
+
form = Formulaic::Form.new(:user, awesome: 'Yes')
|
57
|
+
|
58
|
+
form.fill
|
59
|
+
|
60
|
+
expect(page).to have_select('user_awesome', selected: 'Yes')
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
<form accept-charset="UTF-8" action="/users" class="simple_form new_user" id="new_user" method="post" novalidate="novalidate">
|
2
|
+
<div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"><input name="authenticity_token" type="hidden" value="O6ORla31JvEaWroCuiA7bArM15ztDotMfPAbNW0v61g="></div>
|
3
|
+
<div class="input string required user_name"><label class="string required" for="user_name"><abbr title="required">*</abbr> Display name</label><input class="string required" id="user_name" maxlength="255" name="user[name]" size="50" type="text"></div>
|
4
|
+
<div class="input email required user_email"><label class="email required" for="user_email"><abbr title="required">*</abbr> Email</label><input class="string email required" id="user_email" maxlength="255" name="user[email]" size="50" type="email"></div>
|
5
|
+
<div class="input password optional user_password"><label class="password optional" for="user_password">Password</label><input class="password optional" id="user_password" name="user[password]" size="50" type="password"></div>
|
6
|
+
<div class="input select required user_awesome">
|
7
|
+
<label class="select required" for="user_awesome"><abbr title="required">*</abbr> Are you awesome?</label>
|
8
|
+
<select class="select required" id="user_awesome" name="user[awesome]">
|
9
|
+
<option value=""></option>
|
10
|
+
<option value="true">Yes</option>
|
11
|
+
<option value="false">No</option>
|
12
|
+
</select>
|
13
|
+
</div>
|
14
|
+
<div class="input text required user_bio"><label class="text required" for="user_bio"><abbr title="required">*</abbr> Biography</label><textarea class="text required" cols="40" id="user_bio" name="user[bio]" rows="20" style="overflow: hidden; word-wrap: break-word; resize: horizontal; height: 464px;"></textarea></div>
|
15
|
+
<div class="input date required user_date_of_birth">
|
16
|
+
<label class="date required" for="user_date_of_birth_1i"><abbr title="required">*</abbr> Date of birth</label>
|
17
|
+
<select class="date required" id="user_date_of_birth_1i" name="user[date_of_birth(1i)]">
|
18
|
+
<option value="2001">2001</option>
|
19
|
+
<option value="2000">2000</option>
|
20
|
+
<option value="1999">1999</option>
|
21
|
+
<option value="1998">1998</option>
|
22
|
+
<option value="1997">1997</option>
|
23
|
+
<option value="1996">1996</option>
|
24
|
+
<option value="1995">1995</option>
|
25
|
+
<option value="1994">1994</option>
|
26
|
+
<option value="1993">1993</option>
|
27
|
+
<option value="1992">1992</option>
|
28
|
+
<option value="1991">1991</option>
|
29
|
+
<option value="1990">1990</option>
|
30
|
+
<option value="1989">1989</option>
|
31
|
+
<option value="1988">1988</option>
|
32
|
+
<option value="1987">1987</option>
|
33
|
+
<option value="1986">1986</option>
|
34
|
+
<option value="1985">1985</option>
|
35
|
+
<option value="1984">1984</option>
|
36
|
+
<option value="1983">1983</option>
|
37
|
+
<option value="1982">1982</option>
|
38
|
+
<option value="1981">1981</option>
|
39
|
+
<option value="1980">1980</option>
|
40
|
+
<option value="1979">1979</option>
|
41
|
+
<option value="1978">1978</option>
|
42
|
+
<option value="1977">1977</option>
|
43
|
+
<option value="1976">1976</option>
|
44
|
+
<option value="1975">1975</option>
|
45
|
+
<option value="1974">1974</option>
|
46
|
+
<option value="1973">1973</option>
|
47
|
+
<option value="1972">1972</option>
|
48
|
+
<option value="1971">1971</option>
|
49
|
+
<option value="1970">1970</option>
|
50
|
+
<option value="1969">1969</option>
|
51
|
+
<option value="1968">1968</option>
|
52
|
+
<option value="1967">1967</option>
|
53
|
+
<option value="1966">1966</option>
|
54
|
+
<option value="1965">1965</option>
|
55
|
+
<option value="1964">1964</option>
|
56
|
+
<option value="1963">1963</option>
|
57
|
+
<option value="1962">1962</option>
|
58
|
+
<option value="1961">1961</option>
|
59
|
+
<option value="1960">1960</option>
|
60
|
+
<option value="1959">1959</option>
|
61
|
+
<option value="1958">1958</option>
|
62
|
+
<option value="1957">1957</option>
|
63
|
+
<option value="1956">1956</option>
|
64
|
+
<option value="1955">1955</option>
|
65
|
+
<option value="1954">1954</option>
|
66
|
+
<option value="1953">1953</option>
|
67
|
+
<option value="1952">1952</option>
|
68
|
+
<option value="1951">1951</option>
|
69
|
+
<option value="1950">1950</option>
|
70
|
+
<option value="1949">1949</option>
|
71
|
+
<option value="1948">1948</option>
|
72
|
+
<option value="1947">1947</option>
|
73
|
+
<option value="1946">1946</option>
|
74
|
+
<option value="1945">1945</option>
|
75
|
+
<option value="1944">1944</option>
|
76
|
+
<option value="1943">1943</option>
|
77
|
+
<option value="1942">1942</option>
|
78
|
+
<option value="1941">1941</option>
|
79
|
+
<option value="1940">1940</option>
|
80
|
+
<option value="1939">1939</option>
|
81
|
+
<option value="1938">1938</option>
|
82
|
+
<option value="1937">1937</option>
|
83
|
+
<option value="1936">1936</option>
|
84
|
+
<option value="1935">1935</option>
|
85
|
+
<option value="1934">1934</option>
|
86
|
+
<option value="1933">1933</option>
|
87
|
+
<option value="1932">1932</option>
|
88
|
+
<option value="1931">1931</option>
|
89
|
+
<option value="1930">1930</option>
|
90
|
+
<option value="1929">1929</option>
|
91
|
+
<option value="1928">1928</option>
|
92
|
+
<option value="1927">1927</option>
|
93
|
+
<option value="1926">1926</option>
|
94
|
+
<option value="1925">1925</option>
|
95
|
+
<option value="1924">1924</option>
|
96
|
+
<option value="1923">1923</option>
|
97
|
+
<option value="1922">1922</option>
|
98
|
+
<option value="1921">1921</option>
|
99
|
+
<option value="1920">1920</option>
|
100
|
+
<option value="1919">1919</option>
|
101
|
+
<option value="1918">1918</option>
|
102
|
+
<option value="1917">1917</option>
|
103
|
+
<option value="1916">1916</option>
|
104
|
+
<option value="1915">1915</option>
|
105
|
+
<option value="1914">1914</option>
|
106
|
+
<option value="1913">1913</option>
|
107
|
+
<option value="1912">1912</option>
|
108
|
+
<option value="1911">1911</option>
|
109
|
+
<option value="1910">1910</option>
|
110
|
+
<option value="1909">1909</option>
|
111
|
+
<option value="1908">1908</option>
|
112
|
+
<option value="1907">1907</option>
|
113
|
+
<option value="1906">1906</option>
|
114
|
+
<option value="1905">1905</option>
|
115
|
+
<option value="1904">1904</option>
|
116
|
+
<option value="1903">1903</option>
|
117
|
+
<option value="1902">1902</option>
|
118
|
+
<option value="1901">1901</option>
|
119
|
+
<option value="1900">1900</option>
|
120
|
+
</select>
|
121
|
+
<select class="date required" id="user_date_of_birth_2i" name="user[date_of_birth(2i)]">
|
122
|
+
<option value="1">January</option>
|
123
|
+
<option value="2">February</option>
|
124
|
+
<option value="3">March</option>
|
125
|
+
<option value="4">April</option>
|
126
|
+
<option value="5">May</option>
|
127
|
+
<option selected="selected" value="6">June</option>
|
128
|
+
<option value="7">July</option>
|
129
|
+
<option value="8">August</option>
|
130
|
+
<option value="9">September</option>
|
131
|
+
<option value="10">October</option>
|
132
|
+
<option value="11">November</option>
|
133
|
+
<option value="12">December</option>
|
134
|
+
</select>
|
135
|
+
<select class="date required" id="user_date_of_birth_3i" name="user[date_of_birth(3i)]">
|
136
|
+
<option value="1">1</option>
|
137
|
+
<option value="2">2</option>
|
138
|
+
<option value="3">3</option>
|
139
|
+
<option value="4">4</option>
|
140
|
+
<option value="5">5</option>
|
141
|
+
<option value="6">6</option>
|
142
|
+
<option selected="selected" value="7">7</option>
|
143
|
+
<option value="8">8</option>
|
144
|
+
<option value="9">9</option>
|
145
|
+
<option value="10">10</option>
|
146
|
+
<option value="11">11</option>
|
147
|
+
<option value="12">12</option>
|
148
|
+
<option value="13">13</option>
|
149
|
+
<option value="14">14</option>
|
150
|
+
<option value="15">15</option>
|
151
|
+
<option value="16">16</option>
|
152
|
+
<option value="17">17</option>
|
153
|
+
<option value="18">18</option>
|
154
|
+
<option value="19">19</option>
|
155
|
+
<option value="20">20</option>
|
156
|
+
<option value="21">21</option>
|
157
|
+
<option value="22">22</option>
|
158
|
+
<option value="23">23</option>
|
159
|
+
<option value="24">24</option>
|
160
|
+
<option value="25">25</option>
|
161
|
+
<option value="26">26</option>
|
162
|
+
<option value="27">27</option>
|
163
|
+
<option value="28">28</option>
|
164
|
+
<option value="29">29</option>
|
165
|
+
<option value="30">30</option>
|
166
|
+
<option value="31">31</option>
|
167
|
+
</select>
|
168
|
+
</div>
|
169
|
+
<div class="input boolean required user_terms_of_service"><input name="user[terms_of_service]" type="hidden" value="0"><input class="boolean required" id="user_terms_of_service" name="user[terms_of_service]" type="checkbox" value="1"><label class="boolean required" for="user_terms_of_service"><abbr title="required">*</abbr> I agree to the Terms of Service</label></div>
|
170
|
+
<input name="commit" type="submit" value="Register">
|
171
|
+
</form>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Formulaic::Dsl do
|
4
|
+
it 'responds to input' do
|
5
|
+
expect(object_with_dsl).to respond_to(:input)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'responds to fill_form' do
|
9
|
+
expect(object_with_dsl).to respond_to(:fill_form)
|
10
|
+
end
|
11
|
+
|
12
|
+
def object_with_dsl
|
13
|
+
@object_with_dsl ||= Class.new do
|
14
|
+
include Formulaic::Dsl
|
15
|
+
end.new
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Formulaic::Label do
|
4
|
+
it 'returns the string if there are no translations and it can not human_attribute_name the class' do
|
5
|
+
expect(label(nil, 'My label')).to eq 'My label'
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'returns human_attribute_name if available' do
|
9
|
+
expect(label(:user, :attribute)).to eq 'Human Attribute Name'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'uses a translation if available' do
|
13
|
+
I18n.backend.store_translations(:en, { simple_form: { labels: { user: { name: 'Translated' } } } } )
|
14
|
+
|
15
|
+
expect(label(:user, :name)).to eq('Translated')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should leave cases alone' do
|
19
|
+
expect(label(:user, 'Work URL')).to eq 'Work URL'
|
20
|
+
end
|
21
|
+
|
22
|
+
def label(model_name, attribute, action = :create)
|
23
|
+
Formulaic::Label.new(model_name, attribute, action).to_str
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class User
|
28
|
+
def self.human_attribute_name(*)
|
29
|
+
'Human Attribute Name'
|
30
|
+
end
|
31
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'formulaic'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
module SpecHelper
|
5
|
+
def input(model, field)
|
6
|
+
page.find("##{model}_#{field}")
|
7
|
+
end
|
8
|
+
|
9
|
+
def visit(page_name)
|
10
|
+
page.visit("/#{page_name}.html")
|
11
|
+
end
|
12
|
+
|
13
|
+
def page
|
14
|
+
@page ||= begin
|
15
|
+
Capybara.app = Rack::File.new(File.expand_path('../fixtures', __FILE__))
|
16
|
+
Capybara.current_session
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def load_translations
|
21
|
+
I18n.backend.store_translations(:en, YAML.load(<<-TRANSLATIONS))
|
22
|
+
simple_form:
|
23
|
+
labels:
|
24
|
+
user:
|
25
|
+
name: Display name
|
26
|
+
email: Email
|
27
|
+
password: Password
|
28
|
+
date_of_birth: Date of birth
|
29
|
+
terms_of_service: I agree to the Terms of Service
|
30
|
+
awesome: Are you awesome?
|
31
|
+
bio: Biography
|
32
|
+
TRANSLATIONS
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
RSpec.configure do |c|
|
37
|
+
c.include SpecHelper
|
38
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: formulaic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Caleb Thompson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: capybara
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: i18n
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
13
55
|
- !ruby/object:Gem::Dependency
|
14
56
|
name: bundler
|
15
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,22 +80,71 @@ dependencies:
|
|
38
80
|
- - '>='
|
39
81
|
- !ruby/object:Gem::Version
|
40
82
|
version: '0'
|
41
|
-
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: |
|
112
|
+
Removes the tedium of formulaic form filling with Capybara by allowing you
|
113
|
+
to specify a hash of attributes to be input rather than procedurally calling
|
114
|
+
Capybara’s DSL methods.
|
42
115
|
email:
|
43
|
-
-
|
116
|
+
- caleb@calebthompson.io
|
44
117
|
executables: []
|
45
118
|
extensions: []
|
46
119
|
extra_rdoc_files: []
|
47
120
|
files:
|
48
121
|
- .gitignore
|
122
|
+
- .ruby-gemset
|
123
|
+
- .ruby-version
|
124
|
+
- CONTRIBUTING.md
|
49
125
|
- Gemfile
|
50
|
-
- LICENSE
|
126
|
+
- LICENSE
|
51
127
|
- README.md
|
52
128
|
- Rakefile
|
53
129
|
- formulaic.gemspec
|
54
|
-
- lib/
|
55
|
-
- lib/
|
56
|
-
|
130
|
+
- lib/formulaic.rb
|
131
|
+
- lib/formulaic/dsl.rb
|
132
|
+
- lib/formulaic/form.rb
|
133
|
+
- lib/formulaic/inputs.rb
|
134
|
+
- lib/formulaic/inputs/array_input.rb
|
135
|
+
- lib/formulaic/inputs/boolean_input.rb
|
136
|
+
- lib/formulaic/inputs/date_input.rb
|
137
|
+
- lib/formulaic/inputs/input.rb
|
138
|
+
- lib/formulaic/inputs/string_input.rb
|
139
|
+
- lib/formulaic/label.rb
|
140
|
+
- lib/formulaic/version.rb
|
141
|
+
- spec/features/fill_in_user_form_spec.rb
|
142
|
+
- spec/fixtures/user_form.html
|
143
|
+
- spec/formulaic/dsl_spec.rb
|
144
|
+
- spec/formulaic/form_spec.rb
|
145
|
+
- spec/formulaic/label_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
homepage: https://github.com/thoughtbot/formulaic
|
57
148
|
licenses:
|
58
149
|
- MIT
|
59
150
|
metadata: {}
|
@@ -76,5 +167,11 @@ rubyforge_project:
|
|
76
167
|
rubygems_version: 2.0.3
|
77
168
|
signing_key:
|
78
169
|
specification_version: 4
|
79
|
-
summary:
|
80
|
-
test_files:
|
170
|
+
summary: Simplify form filling with Capybara
|
171
|
+
test_files:
|
172
|
+
- spec/features/fill_in_user_form_spec.rb
|
173
|
+
- spec/fixtures/user_form.html
|
174
|
+
- spec/formulaic/dsl_spec.rb
|
175
|
+
- spec/formulaic/form_spec.rb
|
176
|
+
- spec/formulaic/label_spec.rb
|
177
|
+
- spec/spec_helper.rb
|
data/lib/formualic.rb
DELETED
data/lib/formualic/version.rb
DELETED