formulaic 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 402a37df86e5dd8b34b2aa265b27ebf777ef2a15
4
- data.tar.gz: 85085a9bbf8b9a4e575c0cc0cac2d880210f61a6
3
+ metadata.gz: 46041f49475675c4e48824b44f5a4825f1e0a2c6
4
+ data.tar.gz: 5ff5c7da932bbad514632342cf19f84a45778b38
5
5
  SHA512:
6
- metadata.gz: bbb668c73e63d172e8769f7a5f4e63db0cacb478d02f0210365cab04c872e3705f82e22b5713d295a36c77fca4ab756887a910f435b065f2a98876aacb5bbe8d
7
- data.tar.gz: dc8a724475b8548eb3bf414c1f859558a67e63f809003156f1050fae839be484a1762130c1db066a39fb3995dcfb256800b2e16a7eac04cd8d61229ddc0691e8
6
+ metadata.gz: 07e7b143f6ef68deedac88596f213d42dee31ce1b84079dc1855ee33c8eb554babae2742ee3fc65be8f85996c9a8b310bcc628a3385b529ef4fbdc09d53f44d3
7
+ data.tar.gz: f0efb3b62c2580f2fcad9618b1d59e77fd2872ce22f7884d0fbd7b283b9e9732f3f4b2ab43d27cfcf934aef0e42133f3c129bf190262124df582144833aa1451
data/README.md CHANGED
@@ -150,7 +150,7 @@ around `I18n.t`.
150
150
  | `Date`, `ActiveSupport::TimeWithZone` | `select` year, month, and day |
151
151
  | `TrueClass` | `check` |
152
152
  | `FalseClass` | `uncheck` |
153
- | `Array` | `check` each array member, which should all be strings |
153
+ | `Array` | `check` or `select` each array member, which should all be strings. If not all items can be selected or checked, an error will be thrown.|
154
154
  | `File` | `attach_file` with `File#path` |
155
155
 
156
156
  * Formulaic is currently tied to `simple_form` translations and field structure.
@@ -1,9 +1,40 @@
1
1
  module Formulaic
2
2
  module Inputs
3
3
  class ArrayInput < Input
4
+ def initialize(label, value)
5
+ @label = label
6
+ @value = value
7
+ end
8
+
4
9
  def fill
