formulary 0.0.1 → 0.0.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.
Files changed (34) hide show
  1. data/README.md +50 -6
  2. data/formulary.gemspec +1 -0
  3. data/lib/formulary.rb +13 -0
  4. data/lib/formulary/html_form.rb +39 -58
  5. data/lib/formulary/html_form/fields.rb +21 -0
  6. data/lib/formulary/html_form/fields/checkbox_group.rb +43 -0
  7. data/lib/formulary/html_form/fields/email_input.rb +23 -0
  8. data/lib/formulary/html_form/fields/field.rb +45 -0
  9. data/lib/formulary/html_form/fields/field_group.rb +26 -0
  10. data/lib/formulary/html_form/fields/hidden_input.rb +7 -0
  11. data/lib/formulary/html_form/fields/input.rb +32 -0
  12. data/lib/formulary/html_form/fields/radio_button_group.rb +29 -0
  13. data/lib/formulary/html_form/fields/select.rb +24 -0
  14. data/lib/formulary/html_form/fields/tel_input.rb +7 -0
  15. data/lib/formulary/html_form/fields/text_input.rb +7 -0
  16. data/lib/formulary/html_form/fields/textarea.rb +12 -0
  17. data/lib/formulary/version.rb +1 -1
  18. data/spec/html_form/fields/checkbox_group_spec.rb +141 -0
  19. data/spec/html_form/fields/email_input_spec.rb +55 -0
  20. data/spec/html_form/fields/field_spec.rb +10 -0
  21. data/spec/html_form/fields/hidden_input_spec.rb +37 -0
  22. data/spec/html_form/fields/input_spec.rb +17 -0
  23. data/spec/html_form/fields/radio_button_group_spec.rb +94 -0
  24. data/spec/html_form/fields/select_spec.rb +62 -0
  25. data/spec/html_form/fields/tel_input_spec.rb +29 -0
  26. data/spec/html_form/fields/text_input_spec.rb +29 -0
  27. data/spec/html_form/fields/textarea_spec.rb +28 -0
  28. data/spec/html_form_spec.rb +53 -109
  29. data/spec/spec_helper.rb +5 -10
  30. data/spec/support/element_helper.rb +15 -0
  31. data/spec/support/shared_examples_for_pattern.rb +15 -0
  32. data/spec/support/shared_examples_for_required.rb +35 -0
  33. metadata +149 -94
  34. checksums.yaml +0 -7
