with_filters 0.1.0

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 (109) hide show
  1. data/.gitignore +8 -0
  2. data/.yardopts +1 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +63 -0
  6. data/Rakefile +1 -0
  7. data/app/views/with_filters/_filter_form.html.erb +14 -0
  8. data/app/views/with_filters/filter/_check_box.html.erb +2 -0
  9. data/app/views/with_filters/filter/_check_boxes.html.erb +5 -0
  10. data/app/views/with_filters/filter/_radio.html.erb +5 -0
  11. data/app/views/with_filters/filter/_select.html.erb +2 -0
  12. data/app/views/with_filters/filter/_select_range.html.erb +4 -0
  13. data/app/views/with_filters/filter/_text.html.erb +2 -0
  14. data/app/views/with_filters/filter/_text_range.html.erb +4 -0
  15. data/changelog.md +2 -0
  16. data/lib/generators/with_filters/theme/theme_generator.rb +43 -0
  17. data/lib/with_filters/action_view_extension.rb +110 -0
  18. data/lib/with_filters/active_record_extension.rb +26 -0
  19. data/lib/with_filters/active_record_model_extension.rb +163 -0
  20. data/lib/with_filters/engine.rb +5 -0
  21. data/lib/with_filters/hash_extraction.rb +31 -0
  22. data/lib/with_filters/models/action.rb +14 -0
  23. data/lib/with_filters/models/filter/base.rb +36 -0
  24. data/lib/with_filters/models/filter/base_range.rb +42 -0
  25. data/lib/with_filters/models/filter/check_box.rb +20 -0
  26. data/lib/with_filters/models/filter/choice.rb +23 -0
  27. data/lib/with_filters/models/filter/collection.rb +28 -0
  28. data/lib/with_filters/models/filter/filter.rb +59 -0
  29. data/lib/with_filters/models/filter/radio.rb +7 -0
  30. data/lib/with_filters/models/filter/select.rb +22 -0
  31. data/lib/with_filters/models/filter/select_range.rb +15 -0
  32. data/lib/with_filters/models/filter/text.rb +30 -0
  33. data/lib/with_filters/models/filter/text_range.rb +15 -0
  34. data/lib/with_filters/models/filter_form.rb +93 -0
  35. data/lib/with_filters/value_prep/boolean_prep.rb +10 -0
  36. data/lib/with_filters/value_prep/date_prep.rb +10 -0
  37. data/lib/with_filters/value_prep/date_time_prep.rb +51 -0
  38. data/lib/with_filters/value_prep/default_prep.rb +88 -0
  39. data/lib/with_filters/value_prep/value_prep.rb +28 -0
  40. data/lib/with_filters/version.rb +3 -0
  41. data/lib/with_filters.rb +32 -0
  42. data/spec/active_record_model_extension_spec.rb +435 -0
  43. data/spec/dummy/README.rdoc +261 -0
  44. data/spec/dummy/Rakefile +7 -0
  45. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  46. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  47. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  48. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  49. data/spec/dummy/app/mailers/.gitkeep +0 -0
  50. data/spec/dummy/app/models/.gitkeep +0 -0
  51. data/spec/dummy/app/models/date_time_tester.rb +2 -0
  52. data/spec/dummy/app/models/field_format_tester.rb +2 -0
  53. data/spec/dummy/app/models/nobel_prize.rb +3 -0
  54. data/spec/dummy/app/models/nobel_prize_winner.rb +3 -0
  55. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  56. data/spec/dummy/config/application.rb +56 -0
  57. data/spec/dummy/config/boot.rb +10 -0
  58. data/spec/dummy/config/database.yml +25 -0
  59. data/spec/dummy/config/environment.rb +5 -0
  60. data/spec/dummy/config/environments/development.rb +37 -0
  61. data/spec/dummy/config/environments/production.rb +67 -0
  62. data/spec/dummy/config/environments/test.rb +37 -0
  63. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  64. data/spec/dummy/config/initializers/inflections.rb +15 -0
  65. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  66. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  67. data/spec/dummy/config/initializers/session_store.rb +8 -0
  68. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  69. data/spec/dummy/config/locales/en.yml +5 -0
  70. data/spec/dummy/config/routes.rb +58 -0
  71. data/spec/dummy/config.ru +4 -0
  72. data/spec/dummy/db/migrate/20111227224959_additional_columns.rb +73 -0
  73. data/spec/dummy/db/migrate/20120127203225_create_nobel_prize_winners.rb +30 -0
  74. data/spec/dummy/db/migrate/20120203212237_create_nobel_prizes.rb +34 -0
  75. data/spec/dummy/db/migrate/20120209051208_modify_updated_at.rb +13 -0
  76. data/spec/dummy/db/migrate/20120210163052_change_created_at.rb +17 -0
  77. data/spec/dummy/db/migrate/20120214172946_fix_einstein.rb +9 -0
  78. data/spec/dummy/db/migrate/20120227200013_create_date_time_testers.rb +25 -0
  79. data/spec/dummy/db/migrate/20120309202722_create_field_format_testers.rb +22 -0
  80. data/spec/dummy/db/migrate/20120310195447_update_field_format_testers.rb +15 -0
  81. data/spec/dummy/db/schema.rb +51 -0
  82. data/spec/dummy/db/test.sqlite3 +0 -0
  83. data/spec/dummy/lib/assets/.gitkeep +0 -0
  84. data/spec/dummy/log/.gitkeep +0 -0
  85. data/spec/dummy/public/404.html +26 -0
  86. data/spec/dummy/public/422.html +26 -0
  87. data/spec/dummy/public/500.html +25 -0
  88. data/spec/dummy/public/favicon.ico +0 -0
  89. data/spec/dummy/script/rails +6 -0
  90. data/spec/generators/with_filters_theme_spec.rb +33 -0
  91. data/spec/hash_extraction_spec.rb +51 -0
  92. data/spec/helpers/action_view_extension_spec.rb +345 -0
  93. data/spec/models/action.rb +20 -0
  94. data/spec/models/filter/base_range_spec.rb +32 -0
  95. data/spec/models/filter/base_spec.rb +76 -0
  96. data/spec/models/filter/check_box_spec.rb +36 -0
  97. data/spec/models/filter/choice_spec.rb +24 -0
  98. data/spec/models/filter/collection_spec.rb +72 -0
  99. data/spec/models/filter/filter_spec.rb +35 -0
  100. data/spec/models/filter/select_spec.rb +12 -0
  101. data/spec/models/filter/text_spec.rb +16 -0
  102. data/spec/models/filter_form_spec.rb +212 -0
  103. data/spec/spec_helper.rb +12 -0
  104. data/spec/value_prep/boolean_prep_spec.rb +13 -0
  105. data/spec/value_prep/date_prep_spec.rb +28 -0
  106. data/spec/value_prep/date_time_prep_spec.rb +106 -0
  107. data/spec/value_prep/default_prep_spec.rb +43 -0
  108. data/with_filters.gemspec +27 -0
  109. metadata +280 -0