5
- value.each { |checkbox| check checkbox }
10
+ attempt_to_fill_selects ||
11
+ attempt_to_fill_checkboxes ||
12
+ raise_input_error
13
+ end
14
+
15
+ private
16
+
17
+ def attempt_to_fill_selects
18
+ SelectInput.new(label, value).fill
19
+ end
20
+
21
+ def attempt_to_fill_checkboxes
22
+ CheckboxInput.new(label, value).fill
23
+ end
24
+
25
+ def contains_all_options?(nodes)
26
+ nodes.map(&:text).to_set.superset?(value.to_set)
27
+ end
28
+
29
+ def raise_input_error
30
+ raise(
31
+ InputNotFound,
32
+ %[Unable to find checkboxes or select[multiple] "#{label}" containing all options #{value.inspect}.]
33
+ )
6
34
  end
7
35
  end
8
36
  end
9
37
  end
38
+
39
+ require 'formulaic/inputs/checkbox_input'
40
+ require 'formulaic/inputs/select_input'
@@ -0,0 +1,36 @@
1
+ module Formulaic
2
+ module Inputs
3
+ class CheckboxInput < ArrayInput
4
+ def fill
5
+ if has_check_boxes?
6
+ check_boxes
7
+ true
8
+ else
9
+ false
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def has_check_boxes?
16
+ contains_all_options?(checkbox_labels)
17
+ end
18
+
19
+ def check_boxes
20
+ value.each { |checkbox| check checkbox }
21
+ end
22
+
23
+ def checkbox_labels
24
+ all(checkbox_labels_selector)
25
+ end
26
+
27
+ def checkbox_name_selector
28
+ "input[type='checkbox'][name='#{label.model_name}[#{label.attribute}][]']"
29
+ end
30
+
31
+ def checkbox_labels_selector
32
+ "#{checkbox_name_selector} ~ label,label:has(#{checkbox_name_selector})"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ module Formulaic
2
+ module Inputs
3
+ class SelectInput < ArrayInput
4
+ def fill
5
+ if has_multiple_select?
6
+ select_options
7
+ true
8
+ else
9
+ false
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def select_options
16
+ value.each { |option| select option, from: label.to_str }
17
+ end
18
+
19
+ def has_multiple_select?
20
+ has_select? && select_is_multiple?
21
+ end
22
+
23
+ def has_select?
24
+ has_field?(label, type: "select")
25
+ end
26
+
27
+ def select_is_multiple?
28
+ select_element[:multiple].present? &&
29
+ contains_all_options?(select_element.all("option"))
30
+ end
31
+
32
+ def select_element
33
+ @select_element ||= find_field(label, type: "select")
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,5 +1,7 @@
1
1
  module Formulaic
2
2
  class Label
3
+ attr_reader :model_name, :attribute, :action
4
+
3
5
  def initialize(model_name, attribute, action)
4
6
  @model_name = model_name
5
7
  @attribute = attribute
@@ -17,8 +19,6 @@ module Formulaic
17
19
 
18
20
  private
19
21
 
20
- attr_reader :model_name, :attribute, :action
21
-
22
22
  def translate
23
23
  I18n.t(lookup_paths.first, scope: :'simple_form.labels', default: lookup_paths).presence
24
24
  end
@@ -1,3 +1,3 @@
1
1
  module Formulaic
2
- VERSION = '0.1.1'
2
+ VERSION = '0.1.2'
3
3
  end
@@ -88,6 +88,58 @@ describe 'Fill in user form' do
88
88
  expect(input(:user, :age).value).to eq '10'
89
89
  end
90
90
 
91
+ it 'raises a useful error if selecting multiple from a normal select' do
92
+ visit 'user_form'
93
+ form = Formulaic::Form.new(:user, :new, awesome: ['Yes', 'No'])
94
+
95
+ expect { form.fill }
96
+ .to raise_error(
97
+ Formulaic::InputNotFound,
98
+ 'Unable to find checkboxes or select[multiple] "Are you awesome?" containing all options ["Yes", "No"].'
99
+ )
100
+ end
101
+
102
+ it 'raises a useful error if not all select options are present' do
103
+ visit 'user_form'
104
+ form = Formulaic::Form.new(:user, :new, likes: ['Ruby', 'Perl'])
105
+
106
+ expect { form.fill }
107
+ .to raise_error(
108
+ Formulaic::InputNotFound,
109
+ 'Unable to find checkboxes or select[multiple] "Your Likes" containing all options ["Ruby", "Perl"].'
110
+ )
111
+ end
112
+
113
+ it 'selects an array of strings' do
114
+ visit 'user_form'
115
+ form = Formulaic::Form.new(:user, :new, likes: ['Ruby', 'Rails'])
116
+
117
+ form.fill
118
+
119
+ expect(input(:user, :likes).value).to eq ['ruby', 'rails']
120
+ end
121
+
122
+ it 'raises a useful error if not all checkboxes are present' do
123
+ visit 'user_form'
124
+ form = Formulaic::Form.new(:user, :new, dislikes: ['Java', 'Go'])
125
+
126
+ expect { form.fill }
127
+ .to raise_error(
128
+ Formulaic::InputNotFound,
129
+ 'Unable to find checkboxes or select[multiple] "Your Dislikes" containing all options ["Java", "Go"].'
130
+ )
131
+ end
132
+
133
+ it 'selects an array of checkboxes' do
134
+ visit 'user_form'
135
+ form = Formulaic::Form.new(:user, :new, dislikes: ['Java', 'PHP'])
136
+
137
+ form.fill
138
+
139
+ expect(page).to have_checked_field "Java"
140
+ expect(page).to have_checked_field "PHP"
141
+ end
142
+
91
143
  it 'selects a string if there is no input' do
92
144
  visit 'user_form'
93
145
  form = Formulaic::Form.new(:user, :new, awesome: 'Yes')
@@ -1,12 +1,17 @@
1
1
  <form accept-charset="UTF-8" action="/users" class="simple_form new_user" id="new_user" method="post" novalidate="novalidate">
2
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>
3
+ <div class="input string required user_name"><label class="string required"
4
+ for="user_name"><abbr title="required">*</abbr> Your Display name</label><input class="string required" id="user_name" maxlength="255" name="user[name]" size="50" type="text"></div>
5
+ <div class="input email required user_email"><label class="email required"
6
+ for="user_email"><abbr title="required">*</abbr> Your Email</label><input class="string email required" id="user_email" maxlength="255" name="user[email]" size="50" type="email"></div>
5
7
  <div class="input tel required user_phone"><label class="tel required" for="user_phone"><abbr title="required">*</abbr> Phone Number</label><input class="string phone required" id="user_phone" maxlength="255" name="user[phone]" size="50" type="tel"></div>
6
- <div class="input integer required user_age"><label class="integer required" for="user_age"><abbr title="required">*</abbr> Age</label><input class="numeric integer age required" id="user_age" maxlength="255" name="user[age]" size="50" type="number"></div>
8
+ <div class="input integer required user_age"><label class="integer required"
9
+ for="user_age"><abbr title="required">*</abbr> Your Age</label><input class="numeric integer age required" id="user_age" maxlength="255" name="user[age]" size="50" type="number"></div>
7
10
  <div class="input url required user_url"><label class="tel required" for="user_url"><abbr title="required">*</abbr> Website</label><input class="string url required" id="user_url" maxlength="255" name="user[url]" size="50" type="url"></div>
8
- <div class="input file optional user_avatar"><label class="file optional" for="user_avatar">Avatar</label><input class="file optional" id="user_avatar" name="user[avatar]" type="file" /></div>
9
- <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>
11
+ <div class="input file optional user_avatar"><label class="file optional"
12
+ for="user_avatar">Your Avatar</label><input class="file optional" id="user_avatar" name="user[avatar]" type="file" /></div>
13
+ <div class="input password optional user_password"><label class="password
14
+ optional" for="user_password">Your Password</label><input class="password optional" id="user_password" name="user[password]" size="50" type="password"></div>
10
15
  <div class="input select required user_awesome">
11
16
  <label class="select required" for="user_awesome"><abbr title="required">*</abbr> Are you awesome?</label>
12
17
  <select class="select required" id="user_awesome" name="user[awesome]">
@@ -15,9 +20,34 @@
15
20
  <option value="false">No</option>
16
21
  </select>
17
22
  </div>
18
- <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>
23
+ <div class="input select user_likes">
24
+ <label class="select" for="user_likes">Your Likes</label>
25
+ <select class="select" id="user_likes" name="user[likes][]" multiple>
26
+ <option value=""></option>
27
+ <option value="ruby">Ruby</option>
28
+ <option value="rails">Rails</option>
29
+ <option value="git">Git</option>
30
+ </select>
31
+ </div>
32
+ <div class="input check_boxes optional user_dislikes">
33
+ <label class="check_boxes optional">Your Dislikes</label>
34
+ <span class="checkbox">
35
+ <input class="check_boxes optional" id="user_dislikes_1" name="user[dislikes][]" type="checkbox" value="java">
36
+ <label class="collection_check_boxes" for="user_dislikes_1">Java</label>
37
+ </span>
38
+ <span class="checkbox">
39
+ <label class="collection_check_boxes" for="user_dislikes_2">
40
+ PHP
41
+ <input class="check_boxes optional" id="user_dislikes_2" name="user[dislikes][]" type="checkbox" value="php">
42
+ </label>
43
+ </span>
44
+ <input name="user[dislikes][]" type="hidden" value="">
45
+ </div>
46
+ <div class="input text required user_bio"><label class="text required"
47
+ for="user_bio"><abbr title="required">*</abbr> Your 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>
19
48
  <div class="input date required user_date_of_birth">
20
- <label class="date required" for="user_date_of_birth_1i"><abbr title="required">*</abbr> Date of birth</label>
49
+ <label class="date required" for="user_date_of_birth_1i"><abbr
50
+ title="required">*</abbr> Your Date of birth</label>
21
51
  <select class="date required" id="user_date_of_birth_1i" name="user[date_of_birth(1i)]">
22
52
  <option value="2001">2001</option>
23
53
  <option value="2000">2000</option>
@@ -21,15 +21,17 @@ module SpecHelper
21
21
  simple_form:
22
22
  labels:
23
23
  user:
24
- age: Age
25
- avatar: Avatar
24
+ age: Your Age
25
+ avatar: Your Avatar
26
26
  awesome: Are you awesome?
27
27
  bio: Biography
28
- date_of_birth: Date of birth
29
- email: Email
30
- name: Display name
28
+ date_of_birth: Your Date of birth
29
+ likes: Your Likes
30
+ dislikes: Your Dislikes
31
+ email: Your Email
32
+ name: Your Display name
31
33
  new:
32
- password: Password
34
+ password: Your Password
33
35
  phone: Phone Number
34
36
  terms_of_service: I agree to the Terms of Service
35
37
  url: Website
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: formulaic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Caleb Thompson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-25 00:00:00.000000000 Z
11
+ date: 2014-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -136,9 +136,11 @@ files:
136
136
  - lib/formulaic/inputs.rb
137
137
  - lib/formulaic/inputs/array_input.rb
138
138
  - lib/formulaic/inputs/boolean_input.rb
139
+ - lib/formulaic/inputs/checkbox_input.rb
139
140
  - lib/formulaic/inputs/date_input.rb
140
141
  - lib/formulaic/inputs/file_input.rb
141
142
  - lib/formulaic/inputs/input.rb
143
+ - lib/formulaic/inputs/select_input.rb
142
144
  - lib/formulaic/inputs/string_input.rb
143
145
  - lib/formulaic/label.rb
144
146
  - lib/formulaic/version.rb