formulaic 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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