@@ -0,0 +1,25 @@
1
+ class CreateDateTimeTesters < ActiveRecord::Migration
2
+ def up
3
+ create_table :date_time_testers do |t|
4
+ t.datetime :test
5
+ end
6
+
7
+ [
8
+ '2012-01-01 00:00:01.000000',
9
+ '2012-01-01 00:00:01.123456',
10
+ '2012-01-01 00:00:01.654300',
11
+ '2012-01-01 00:00:01.654321',
12
+ '2012-01-01 00:00:02.000000',
13
+ '2012-01-01 00:00:03.000000',
14
+ '2012-01-01 00:00:03.100000',
15
+ '2012-01-01 23:59:59.999999',
16
+ '2012-01-02 00:00:00.000000'
17
+ ].each do |time|
18
+ DateTimeTester.create(test: time)
19
+ end
20
+ end
21
+
22
+ def down
23
+ drop_table :date_time_testers
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ class CreateFieldFormatTesters < ActiveRecord::Migration
2
+ def change
3
+ create_table :field_format_testers do |t|
4
+ t.integer :integer_field
5
+ t.float :float_field
6
+ t.decimal :decimal_field
7
+ t.date :date_field
8
+ t.time :time_field
9
+ t.datetime :datetime_field
10
+ t.timestamp :timestamp_field
11
+ t.boolean :boolean_field
12
+ t.text :text_field
13
+ t.text :email_field
14
+ t.text :phone_field
15
+ t.text :url_field
16
+ end
17
+
18
+ remove_column :nobel_prize_winners, :meaningless_time
19
+ remove_column :nobel_prizes, :meaningless_decimal
20
+ remove_column :nobel_prizes, :meaningless_float
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ class UpdateFieldFormatTesters < ActiveRecord::Migration
2
+ def up
3
+ add_column :field_format_testers, :string_field, :string
4
+ change_column :field_format_testers, :email_field, :string
5
+ change_column :field_format_testers, :phone_field, :string
6
+ change_column :field_format_testers, :url_field, :string
7
+ end
8
+
9
+ def down
10
+ change_column :field_format_testers, :email_field, :text
11
+ change_column :field_format_testers, :phone_field, :text
12
+ change_column :field_format_testers, :url_field, :text
13
+ remove_column :field_format_testers, :string_field
14
+ end
15
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended to check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(:version => 20120310195447) do
15
+
16
+ create_table "date_time_testers", :force => true do |t|
17
+ t.datetime "test"
18
+ end
19
+
20
+ create_table "field_format_testers", :force => true do |t|
21
+ t.integer "integer_field"
22
+ t.float "float_field"
23
+ t.decimal "decimal_field"
24
+ t.date "date_field"
25
+ t.time "time_field"
26
+ t.datetime "datetime_field"
27
+ t.datetime "timestamp_field"
28
+ t.boolean "boolean_field"
29
+ t.text "text_field"
30
+ t.string "email_field"
31
+ t.string "phone_field"
32
+ t.string "url_field"
33
+ t.string "string_field"
34
+ end
35
+
36
+ create_table "nobel_prize_winners", :force => true do |t|
37
+ t.string "first_name"
38
+ t.string "last_name"
39
+ t.date "birthdate"
40
+ t.datetime "created_at"
41
+ t.datetime "updated_at"
42
+ end
43
+
44
+ create_table "nobel_prizes", :force => true do |t|
45
+ t.integer "nobel_prize_winner_id"
46
+ t.string "category"
47
+ t.integer "year"
48
+ t.boolean "shared"
49
+ end
50
+
51
+ end
Binary file
File without changes
File without changes
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ </div>
24
+ </body>
25
+ </html>
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+ require 'genspec'
3
+
4
+ describe 'with_filters:theme' do
5
+ with_args :foo do
6
+ it 'generates app/views/with_filters/foo/ with all files' do
7
+ subject.should generate('app/views/with_filters/foo')
8
+ subject.should generate('app/views/with_filters/foo/_filter_form.html.erb')
9
+ subject.should generate('app/views/with_filters/foo/filter/_text.html.erb')
10
+ end
11
+ end
12
+
13
+ with_args :foo, 'filter_form' do
14
+ it 'generates a single file in app/views/with_filters/foo/' do
15
+ subject.should generate('app/views/with_filters/foo')
16
+ subject.should generate('app/views/with_filters/foo/_filter_form.html.erb')
17
+ end
18
+ end
19
+
20
+ with_args :foo, 'filter/text' do
21
+ it 'generates a single file in app/views/with_filters/foo/filters' do
22
+ subject.should generate('app/views/with_filters/foo/filter')
23
+ subject.should generate('app/views/with_filters/foo/filter/_text.html.erb')
24
+ end
25
+ end
26
+
27
+ with_args :foo, 'filter/text_as_email' do
28
+ it 'generates a file in app/views/with_filters/foo/filters based on text to support "email" types' do
29
+ subject.should generate('app/views/with_filters/foo/filter')
30
+ subject.should generate('app/views/with_filters/foo/filter/_text_as_email.html.erb')
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe WithFilters::HashExtraction do
4
+ describe '#extract_hash_value(hash, key)' do
5
+ let(:params) {{
6
+ 'fizz' => 'buzz',
7
+ foo: 'bar',
8
+ one: {'two' => {'three' => 3}}
9
+ }}
10
+ subject {
11
+ class TestHashExtraction
12
+ include WithFilters::HashExtraction
13
+ end
14
+ TestHashExtraction.new
15
+ }
16
+
17
+ context 'where a regular hash key is used' do
18
+ context 'where the value is a Symbol' do
19
+ it 'returns the value from the hash' do
20
+ subject.extract_hash_value(params, :foo).should == params[:foo]
21
+ subject.extract_hash_value(params, :fizz).should == params['fizz']
22
+ end
23
+ end
24
+
25
+ context 'where the value is a String' do
26
+ it 'returns the value from the hash' do
27
+ subject.extract_hash_value(params, 'foo').should == params[:foo]
28
+ subject.extract_hash_value(params, 'fizz').should == params['fizz']
29
+ end
30
+ end
31
+
32
+ context 'where the value is not found' do
33
+ it 'returns nil' do
34
+ subject.extract_hash_value(params, 'yo').should be nil
35
+ end
36
+ end
37
+ end
38
+
39
+ context 'where a nested hash key is used' do
40
+ it 'returns the value from the hash' do
41
+ subject.extract_hash_value(params, 'one[two][three]').should == params[:one]['two']['three']
42
+ end
43
+
44
+ context 'where the value is not found' do
45
+ it 'returns nil' do
46
+ subject.extract_hash_value(params, 'yo[one]').should be nil
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,345 @@
1
+ require 'spec_helper'
2
+
3
+ describe WithFilters::ActionViewExtension do
4
+ describe '#filter_form_for(record, &block)' do
5
+ it 'creates a form' do
6
+ output = helper.filter_form_for(NobelPrizeWinner.with_filters) {}
7
+
8
+ output.should have_selector('form[@novalidate="novalidate"]')
9
+ end
10
+ end
11
+
12
+ describe '#with_filters_hidden(hidden_filters)' do
13
+ it 'outputs hidden input tags' do
14
+ hidden1 = WithFilters::Filter::Text.new(:hidden1, :foo, 1, {})
15
+ hidden2 = WithFilters::Filter::Text.new(:hidden2, :foo, 2, {})
16
+
17
+ output = helper.with_filters_hidden([hidden1, hidden2])
18
+
19
+ output.should have_selector('input[type="hidden"][value="1"]')
20
+ output.should have_selector('input[type="hidden"][value="2"]')
21
+ end
22
+ end
23
+
24
+ describe '#with_filters_input(filter)' do
25
+ context 'with a single input' do
26
+ context 'types' do
27
+ let(:options) {{
28
+ class: 'input_class',
29
+ label_attrs: {class: 'label_class'}
30
+ }}
31
+
32
+ context 'text' do
33
+ let(:filter) {WithFilters::Filter::Text.new(:first_name, :foo, 'Aaron', options)}
34
+ subject {helper.with_filters_input(filter)}
35
+
36
+ it 'has a label tag' do
37
+ subject.should have_selector('label')
38
+ end
39
+
40
+ it 'has an input tag' do
41
+ subject.should have_selector("input[@name='#{filter.field_name}']")
42
+ end
43
+ end
44
+
45
+ context 'radio' do
46
+ let(:filter) {WithFilters::Filter::Radio.new(:gender, :foo, 'Male', options.merge(collection: [['Male', {class: 'choice_class'}], 'Female']))}
47
+ subject {helper.with_filters_input(filter)}
48
+
49
+ it 'has a label for the group' do
50
+ subject.should have_selector("div[text()='#{filter.label}']")
51
+ end
52
+
53
+ it 'has a label tag for each choice' do
54
+ filter.collection.each do |choice|
55
+ subject.should have_selector("label[text()='#{choice.label}']")
56
+ end
57
+ end
58
+
59
+ it 'has an input tag for each choice' do
60
+ subject.should have_selector("input[@type='radio']")
61
+ filter.collection.each do |choice|
62
+ subject.should have_selector("input[@name='#{choice.field_name}']")
63
+ subject.should have_selector("input[@value='#{choice.value}']")
64
+ if choice.value == filter.value
65
+ subject.should have_selector("input[@checked='checked']")
66
+ end
67
+ choice.attrs.each do |k, v|
68
+ subject.should have_selector("input[@#{k}='#{v}']")
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ context 'check_box' do
75
+ let(:collection) {['Chemistry', 'Literature', 'Peace', 'Physics', 'Physiology or Medicine']}
76
+
77
+ context 'without collection' do
78
+ let(:filter) {WithFilters::Filter::CheckBox.new(:gender, :foo, 'on')}
79
+ subject {helper.with_filters_input(filter)}
80
+
81
+ it 'has a label tag' do
82
+ subject.should have_selector('label')
83
+ end
84
+
85
+ it 'has an input tag' do
86
+ subject.should have_selector("input[@type='checkbox']")
87
+ subject.should have_selector("input[@name='#{filter.field_name}']")
88
+ subject.should have_selector("input[@value='#{filter.value}']")
89
+ subject.should have_selector("input[@checked='checked']")
90
+ end
91
+ end
92
+
93
+ context 'with collection' do
94
+ let(:filter) {WithFilters::Filter::CheckBox.new(:gender, :foo, ['Chemistry', 'Peace'], options.merge(collection: collection))}
95
+ subject {helper.with_filters_input(filter)}
96
+
97
+ it 'has a label for the group' do
98
+ subject.should have_selector("div[text()='#{filter.label}']")
99
+ end
100
+
101
+ it 'has a label tag for each choice' do
102
+ filter.collection.each do |choice|
103
+ subject.should have_selector("label[text()='#{choice.label}']")
104
+ end
105
+ end
106
+
107
+ it 'has an input tag for each choice' do
108
+ subject.should have_selector("input[@type='checkbox']")
109
+ filter.collection.each do |choice|
110
+ subject.should have_selector("input[@name='#{choice.field_name}']")
111
+ subject.should have_selector("input[@value='#{choice.value}']")
112
+ if filter.value.include?(choice.value)
113
+ subject.should have_selector("input[@checked='checked']")
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ context 'with ranged inputs' do
122
+ context 'types' do
123
+ context 'text' do
124
+ let(:filter) {WithFilters::Filter::TextRange.new(:year, :foo, {start: 1900, stop: 2000})}
125
+ subject {helper.with_filters_input(filter)}
126
+
127
+ context 'start' do
128
+ it 'has a label tag' do
129
+ subject.should have_selector("label[text()='#{filter.start.label}']")
130
+ end
131
+
132
+ it 'has an input tag' do
133
+ subject.should have_selector("input[@name='#{filter.start.field_name}']")
134
+ subject.should have_selector("input[@value='#{filter.start.value}']")
135
+ end
136
+ end
137
+
138
+ context 'stop' do
139
+ it 'has a label tag' do
140
+ subject.should have_selector("label[text()='#{filter.stop.label}']")
141
+ end
142
+
143
+ it 'has an input tag' do
144
+ subject.should have_selector("input[@name='#{filter.stop.field_name}']")
145
+ subject.should have_selector("input[@value='#{filter.stop.value}']")
146
+ end
147
+ end
148
+ end
149
+
150
+ context 'select' do
151
+ let(:filter) {WithFilters::Filter::SelectRange.new(:year, :foo, {start: 1900, stop: 1905}, collection: 1900..1910)}
152
+ subject {helper.with_filters_input(filter)}
153
+
154
+ context 'start' do
155
+ it 'has a label tag' do
156
+ subject.should have_selector("label[text()='#{filter.start.label}']")
157
+ end
158
+ end
159
+
160
+ context 'stop' do
161
+ it 'has a label tag' do
162
+ subject.should have_selector("label[text()='#{filter.stop.label}']")
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ context 'options' do
171
+ context ':label_attrs' do
172
+ it 'adds attrs to the label_tag' do
173
+ output = helper.filter_form_for(NobelPrizeWinner.with_filters) do |f|
174
+ f.input :first_name, label_attrs: {class: 'label_class'}
175
+ end
176
+
177
+ output.should have_selector('label.label_class')
178
+ end
179
+ end
180
+
181
+ context ':collection' do
182
+ it 'outputs all collection' do
183
+ collection = ['Chemistry', 'Literature', 'Peace', 'Physics', 'Physiology or Medicine']
184
+ output = helper.filter_form_for(NobelPrize.with_filters) do |f|
185
+ f.input :category, collection: collection
186
+ end
187
+
188
+ output.should have_selector("label[text()='Category']")
189
+ collection.each do |choice|
190
+ output.should have_selector("option[text()='#{choice}']")
191
+ output.should have_selector("option[@value='#{choice}']")
192
+ end
193
+ end
194
+ end
195
+
196
+ context 'everything else' do
197
+ it 'adds attrs to the input' do
198
+ output = helper.filter_form_for(NobelPrizeWinner.with_filters) do |f|
199
+ f.input :first_name, class: 'input_class'
200
+ end
201
+
202
+ output.should have_selector('input.input_class')
203
+ end
204
+ end
205
+ end
206
+
207
+ context 'param value is available' do
208
+ it 'creates an input with a value' do
209
+ helper.stub(:params).and_return({nobel_prize_winners: {first_name: 'Albert'}})
210
+ output = helper.filter_form_for(NobelPrizeWinner.with_filters) do |f|
211
+ f.input :first_name
212
+ end
213
+
214
+ output.should have_selector('input[@value="Albert"]')
215
+ end
216
+ end
217
+ end
218
+
219
+ describe '#with_filters_label_tag(filter)' do
220
+ let(:filter) {WithFilters::Filter::Text.new(:first_name, :foo, 'Aaron', label_attrs: {class: 'bar'})}
221
+ subject {helper.with_filters_label_tag(filter)}
222
+
223
+ it 'has the correct label text' do
224
+ subject.should have_selector("label[text()='#{filter.label}']")
225
+ end
226
+
227
+ it 'has the correct for attribute' do
228
+ subject.should have_selector(%Q{label[for="#{filter.field_name.match(/^(.*)\[(.*)\]$/).captures.join('_')}"]})
229
+ end
230
+
231
+ it 'has the correct attributes' do
232
+ filter.label_attrs.should_not be_empty
233
+ filter.label_attrs.each do |k, v|
234
+ subject.should have_selector("label[@#{k}='#{v}']")
235
+ end
236
+ end
237
+ end
238
+
239
+ describe '#with_filters_label(filter)' do
240
+ context 'a tag with a single label' do
241
+ let(:filter) {WithFilters::Filter::Text.new(:first_name, :foo, 'Aaron', label_attrs: {class: 'bar'})}
242
+ subject {helper.with_filters_label(filter)}
243
+
244
+ it 'creates a label tag' do
245
+ subject.should have_selector("label[text()='#{filter.label}']")
246
+ end
247
+ end
248
+
249
+ context 'a group of tags with individual labels and one form label' do
250
+ let(:options) {{label_attrs: {class: 'label_class'}}}
251
+ let(:filter) {WithFilters::Filter::Radio.new(:gender, :foo, 'Male', options.merge(collection: ['Male', 'Female']))}
252
+ subject {helper.with_filters_label(filter)}
253
+
254
+ it 'creates a div to act as a label tag for the group' do
255
+ subject.should have_selector("div[text()='#{filter.label}']")
256
+
257
+ filter.label_attrs.should_not be_empty
258
+ filter.label_attrs.each do |k, v|
259
+ subject.should have_selector("div[@#{k}='#{v}']")
260
+ end
261
+ end
262
+ end
263
+ end
264
+
265
+ describe '#with_filters_text_field_tag(filter)' do
266
+ let(:options) {{
267
+ class: 'input_class',
268
+ label_attrs: {class: 'label_class'}
269
+ }}
270
+ let(:filter) {WithFilters::Filter::Text.new(:first_name, :foo, 'Aaron', options)}
271
+ subject {helper.with_filters_text_field_tag(filter)}
272
+
273
+ it 'has an input tag' do
274
+ subject.should have_selector("input[@name='#{filter.field_name}']")
275
+ subject.should have_selector("input[@value='#{filter.value}']")
276
+ filter.attrs.should_not be_empty
277
+ filter.attrs.each do |k, v|
278
+ subject.should have_selector("input[@#{k}='#{v}']")
279
+ end
280
+ end
281
+ end
282
+
283
+ describe '#with_filters_select_tag(filter)' do
284
+ let(:options) {{
285
+ class: 'input_class',
286
+ label_attrs: {class: 'label_class'}
287
+ }}
288
+ let(:filter) {WithFilters::Filter::Select.new(:gender, :foo, 'Male', options.merge(collection: [['Male', {class: 'choice_class'}], 'Female']))}
289
+ subject {helper.with_filters_select_tag(filter)}
290
+
291
+ it 'creates a select field' do
292
+ subject.should have_selector("select[@name='#{filter.field_name}']")
293
+ end
294
+
295
+ it 'has an option for each choice' do
296
+ filter.collection.each do |choice|
297
+ subject.should have_selector("option[@value='#{choice.value}']")
298
+ if choice.value == filter.value
299
+ subject.should have_selector("option[@selected='selected']")
300
+ end
301
+ choice.attrs.each do |k, v|
302
+ subject.should have_selector("option[@#{k}='#{v}']")
303
+ end
304
+ end
305
+ end
306
+
307
+ context 'where :collection is a String' do
308
+ let(:filter) {WithFilters::Filter::Select.new(:gender, :foo, 'Male', collection: '<option>Male</option><option value="1">Female</option>')}
309
+ subject {helper.with_filters_select_tag(filter)}
310
+
311
+ context 'option does not contain a value attribute' do
312
+ it 'should mark an option as selected' do
313
+ subject.should have_selector('option[@selected="selected"][text()="Male"]')
314
+ subject.should have_selector('option[text()="Female"]')
315
+ end
316
+ end
317
+
318
+ context 'option contains a value attribute' do
319
+ let(:filter) {WithFilters::Filter::Select.new(:gender, :foo, 1, collection: '<option>Male</option><option value="1">Female</option>')}
320
+ subject {helper.with_filters_select_tag(filter)}
321
+
322
+ it 'should mark an option as selected' do
323
+ subject.should have_selector('option[text()="Male"]')
324
+ subject.should have_selector('option[@selected="selected"][text()="Female"]')
325
+ end
326
+ end
327
+ end
328
+ end
329
+
330
+ describe '#with_filters_action_tag(action)' do
331
+ context 'action' do
332
+ context ':submit' do
333
+ it 'returns a submit button' do
334
+ helper.with_filters_action_tag(WithFilters::Action.new(:submit)).should have_selector('input[type="submit"]')
335
+ end
336
+ end
337
+
338
+ context ':reset' do
339
+ it 'returns a reset button' do
340
+ helper.with_filters_action_tag(WithFilters::Action.new(:reset)).should have_selector('button[type="reset"]')
341
+ end
342
+ end
343
+ end
344
+ end
345
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe WithFilters::Action do
4
+ describe '#initialize(type, options = {})' do
5
+ context 'defaults' do
6
+ subject {described_class.new(:submit)}
7
+
8
+ its(:type) {should be :submit}
9
+ its(:attrs) {should == {type: :submit}}
10
+ end
11
+
12
+ context 'options' do
13
+ context ':label' do
14
+ it 'labels the button' do
15
+ described_class.new(:submit, label: 'Submit').attrs[:value].should == 'Submit'
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end