client_side_validations 0.8.0 → 2.2.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.
@@ -1,210 +0,0 @@
1
-
2
- // JSpec - XHR - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
3
-
4
- (function(){
5
-
6
- var lastRequest
7
-
8
- // --- Original XMLHttpRequest
9
-
10
- var OriginalXMLHttpRequest = 'XMLHttpRequest' in this ?
11
- XMLHttpRequest :
12
- function(){}
13
- var OriginalActiveXObject = 'ActiveXObject' in this ?
14
- ActiveXObject :
15
- undefined
16
-
17
- // --- MockXMLHttpRequest
18
-
19
- var MockXMLHttpRequest = function() {
20
- this.requestHeaders = {}
21
- }
22
-
23
- MockXMLHttpRequest.prototype = {
24
- status: 0,
25
- async: true,
26
- readyState: 0,
27
- responseXML: null,
28
- responseText: '',
29
- abort: function(){},
30
- onreadystatechange: function(){},
31
-
32
- /**
33
- * Return response headers hash.
34
- */
35
-
36
- getAllResponseHeaders : function(){
37
- return JSpec.inject(this.responseHeaders, '', function(buf, key, val){
38
- return buf + key + ': ' + val + '\r\n'
39
- })
40
- },
41
-
42
- /**
43
- * Return case-insensitive value for header _name_.
44
- */
45
-
46
- getResponseHeader : function(name) {
47
- return this.responseHeaders[name.toLowerCase()]
48
- },
49
-
50
- /**
51
- * Set case-insensitive _value_ for header _name_.
52
- */
53
-
54
- setRequestHeader : function(name, value) {
55
- this.requestHeaders[name.toLowerCase()] = value
56
- },
57
-
58
- /**
59
- * Open mock request.
60
- */
61
-
62
- open : function(method, url, async, user, password) {
63
- this.user = user
64
- this.password = password
65
- this.url = url
66
- this.readyState = 1
67
- this.method = method.toUpperCase()
68
- if (async != undefined) this.async = async
69
- if (this.async) this.onreadystatechange()
70
- },
71
-
72
- /**
73
- * Send request _data_.
74
- */
75
-
76
- send : function(data) {
77
- var self = this
78
- this.data = data
79
- this.readyState = 4
80
- if (this.method == 'HEAD') this.responseText = null
81
- this.responseHeaders['content-length'] = (this.responseText || '').length
82
- if(this.async) this.onreadystatechange()
83
- this.populateResponseXML()
84
- lastRequest = function(){
85
- return self
86
- }
87
- },
88
-
89
- /**
90
- * Parse request body and populate responseXML if response-type is xml
91
- * Based on the standard specification : http://www.w3.org/TR/XMLHttpRequest/
92
- */
93
- populateResponseXML: function() {
94
- var type = this.getResponseHeader("content-type")
95
- if (!type || !this.responseText || !type.match(/(text\/xml|application\/xml|\+xml$)/g))
96
- return
97
- this.responseXML = JSpec.parseXML(this.responseText)
98
- }
99
- }
100
-
101
- // --- Response status codes
102
-
103
- JSpec.statusCodes = {
104
- 100: 'Continue',
105
- 101: 'Switching Protocols',
106
- 200: 'OK',
107
- 201: 'Created',
108
- 202: 'Accepted',
109
- 203: 'Non-Authoritative Information',
110
- 204: 'No Content',
111
- 205: 'Reset Content',
112
- 206: 'Partial Content',
113
- 300: 'Multiple Choice',
114
- 301: 'Moved Permanently',
115
- 302: 'Found',
116
- 303: 'See Other',
117
- 304: 'Not Modified',
118
- 305: 'Use Proxy',
119
- 307: 'Temporary Redirect',
120
- 400: 'Bad Request',
121
- 401: 'Unauthorized',
122
- 402: 'Payment Required',
123
- 403: 'Forbidden',
124
- 404: 'Not Found',
125
- 405: 'Method Not Allowed',
126
- 406: 'Not Acceptable',
127
- 407: 'Proxy Authentication Required',
128
- 408: 'Request Timeout',
129
- 409: 'Conflict',
130
- 410: 'Gone',
131
- 411: 'Length Required',
132
- 412: 'Precondition Failed',
133
- 413: 'Request Entity Too Large',
134
- 414: 'Request-URI Too Long',
135
- 415: 'Unsupported Media Type',
136
- 416: 'Requested Range Not Satisfiable',
137
- 417: 'Expectation Failed',
138
- 422: 'Unprocessable Entity',
139
- 500: 'Internal Server Error',
140
- 501: 'Not Implemented',
141
- 502: 'Bad Gateway',
142
- 503: 'Service Unavailable',
143
- 504: 'Gateway Timeout',
144
- 505: 'HTTP Version Not Supported'
145
- }
146
-
147
- /**
148
- * Mock XMLHttpRequest requests.
149
- *
150
- * mockRequest().and_return('some data', 'text/plain', 200, { 'X-SomeHeader' : 'somevalue' })
151
- *
152
- * @return {hash}
153
- * @api public
154
- */
155
-
156
- function mockRequest() {
157
- return { and_return : function(body, type, status, headers) {
158
- XMLHttpRequest = MockXMLHttpRequest
159
- ActiveXObject = false
160
- status = status || 200
161
- headers = headers || {}
162
- headers['content-type'] = type
163
- JSpec.extend(XMLHttpRequest.prototype, {
164
- responseText: body,
165
- responseHeaders: headers,
166
- status: status,
167
- statusText: JSpec.statusCodes[status]
168
- })
169
- }}
170
- }
171
-
172
- /**
173
- * Unmock XMLHttpRequest requests.
174
- *
175
- * @api public
176
- */
177
-
178
- function unmockRequest() {
179
- XMLHttpRequest = OriginalXMLHttpRequest
180
- ActiveXObject = OriginalActiveXObject
181
- }
182
-
183
- JSpec.include({
184
- name: 'Mock XHR',
185
-
186
- // --- Utilities
187
-
188
- utilities : {
189
- mockRequest: mockRequest,
190
- unmockRequest: unmockRequest
191
- },
192
-
193
- // --- Hooks
194
-
195
- afterSpec : function() {
196
- unmockRequest()
197
- },
198
-
199
- // --- DSLs
200
-
201
- DSLs : {
202
- snake : {
203
- mock_request: mockRequest,
204
- unmock_request: unmockRequest,
205
- last_request: function(){ return lastRequest() }
206
- }
207
- }
208
-
209
- })
210
- })()
@@ -1,39 +0,0 @@
1
- module DNCLabs
2
- module ClientSideValidations
3
- module Adapters
4
- module ActionView
5
- module BaseMethods
6
-
7
- def client_side_validations(object_name, options = {})
8
- url = options.delete(:url)
9
- raise "No URL Specified!" unless url
10
- adapter = options.delete(:adapter) || 'jquery.validate'
11
- js = %{<script type="text/javascript">$(document).ready(function(){$('##{dom_id(options[:object])}').clientSideValidations('#{url}','#{adapter}');});</script>}
12
- if js.respond_to?(:html_safe)
13
- js.html_safe
14
- else
15
- js
16
- end
17
- end
18
-
19
- end # BaseMethods
20
-
21
- module FormBuilderMethods
22
-
23
- def client_side_validations(options = {})
24
- @template.send(:client_side_validations, @object_name, objectify_options(options))
25
- end
26
-
27
- end # FormBuilderMethods
28
- end
29
- end
30
- end
31
- end
32
-
33
- ActionView::Base.class_eval do
34
- include DNCLabs::ClientSideValidations::Adapters::ActionView::BaseMethods
35
- end
36
-
37
- ActionView::Helpers::FormBuilder.class_eval do
38
- include DNCLabs::ClientSideValidations::Adapters::ActionView::FormBuilderMethods
39
- end
@@ -1,55 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
- gem 'actionpack', '~> 2.0'
3
- require 'action_pack'
4
- require 'action_view'
5
- require 'client_side_validations'
6
-
7
- describe 'ActionView 2.x Form Helper' do
8
- context 'ActionView::Base' do
9
- subject { ActionView::Base.new }
10
-
11
- context 'only the url' do
12
- before do
13
- @object_name = 'object'
14
- @url = '/objects/new.json'
15
- @expected_javascript = %{<script type="text/javascript">$(document).ready(function(){$('##{@object_name}').clientSideValidations('#{@url}','jquery.validate');});</script>}
16
- subject.should_receive(:dom_id).and_return(@object_name)
17
- end
18
-
19
- it 'should generate the proper javascript' do
20
- subject.client_side_validations(@object_name,
21
- :url => @url).should == @expected_javascript
22
- end
23
- end
24
-
25
- context 'a different adapter' do
26
- before do
27
- @object_name = 'object'
28
- @url = '/objects/new.json'
29
- @adapter = 'some.other.adapter'
30
- @expected_javascript = %{<script type="text/javascript">$(document).ready(function(){$('##{@object_name}').clientSideValidations('#{@url}','#{@adapter}');});</script>}
31
- subject.should_receive(:dom_id).and_return(@object_name)
32
- end
33
-
34
- it 'should generate the proper javascript' do
35
- subject.client_side_validations(@object_name,
36
- :url => @url, :adapter => @adapter).should == @expected_javascript
37
- end
38
- end
39
-
40
- context 'not including the :url' do
41
- before do
42
- @object_name = 'object'
43
- @adapter = 'some.other.adapter'
44
- end
45
-
46
- it 'should raise an error' do
47
- expect {
48
- subject.client_side_validations(@object_name,
49
- :adapter => @some_other_adapter)
50
- }.to raise_error
51
- end
52
- end
53
-
54
- end
55
- end
@@ -1,55 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
- gem 'actionpack', '~> 3.0'
3
- require 'action_pack'
4
- require 'action_view'
5
- require 'client_side_validations'
6
-
7
- describe 'ActionView 3.x Form Helper' do
8
- context 'ActionView::Base' do
9
- subject { ActionView::Base.new }
10
-
11
- context 'only the url' do
12
- before do
13
- @object_name = 'object'
14
- @url = '/objects/new.json'
15
- @expected_javascript = %{<script type="text/javascript">$(document).ready(function(){$('##{@object_name}').clientSideValidations('#{@url}','jquery.validate');});</script>}
16
- subject.should_receive(:dom_id).and_return(@object_name)
17
- end
18
-
19
- it 'should generate the proper javascript' do
20
- subject.client_side_validations(@object_name,
21
- :url => @url).should == @expected_javascript
22
- end
23
- end
24
-
25
- context 'a different adapter' do
26
- before do
27
- @object_name = 'object'
28
- @url = '/objects/new.json'
29
- @adapter = 'some.other.adapter'
30
- @expected_javascript = %{<script type="text/javascript">$(document).ready(function(){$('##{@object_name}').clientSideValidations('#{@url}','#{@adapter}');});</script>}
31
- subject.should_receive(:dom_id).and_return(@object_name)
32
- end
33
-
34
- it 'should generate the proper javascript' do
35
- subject.client_side_validations(@object_name,
36
- :url => @url, :adapter => @adapter).should == @expected_javascript
37
- end
38
- end
39
-
40
- context 'not including the :url' do
41
- before do
42
- @object_name = 'object'
43
- @adapter = 'some.other.adapter'
44
- end
45
-
46
- it 'should raise an error' do
47
- expect {
48
- subject.client_side_validations(@object_name,
49
- :adapter => @some_other_adapter)
50
- }.to raise_error
51
- end
52
- end
53
-
54
- end
55
- end
@@ -1,271 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
- require 'active_model'
3
- require 'client_side_validations'
4
-
5
- describe "Validation to hash" do
6
-
7
- before do
8
- class Klass
9
- include ActiveModel::Validations
10
- end
11
- end
12
-
13
- after do
14
- Object.send(:remove_const, :Klass)
15
- end
16
-
17
- it "should support validate_presence_of" do
18
- Klass.class_eval { validates_presence_of :string }
19
- instance = Klass.new
20
- expected_hash = { "presence" => { "message" => "can't be blank"} }
21
- result_hash = instance.validation_to_hash(:string)
22
- result_hash.should == expected_hash
23
- end
24
-
25
- it "should support validates_format_of of" do
26
- Klass.class_eval { validates_format_of :string, :with => /\A\d\Z/i }
27
- instance = Klass.new
28
- expected_hash = { "format" => { "message" => "is invalid", "with" => "^\\d$" } }
29
- result_hash = instance.validation_to_hash(:string)
30
- result_hash.should == expected_hash
31
- end
32
-
33
- it "should support different ways to write regex" do
34
- Klass.class_eval do
35
- validates_format_of :string, :with => /^\d$/i
36
- validates_format_of :string_2, :with => /\d/
37
- end
38
- instance = Klass.new
39
- expected_hash_1 = { "format" => { "message" => "is invalid", "with" => "^\\d$" } }
40
- expected_hash_2 = { "format" => { "message" => "is invalid", "with" => "\\d" } }
41
- result_hash_1 = instance.validation_to_hash(:string)
42
- result_hash_2 = instance.validation_to_hash(:string_2)
43
- result_hash_1.should == expected_hash_1
44
- result_hash_2.should == expected_hash_2
45
- end
46
-
47
- it "should support minimum validates_length_of of" do
48
- Klass.class_eval { validates_length_of :string, :minimum => 10 }
49
- instance = Klass.new
50
- expected_hash = { "length" => { "message" => "is too short (minimum is 10 characters)", "minimum" => 10 } }
51
- result_hash = instance.validation_to_hash(:string)
52
- result_hash.should == expected_hash
53
- end
54
-
55
- it "should support maximum validates_length_of of" do
56
- Klass.class_eval { validates_length_of :string, :maximum => 10 }
57
- instance = Klass.new
58
- expected_hash = { "length" => { "message" => "is too long (maximum is 10 characters)", "maximum" => 10 } }
59
- result_hash = instance.validation_to_hash(:string)
60
- result_hash.should == expected_hash
61
- end
62
-
63
- it "should support validations with conditionals" do
64
- Klass.class_eval do
65
- validates_presence_of :string, :if => :need_string?
66
- validates_presence_of :string_2, :unless => :need_string?
67
- validates_presence_of :integer, :if => :need_integer?
68
-
69
- def need_string?
70
- true
71
- end
72
-
73
- def need_integer?
74
- false
75
- end
76
- end
77
-
78
- instance = Klass.new
79
- expected_hash_1 = { "presence" => { "message" => "can't be blank" } }
80
- result_hash_1 = instance.validation_to_hash(:string)
81
- result_hash_1.should == expected_hash_1
82
-
83
- expected_hash_2 = { }
84
- result_hash_2 = instance.validation_to_hash(:string_2)
85
- result_hash_2.should == expected_hash_2
86
-
87
- expected_hash_3 = { }
88
- result_hash_3 = instance.validation_to_hash(:integer)
89
- result_hash_3.should == expected_hash_3
90
- end
91
-
92
- it "should support validating the validates_numericality_of of" do
93
- Klass.class_eval { validates_numericality_of :integer }
94
- instance = Klass.new
95
- expected_hash = { "numericality" => { "message" => "is not a number" } }
96
- result_hash = instance.validation_to_hash(:integer)
97
- result_hash.should == expected_hash
98
- end
99
-
100
- it "should strip out the AR callback options" do
101
- Klass.class_eval { validates_presence_of :string, :on => :create }
102
- instance = Klass.new
103
- expected_hash = { "presence" => { "message" => "can't be blank"} }
104
- result_hash = instance.validation_to_hash(:string)
105
- result_hash.should == expected_hash
106
- end
107
-
108
- it "should support multiple validations for the same method" do
109
- Klass.class_eval do
110
- validates_presence_of :integer
111
- validates_numericality_of :integer
112
- end
113
-
114
- instance = Klass.new
115
- expected_hash = { "presence" => { "message" => "can't be blank" },
116
- "numericality" => { "message" => "is not a number" } }
117
- result_hash = instance.validation_to_hash(:integer)
118
- result_hash.should == expected_hash
119
- end
120
-
121
- context 'with custom validation messages' do
122
- before do
123
- add_translation(:en, :klass => { :attributes => { :string_2 => { :presence => "String_2" } } })
124
-
125
- Klass.class_eval do
126
- validates_presence_of :string, :message => "String"
127
- validates_presence_of :string_2, :message => :presence
128
- end
129
- end
130
-
131
- after do
132
- remove_translation(:en, :klass)
133
- end
134
-
135
- it 'should have a message of "String" for #string' do
136
- instance = Klass.new
137
- expected_hash = { "presence" => { "message" => "String" } }
138
- result_hash = instance.validation_to_hash(:string)
139
- result_hash.should == expected_hash
140
- end
141
-
142
- it 'should have a message of "String_2" for #string_2' do
143
- instance = Klass.new
144
- expected_hash = { "presence" => { "message" => "String_2" } }
145
- result_hash = instance.validation_to_hash(:string_2)
146
- result_hash.should == expected_hash
147
- end
148
- end
149
-
150
- context 'Other languages' do
151
- before do
152
- add_translation(:es, :klass => { :attributes => { :string => { :presence => "String-es" } } })
153
-
154
- Klass.class_eval do
155
- validates_presence_of :string, :message => :presence
156
- end
157
- end
158
-
159
- after do
160
- remove_translation(:es, :klass)
161
- end
162
-
163
- it 'should result in "String-es" for Spanish translations' do
164
- instance = Klass.new
165
- expected_hash = { "presence" => { "message" => "String-es" } }
166
- result_hash = instance.validation_to_hash(:string, :locale => :es)
167
- result_hash.should == expected_hash
168
- end
169
-
170
- it 'should result in "String-es" for Spanish translations when passed string "es" instead of symbol' do
171
- instance = Klass.new
172
- expected_hash = { "presence" => { "message" => "String-es" } }
173
- result_hash = instance.validation_to_hash(:string, :locale => "es")
174
- result_hash.should == expected_hash
175
- end
176
- end
177
-
178
- xit "should support the regular validate method" do
179
- Klass.class_eval do
180
- validate :do_something
181
-
182
- def do_something
183
- errors.add(:string, "test this out")
184
- end
185
- end
186
-
187
- instance = Klass.new
188
- # TODO: Unsupported right now
189
- end
190
-
191
- def add_translation(lang, hash)
192
- validations = {
193
- :errors => {
194
- :models => hash
195
- }
196
- }
197
- I18n.backend.store_translations(lang, validations)
198
- end
199
-
200
- def remove_translation(lang, key)
201
- model_validations = I18n.translate('errors.models')
202
- model_validations.delete(key)
203
- validations = {
204
- :errors => model_validations
205
- }
206
- I18n.backend.store_translations(lang, validations)
207
- end
208
- end
209
-
210
- describe "Validations to JSON" do
211
- before do
212
- class Klass
213
- include ActiveModel::Validations
214
- end
215
- end
216
-
217
- after do
218
- Object.send(:remove_const, :Klass)
219
- end
220
-
221
- it "should support a sinlgle validation" do
222
- Klass.class_eval do
223
- validates_presence_of :string
224
- end
225
-
226
- instance = Klass.new
227
- expected_json = {:string => { "presence" => { "message" => "can't be blank" } } }.to_json
228
- result_json = instance.validations_to_json(:string)
229
- result_json.should == expected_json
230
- end
231
-
232
- it "should support multiple validations on the same field" do
233
- Klass.class_eval do
234
- validates_presence_of :number
235
- validates_numericality_of :number
236
- end
237
-
238
- instance = Klass.new
239
- expected_json = {:number => { "presence" => { "message" => "can't be blank" }, "numericality" => { "message" => "is not a number" } } }.to_json
240
- result_json = instance.validations_to_json(:number)
241
- result_json.should == expected_json
242
- end
243
-
244
- it "should support single validations on different fields" do
245
- Klass.class_eval do
246
- validates_presence_of :string
247
- validates_presence_of :string_2
248
- end
249
-
250
- instance = Klass.new
251
- expected_json = {:string => { "presence" => { "message" => "can't be blank" } },
252
- :string_2 => { "presence" => { "message" => "can't be blank" } } }.to_json
253
- result_json = instance.validations_to_json(:string, :string_2)
254
- result_json.should == expected_json
255
- end
256
-
257
- it "should support multiple validations on different fields" do
258
- Klass.class_eval do
259
- validates_presence_of :number_1
260
- validates_numericality_of :number_1
261
- validates_presence_of :number_2
262
- validates_numericality_of :number_2
263
- end
264
-
265
- instance = Klass.new
266
- expected_json = {:number_1 => { "presence" => { "message" => "can't be blank" }, "numericality" => { "message" => "is not a number" } },
267
- :number_2 => { "presence" => { "message" => "can't be blank" }, "numericality" => { "message" => "is not a number" } } }.to_json
268
- result_json = instance.validations_to_json(:number_1, :number_2)
269
- result_json.should == expected_json
270
- end
271
- end