with_filters 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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