@@ -0,0 +1,29 @@
1
+ module Formulary::HtmlForm::Fields
2
+ class RadioButtonGroup < FieldGroup
3
+ def self.compatible_type
4
+ "radio"
5
+ end
6
+
7
+ def self.supports_required?
8
+ true
9
+ end
10
+
11
+ protected
12
+
13
+ def required?
14
+ @elements.any? { |e| e.attributes.include?("required") }
15
+ end
16
+
17
+ def value_in_list?
18
+ return true if @value.blank?
19
+ valid_values.include?(@value)
20
+ end
21
+
22
+ def valid_values
23
+ @valid_values ||= \
24
+ @elements.map do |element|
25
+ element.attributes["value"].value
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ module Formulary::HtmlForm::Fields
2
+ class Select < Field
3
+ def self.compatible_with?(element)
4
+ element.name == "select"
5
+ end
6
+
7
+ def valid?
8
+ valid_values.include?(@value)
9
+ end
10
+
11
+ def error
12
+ return "choose" unless valid?
13
+ end
14
+
15
+ protected
16
+
17
+ def valid_values
18
+ @valid_values ||= \
19
+ @element.css("option").map do |option|
20
+ option["value"] ? option["value"] : option.text
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ module Formulary::HtmlForm::Fields
2
+ class TelInput < Input
3
+ def self.compatible_type
4
+ "tel"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Formulary::HtmlForm::Fields
2
+ class TextInput < Input
3
+ def self.compatible_type
4
+ "text"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Formulary::HtmlForm::Fields
2
+ class Textarea < Field
3
+ def self.compatible_with?(element)
4
+ element.name == "textarea"
5
+ end
6
+
7
+ def self.supports_required?
8
+ true
9
+ end
10
+ end
11
+ end
12
+
@@ -1,3 +1,3 @@
1
1
  module Formulary
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,141 @@
1
+ require 'spec_helper'
2
+
3
+ describe Formulary::HtmlForm::Fields::CheckboxGroup do
4
+ describe ".compatible_with?" do
5
+ subject { Formulary::HtmlForm::Fields::CheckboxGroup.compatible_with?(elements) }
6
+
7
+ context "with checkboxen" do
8
+ let(:markup) do
9
+ %{
10
+ <input type="checkbox" name="field" value="one">
11
+ <input type="checkbox" name="field" value="two">
12
+ }
13
+ end
14
+
15
+ it { should be_true }
16
+ end
17
+
18
+ context "with radio buttons" do
19
+ let(:markup) do
20
+ %{
21
+ <input type="radio" name="field" value="one">
22
+ <input type="radio" name="field" value="two">
23
+ }
24
+ end
25
+
26
+ it { should be_false }
27
+ end
28
+
29
+ context "with a sweet mix of the two" do
30
+ let(:markup) do
31
+ %{
32
+ <input type="checkbox" name="field" value="one">
33
+ <input type="radio" name="field" value="two">
34
+ }
35
+ end
36
+ it { should be_false }
37
+
38
+ end
39
+ end
40
+
41
+ describe "validations" do
42
+ subject(:checkbox_group) do
43
+ Formulary::HtmlForm::Fields::CheckboxGroup.new("food", elements)
44
+ end
45
+
46
+ context "when one of the items in the group is required" do
47
+ let(:markup) do
48
+ %{
49
+ <input type="checkbox" name="field" value="first" required>
50
+ <input type="checkbox" name="field" value="second">
51
+ }
52
+ end
53
+
54
+ context "with the required item" do
55
+ before { checkbox_group.set_value("first") }
56
+
57
+ it { should be_valid }
58
+ its(:error) { should be_blank }
59
+ end
60
+
61
+ context "with required and non-required items" do
62
+ before { checkbox_group.set_value(["first","second"]) }
63
+
64
+ it { should be_valid }
65
+ its(:error) { should be_blank }
66
+ end
67
+
68
+ context "with a non-required item" do
69
+ before { checkbox_group.set_value("second") }
70
+
71
+ it { should_not be_valid }
72
+ its(:error) { should include("required") }
73
+ end
74
+
75
+ context "with a value that isn't expected" do
76
+ before { checkbox_group.set_value([ "first", "invalid" ]) }
77
+
78
+ it { should_not be_valid }
79
+ its(:error) { should include("choose") }
80
+ end
81
+
82
+ context "with no value" do
83
+ it { should_not be_valid }
84
+ its(:error) { should include("required") }
85
+ end
86
+ end
87
+
88
+ context "when none are required" do
89
+ let(:markup) do
90
+ %{
91
+ <input type="checkbox" name="field" value="first">
92
+ <input type="checkbox" name="field" value="second">
93
+ }
94
+ end
95
+
96
+ context "with a value that isn't expected" do
97
+ before { checkbox_group.set_value("invalid") }
98
+
99
+ it { should_not be_valid }
100
+ its(:error) { should include("choose") }
101
+ end
102
+
103
+ context "with no value" do
104
+ it { should be_valid }
105
+ its(:error) { should be_blank }
106
+ end
107
+
108
+ context "passed 'on' when all values are specified" do
109
+ before { checkbox_group.set_value("on") }
110
+
111
+ it { should_not be_valid }
112
+ its(:error) { should include("choose") }
113
+ end
114
+ end
115
+
116
+ context "when no value is specified in the markup" do
117
+ context "when it is required" do
118
+ let(:markup) { %{<input type="checkbox" name="field" required>} }
119
+
120
+ context "when it is checked" do
121
+ before { checkbox_group.set_value("on") }
122
+
123
+ it { should be_valid }
124
+ its(:error) { should be_blank }
125
+ end
126
+ end
127
+
128
+ context "when it is not required" do
129
+ let(:markup) { %{<input type="checkbox" name="field">} }
130
+
131
+
132
+ context "when it is checked" do
133
+ before { checkbox_group.set_value("on") }
134
+
135
+ it { should be_valid }
136
+ its(:error) { should be_blank }
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Formulary::HtmlForm::Fields::EmailInput do
4
+ describe ".compatible_with?" do
5
+ subject { Formulary::HtmlForm::Fields::EmailInput.compatible_with?(element) }
6
+ let(:markup) { %{<input type="#{type}" name="name" />} }
7
+
8
+ context "text type" do
9
+ let(:type) { "text" }
10
+ it { should be_false }
11
+ end
12
+
13
+ context "email type" do
14
+ let(:type) { "email" }
15
+ it { should be_true }
16
+ end
17
+ end
18
+
19
+ it_should_behave_like "a field that allows the required attribute" do
20
+ let(:markup_with_required) { %{<input type="email" name="field" required />} }
21
+ let(:markup_without_required) { %{<input type="email" name="field" />} }
22
+ let(:valid_value) { "test@example.com" }
23
+ end
24
+
25
+ it_should_behave_like "a field that allows the pattern attribute" do
26
+ let(:markup) { '<input type="email" name="field" pattern="@example\.com$" />' }
27
+ let(:valid_value) { "test@example.com" }
28
+ end
29
+
30
+ describe "validations" do
31
+ subject(:input) { Formulary::HtmlForm::Fields::EmailInput.new(element) }
32
+ let(:markup) { %{<input type="email" name="name" />} }
33
+
34
+ context "with a valid email address" do
35
+ before { input.set_value("test@example.com") }
36
+
37
+ it { should be_valid }
38
+ its(:error) { should be_blank }
39
+ end
40
+
41
+ context "with an invalid email address" do
42
+ before { input.set_value("invalid!") }
43
+
44
+ it { should_not be_valid }
45
+ its(:error) { should include("email") }
46
+ end
47
+
48
+ context "with a nil email address" do
49
+ before { input.set_value(nil) }
50
+
51
+ it { should be_valid }
52
+ its(:error) { should be_blank }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Formulary::HtmlForm::Fields::Field do
4
+ describe "#name" do
5
+ subject { Formulary::HtmlForm::Fields::Field.new(element).name }
6
+ let(:markup) { %{<input type="text" name="field" />} }
7
+
8
+ it { should eq("field") }
9
+ end
10
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Formulary::HtmlForm::Fields::HiddenInput do
4
+ describe ".compatible_with?" do
5
+ subject { Formulary::HtmlForm::Fields::HiddenInput.compatible_with?(element) }
6
+ let(:markup) { %{<input type="#{type}" name="name" />} }
7
+
8
+ context "text type" do
9
+ let(:type) { "text" }
10
+ it { should be_false }
11
+ end
12
+
13
+ context "hidden type" do
14
+ let(:type) { "hidden" }
15
+ it { should be_true }
16
+ end
17
+ end
18
+
19
+ describe "validations" do
20
+ subject(:input) { Formulary::HtmlForm::Fields::HiddenInput.new(element) }
21
+ let(:markup) { %{<input type="hidden" name="field"></input>} }
22
+
23
+ context "passed a value" do
24
+ before { input.set_value("test") }
25
+
26
+ it { should be_valid }
27
+ its(:error) { should be_blank }
28
+ end
29
+
30
+ context "passed no value" do
31
+ before { input.set_value("") }
32
+
33
+ it { should be_valid }
34
+ its(:error) { should be_blank }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Formulary::HtmlForm::Fields::Input do
4
+ describe ".compatible_with?" do
5
+ subject { Formulary::HtmlForm::Fields::EmailInput.compatible_with?(element) }
6
+
7
+ context "with a textarea" do
8
+ let(:markup) { %{<textarea name="name"></textarea>} }
9
+ it { should be_false }
10
+ end
11
+
12
+ context "with a select" do
13
+ let(:markup) { %{<select name="name"></select>} }
14
+ it { should be_false }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe Formulary::HtmlForm::Fields::RadioButtonGroup do
4
+ describe ".compatible_with?" do
5
+ subject { Formulary::HtmlForm::Fields::RadioButtonGroup.compatible_with?(elements) }
6
+
7
+ context "with checkboxen" do
8
+ let(:markup) do
9
+ %{
10
+ <input type="checkbox" name="field" value="one">
11
+ <input type="checkbox" name="field" value="two">
12
+ }
13
+ end
14
+
15
+ it { should be_false }
16
+ end
17
+
18
+ context "with radio buttons" do
19
+ let(:markup) do
20
+ %{
21
+ <input type="radio" name="field" value="one">
22
+ <input type="radio" name="field" value="two">
23
+ }
24
+ end
25
+
26
+ it { should be_true }
27
+ end
28
+
29
+ context "with a sweet mix of the two" do
30
+ let(:markup) do
31
+ %{
32
+ <input type="checkbox" name="field" value="one">
33
+ <input type="radio" name="field" value="two">
34
+ }
35
+ end
36
+
37
+ it { should be_false }
38
+ end
39
+ end
40
+
41
+ describe "validations" do
42
+ subject(:radio_group) { Formulary::HtmlForm::Fields::RadioButtonGroup.new("food", elements) }
43
+
44
+ context "when one of the items in the group is required" do
45
+ let(:markup) do
46
+ %{<input type="radio" name="food" value="bacon" required />
47
+ <input type="radio" name="food" value="butter" /> }
48
+ end
49
+
50
+ context "with a valid submission" do
51
+ before { radio_group.set_value("bacon") }
52
+ it { should be_valid }
53
+ its(:error) { should be_blank }
54
+ end
55
+
56
+ context "with a value that isn't expected" do
57
+ before { radio_group.set_value("eggplant") }
58
+ it { should_not be_valid }
59
+ its(:error) { should include("choose") }
60
+ end
61
+
62
+ context "with no value" do
63
+ before { radio_group.set_value("") }
64
+ it { should_not be_valid }
65
+ its(:error) { should include("required") }
66
+ end
67
+ end
68
+
69
+ context "when none are required" do
70
+ let(:markup) do
71
+ %{<input type="radio" name="food" value="bacon" />
72
+ <input type="radio" name="food" value="butter" /> }
73
+ end
74
+
75
+ context "with a value that isn't expected" do
76
+ before { radio_group.set_value("eggplant") }
77
+ it { should_not be_valid }
78
+ its(:error) { should include("choose") }
79
+ end
80
+
81
+ context "with no value" do
82
+ before { radio_group.set_value("") }
83
+ it { should be_valid }
84
+ its(:error) { should be_blank }
85
+ end
86
+
87
+ context "with nil value" do
88
+ before { radio_group.set_value(nil) }
89
+ it { should be_valid }
90
+ its(:error) { should be_blank }
91
+ end
92
+ end
93
+ end
94
+ end