pax_global_header 0000666 0000000 0000000 00000000064 12202276743 0014517 g ustar 00root root 0000000 0000000 52 comment=03dfff597e025e164f44621846cf25d85e596ddc
client_side_validations-3.2.6/ 0000775 0000000 0000000 00000000000 12202276743 0016406 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/.gitignore 0000664 0000000 0000000 00000000142 12202276743 0020373 0 ustar 00root root 0000000 0000000 *.gem
.bundle
*.lock
pkg/*
tags
test/generators/tmp/*
*.swp
.*rc
bundler_stubs/*
binstubs/*
bin/*
client_side_validations-3.2.6/.travis.yml 0000664 0000000 0000000 00000000125 12202276743 0020515 0 ustar 00root root 0000000 0000000 rvm:
- 1.9.3
before_install:
- gem update --system
- gem install bundler --pre
client_side_validations-3.2.6/CONTRIBUTING.md 0000664 0000000 0000000 00000002426 12202276743 0020643 0 ustar 00root root 0000000 0000000 # Contribution Guidelines #
## Submitting a new issue ##
If you need to open a new issue you *must* provide the following:
1. Version of ClientSideValidations
2. Version of Rails
3. Code snippet from your model of the validations
4. The form code from your template
5. The resulting HTML along with the script tag
Failure to include the above mentioned requirements will result in the
issue being closed.
If you want to ensure that your issue gets fixed *fast* you should
attempt to reproduce the issue in an isolated example application that
you can share.
## Making a pull request ##
If you'd like to submit a pull request please adhere to the following:
1. Your code *must* be tested. Please TDD your code!
2. No single-character variables
3. Two-spaces instead of tabs
4. Single-quotes instead of double-quotes unless you are using string
interpolation or escapes.
5. General Rails/Ruby naming conventions for files and classes
6. *Do not* use Ruby 1.9 hash syntax
7. *Do not* use Ruby 1.9 stubby proc syntax
Plase note that you must adhere to each of the above mentioned rules.
Failure to do so will result in an immediate closing of the pull
request. If you update and rebase the pull request to follow the
guidelines your pull request will be re-opened and considered for
inclusion.
client_side_validations-3.2.6/Gemfile 0000664 0000000 0000000 00000000310 12202276743 0017673 0 ustar 00root root 0000000 0000000 source "http://rubygems.org"
# Specify your gem's dependencies in client_side_validations.gemspec
gemspec
if RUBY_VERSION >= '1.9.3'
gem 'debugger'
elsif RUBY_VERSION < '1.9'
gem 'minitest'
end
client_side_validations-3.2.6/HISTORY.md 0000664 0000000 0000000 00000004441 12202276743 0020074 0 ustar 00root root 0000000 0000000 # ClientSideValidation History #
## Version 3.2 ##
* [v3.2.1](https://github.com/bcardarella/client_side_validations/compare/v3.2.0...v3.2.1)
* [v3.2.0](https://github.com/bcardarella/client_side_validations/compare/v3.1.5...v3.2.0)
## Version 3.1
* [v3.1.5](https://github.com/bcardarella/client_side_validations/compare/v3.1.4...v3.1.5)
* [v3.1.4](https://github.com/bcardarella/client_side_validations/compare/v3.1.3...v3.1.4)
* [v3.1.3](https://github.com/bcardarella/client_side_validations/compare/v3.1.2...v3.1.3)
* [v3.1.2](https://github.com/bcardarella/client_side_validations/compare/v3.1.1...v3.1.2)
* [v3.1.1](https://github.com/bcardarella/client_side_validations/compare/v3.1.0...v3.1.1)
* [v3.1.0](https://github.com/bcardarella/client_side_validations/compare/badf88aa6a09012900e9275bb01c80f4d19482ce...v3.1.0)
## Version 3.0
* [v3.0.13](https://github.com/bcardarella/client_side_validations/compare/v3.0.12...v3.0.13)
* [v3.0.12](https://github.com/bcardarella/client_side_validations/compare/v3.0.11...v3.0.12)
* [v3.0.11](https://github.com/bcardarella/client_side_validations/compare/v3.0.10...v3.0.11)
* [v3.0.10](https://github.com/bcardarella/client_side_validations/compare/v3.0.9...v3.0.10)
* [v3.0.9](https://github.com/bcardarella/client_side_validations/compare/v3.0.8...v3.0.9)
* [v3.0.8](https://github.com/bcardarella/client_side_validations/compare/v3.0.7...v3.0.8)
* [v3.0.7](https://github.com/bcardarella/client_side_validations/compare/v3.0.6...v3.0.7)
* [v3.0.6](https://github.com/bcardarella/client_side_validations/compare/v3.0.5...v3.0.6)
* [v3.0.5](https://github.com/bcardarella/client_side_validations/compare/v3.0.4...v3.0.5)
* [v3.0.4](https://github.com/bcardarella/client_side_validations/compare/v3.0.3...v3.0.4)
* [v3.0.3](https://github.com/bcardarella/client_side_validations/compare/v3.0.2...v3.0.3)
* [v3.0.2](https://github.com/bcardarella/client_side_validations/compare/v3.0.1...v3.0.2)
* [v3.0.1](https://github.com/bcardarella/client_side_validations/compare/v3.0.0...v3.0.1)
* [v3.0.0](https://github.com/bcardarella/client_side_validations/compare/4c6262702e513f1c4c063d36ccc88c0f3071199a...v3.0.0)
## Prior to Version 3.0
This gem was a re-write of the original [ClientSideValidationsgem](https://github.com/dnclabs/client_side_validations).
Versions were not tagged.
client_side_validations-3.2.6/README.md 0000664 0000000 0000000 00000047405 12202276743 0017677 0 ustar 00root root 0000000 0000000 # ClientSideValidations #
[](http://travis-ci.org/bcardarella/client_side_validations)
[](https://gemnasium.com/bcardarella/client_side_validations)
[](https://codeclimate.com/github/bcardarella/client_side_validations)
`ClientSideValidations` made easy for your Rails v3.1+ applications!
## Project Goals ##
1. Follow the best practices for client side validations developed by [Luke Wroblewski](http://www.alistapart.com/articles/inline-validation-in-web-forms/)
2. Automatically extract and apply validation rules defined on the
server to the client.
3. In the cases where a server-side validation rule would not work on
the client (i.e. conditional callbacks like :if, :unless) then do not
attempt client side validations. Fall back to the server side
validation.
4. The client side validation error rendering should be
indistinguishable from the server side validation error rendering.
5. Wide browser compliancy.
6. Work with any ActiveModel::Validations based model
7. Validate nested fields
8. Support custom validations
9. Client side validation callbacks
10. Plugin system to support additional FormBuilders, ORMs, etc...
## Install ##
Include `ClientSideValidations` in your Gemfile
```ruby
gem 'client_side_validations'
```
Then run the install generator
```
rails g client_side_validations:install
```
This will install the initializer:
```
config/initializers/client_side_validations.rb
```
If you want to copy the asset files from the gem into your project:
```
rails g client_side_validations:copy_assets
```
## Initializer ##
The initializer includes a commented out `ActionView::Base.field_error_proc`.
Uncomment this to render your error messages inline with the input fields.
I recommend you not use a solution similar to `error_messages_for`. Client
Side Validations is never going to support rendering this type of error
rendering. If you want to maintain consistency between the client side
rendered validation error messages and the server side rendered
validation error messages please use what is in
`config/initializers/client_side_validations.rb`
## Plugins ##
There is additional support for other `ActiveModel` based ORMs and other
Rails `FormBuilders`. Please see the [Plugin wiki page](https://github.com/bcardarella/client_side_validations/wiki/Plugins)
(feel free to add your own)
* [SimpleForm](https://github.com/DockYard/client_side_validations-simple_form)
* [Formtastic](https://github.com/DockYard/client_side_validations-formtastic)
* [Mongoid](https://github.com/DockYard/client_side_validations-mongoid)
* [MongoMapper](https://github.com/DockYard/client_side_validations-mongo_mapper)
* [Turbolinks](https://github.com/DockYard/client_side_validations-turbolinks)
## Usage ##
The javascript file is served up in the asset pipeline. Add the
following to your `app/assets/javascripts/application.js` file.
```javascript
//= require rails.validations
```
In your `FormBuilder` you only need to enable validations:
```erb
<%= form_for @user, :validate => true do |f| %>
...
```
That should be enough to get you going.
By default the validators will be serialized and embedded in a
`
```
This script registers a new form object on `ClientSideValidations.form`. The key is equal to the ID of the form that is rendered. The objects it contains will have different keys depending upon the `FormBuilder` being used. However, `type` and `validators` will always be present.
### `type` ###
This will always be equal to the class of the `FormBuilder` that did the rendering. The type will be used by the JavaScript to determine how to `add` and `remove` the error messages. If you create a new `FormBuilder` you will need to write your own handlers for adding and removing.
### `validators` ###
This object contains the validators for each of the inputs rendered on the `FormBuilder`. Each input is keyed to the `name` attribute and each containing validator could simply contain the error message itself or also specific options on how that validator should be run.
### Adding validators that aren't inputs ###
If you need to add more validators but don't want them rendered on the form immediately you can inject those validators with `FormBuilder#validate`:
```erb
<%= form_for @user, :validate => true do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.validate :age, :bio %>
...
```
In the above example `age` and `bio` will not render as inputs on the form but their validators will be properly added to the `validators` object for use later. If you do intend to dynamically render these inputs later the `name` attributes on the inputs will have to match with the keys on the `validators` object, and the inputs will have to be enabled for client side validation.
You can add all attributes with validators for the given object by
passing nothing:
```erb
<%= f.validate %>
```
You can also force validators similarly to the input syntax:
```erb
<%= f.validate :email, :uniqueness => false %>
```
Take care when using this method. The embedded validators are
overwritten based upon the order they are rendered. So if you do
something like:
```erb
<%= f.text_field :email, :validate => { :uniqueness => false } %>
<%= f.validate %>
```
The `uniqueness` validator will not be turned off because the options
were overwritten by the call to `FormBuilder#validate`
## Customize Error Rendering ##
`ClientSideValidations` will use `ActiveRecord::Base.field_error_proc` to render the error messages. Other `FormBuilders` will use their own settings.
If you need to change the markup of how the errors are rendered you can modify that in `config/initializers/client_side_validations.rb`
*Please Note* if you modify the markup, you will also need to modify `ClientSideValidations.formBuilders['ActionView::Helpers::FormBuilder']`'s `add` and `remove` functions. You can override the behavior by creating a new javascript file called `rails.validations.actionView.js` that contains the following:
```js
window.ClientSideValidations.formBuilders['ActionView::Helpers::FormBuilder`] = {
add: function(element, settings, message) {
// custom add code here
},
remove: function(element, settings) {
// custom remove code here
}
}
```
Please view the code in `rails.validations.js` to see how the existing `add` and `remove` functions work and how best to override for your specific use-case.
## Custom Validators ##
### Local Validators ###
Client Side Validations supports the use of custom validators. The following is an example for creating a custom validator that validates the format of email addresses.
Let's say you have several models that all have email fields and you are validating the format of that email address on each one. This is a common validation and could probably benefit from a custom validator. We're going to put the validator into `app/validators/email_validator.rb`
```ruby
class EmailValidator < ActiveModel::EachValidator
def validate_each(record, attr_name, value)
unless value =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
record.errors.add(attr_name, :email, options.merge(:value => value))
end
end
end
# This allows us to assign the validator in the model
module ActiveModel::Validations::HelperMethods
def validates_email(*attr_names)
validates_with EmailValidator, _merge_attributes(attr_names)
end
end
```
Next we need to add the error message to the Rails i18n file `config/locales/en.yml`
```yaml
# config/locales/en.yml
en:
errors:
messages:
email: "Not an email address"
```
Finally we need to add a client side validator. This can be done by hooking into the `ClientSideValidations.validator` object. Create a new file `app/assets/javascripts/rails.validations.customValidators.js`
```javascript
// The validator variable is a JSON Object
// The selector variable is a jQuery Object
window.ClientSideValidations.validators.local['email'] = function(element, options) {
// Your validator code goes in here
if (!/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i.test(element.val())) {
// When the value fails to pass validation you need to return the error message.
// It can be derived from validator.message
return options.message;
}
}
```
That's it! Now you can use the custom validator as you would any other validator in your model
```ruby
# app/models/person.rb
class Person < ActiveRecord::Base
validates_email :email
end
```
Client Side Validations will apply the new validator and validate your forms as needed.
### Remote Validators ###
A good example of a remote validator would be for Zipcodes. It wouldn't be reasonable to embed every single zipcode inline, so we'll need to check for its existence with remote javascript call back to our app. Assume we have a zipcode database mapped to the model Zipcode. The primary key is the unique zipcode. Our Rails validator would probably look something like this:
```ruby
class ZipcodeValidator < ActiveModel::EachValidator
def validate_each(record, attr_name, value)
unless ::Zipcode.where(:id => value).exists?
record.errors.add(attr_name, :zipcode, options.merge(:value => value))
end
end
end
# This allows us to assign the validator in the model
module ActiveModel::Validations::HelperMethods
def validates_zipcode(*attr_names)
validates_with ZipcodeValidator, _merge_attributes(attr_names)
end
end
```
Of course we still need to add the i18n message:
```yaml
en:
errors:
messages:
zipcode: "Not a valid US zip code"
```
And let's add the Javascript validator. Because this will be remote validator we need to add it to `ClientSideValidations.validators.remote`:
```javascript
window.ClientSideValidations.validators.remote['zipcode'] = function(element, options) {
if ($.ajax({
url: '/validators/zipcode',
data: { id: element.val() },
// async *must* be false
async: false
}).status == 404) { return options.message; }
}
```
All we're doing here is checking to see if the resource exists (in this case the given zipcode) and if it doesn't the error message is returned.
Notice that the remote call is forced to *async: false*. This is necessary and the validator may not work properly if this is left out.
Now the extra step for adding a remote validator is to add to the middleware. All ClientSideValidations middleware should inherit from `ClientSideValidations::Middleware::Base`:
```ruby
module ClientSideValidations::Middleware
class Zipcode < ClientSideValidations::Middleware::Base
def response
if ::Zipcode.where(:id => request.params[:id]).exists?
self.status = 200
else
self.status = 404
end
super
end
end
end
```
The `#response` method is always called and it should set the status accessor. Then a call to `super` is required. In the javascript we set the 'id' in the params to the value of the zipcode input, in the middleware we check to see if this zipcode exists in our zipcode database. If it does, we return 200, if it doesn't we return 404.
## Enabling, Disabling, and Resetting on the client ##
There are many reasons why you might want to enable, disable, or even completely reset the bound validation events on the client. `ClientSideValidations` offers a simple API for this.
### Enabling ###
If you have rendered a new form via AJAX into your page you will need to enable that form for validation:
```js
$(new_form).enableClientSideValidations();
```
You should attach this to an event that is fired when the new HTML renders.
You can use the same function if you introduce new inputs to an existing form:
```js
$(new_input).enableClientSideValidations();
```
### Disabling ###
If you wish to turn off validations entirely on a form:
```js
$(form).disableClientSideValidations();
```
### Resetting ###
You can reset the current state of the validations, clear all error messages, and reattach clean event handlers:
```js
$(form).resetClientSideValidations();
```
## Callbacks ##
`ClientSideValidations` will run callbacks based upon the state of the element or form. The following callbacks are supported:
* `ClientSideValidations.callbacks.element.after(element, eventData)`
* `ClientSideValidations.callbacks.element.before(element, eventData)`
* `ClientSideValidations.callbacks.element.fail(element, message, callback, eventData)`
* `ClientSideValidations.callbacks.element.pass(element, callback, eventData)`
* `ClientSideValidations.callbacks.form.after(form, eventData)`
* `ClientSideValidations.callbacks.form.before(form, eventData)`
* `ClientSideValidations.callbacks.form.fail(form, eventData)`
* `ClientSideValidations.callbacks.form.pass(form, eventData)`
The names of the callbacks should be pretty straight forward. For example, `ClientSideValidations.callbacks.form.fail` will be called if a form failed to validate. And `ClientSideValidations.callbacks.element.before` will be called before that particular element's validations are run.
All element callbacks will receive the element in a jQuery object as the first parameter and the eventData object as the second parameter. `ClientSideValidations.callbacks.element.fail()` will receive the message of the failed validation as the second parameter, the callback for adding the error fields as the third and the eventData object as the third. `ClientSideValidations.elementValidatePass()` will receive the callback for removing the error fields. The error field callbacks must be run in your custom callback in some fashion. (either after a blocking event or as a callback for another event, such as an animation)
All form callbacks will receive the form in a jQuery object as the first parameter and the eventData object as the second parameter.
Here is an example callback for sliding out the error message when the validation fails then sliding it back in when the validation passes:
``` javascript
// You will need to require 'jquery-ui' for this to work
window.ClientSideValidations.callbacks.element.fail = function(element, message, callback) {
callback();
if (element.data('valid') !== false) {
element.parent().find('.message').hide().show('slide', {direction: "left", easing: "easeOutBounce"}, 500);
}
}
window.ClientSideValidations.callbacks.element.pass = function(element, callback) {
// Take note how we're passing the callback to the hide()
// method so it is run after the animation is complete.
element.parent().find('.message').hide('slide', {direction: "left"}, 500, callback);
}
```
``` css
.message {
background-color: red;
border-bottom-right-radius: 5px 5px;
border-top-right-radius: 5px 5px;
padding: 2px 5px;
}
div.field_with_errors div.ui-effects-wrapper {
display: inline-block !important;
}
```
Finally uncomment the `ActionView::Base.field_error_proc` override in `config/initializers/client_side_validations.rb`
## Security ##
By default a uniqueness middleware is added. This can be a potential security issue. If you wish this middleware can be disabled. In `config/initializers/client_side_validations.rb` just uncomment:
```ruby
ClientSideValidations::Config.disabled_validators = [:uniqueness]
```
This will completely disable the uniqueness validator. The `FormBuilder`
will automatically skip building validators that are disabled.
## Authors ##
[Brian Cardarella](http://twitter.com/bcardarella)
[We are very thankful for the many contributors](https://github.com/bcardarella/client_side_validations/graphs/contributors)
## Versioning ##
This gem follows [Semantic Versioning](http://semver.org)
Major and minor version numbers will follow `Rails`'s major and
minor version numbers. For example,
`client_side_validations-3.2.0` will be compatible up to
`~> rails-3.2.0`
We will maintain compatibility with one minor version back. So the 3.2.0 version of
`client_side_validations` will be compatible with `~> rails-3.1.0`
Only two versions minor versions will be actively maintained.
## Want to help? ##
Please do! We are always looking to improve this gem. Please see our
[Contribution Guidelines](https://github.com/bcardarella/client_side_validations/blob/master/CONTRIBUTING.md)
on how to properly submit issues and pull requests.
## Legal ##
[DockYard](http://dockyard.com), LLC © 2012
[@dockyard](http://twitter.com/dockyard)
[Licensed under the MIT license](http://www.opensource.org/licenses/mit-license.php)
client_side_validations-3.2.6/Rakefile 0000664 0000000 0000000 00000004763 12202276743 0020065 0 ustar 00root root 0000000 0000000 require 'bundler'
require File.join(File.expand_path('..', __FILE__), 'coffeescript/processor')
Bundler::GemHelper.install_tasks
multitask :default => 'test:ruby'
require 'rake/testtask'
namespace :test do
desc %(Run all tests)
multitask :all => ['test:ruby', 'test:js']
desc %(Test Ruby code)
Rake::TestTask.new(:ruby) do |test|
test.libs << 'lib' << 'test'
test.test_files = Dir.glob("#{File.dirname(__FILE__)}/test/**/test_*.rb").sort
end
desc %(Test Javascript code)
multitask :js => ['test:server', 'test:open']
desc %(Starts the test server)
task :server do
system 'bundle exec ruby test/javascript/server.rb'
end
desc %(Starts the test server which reloads everything on each refresh)
task :reloadable do
exec "bundle exec shotgun test/javascript/config.ru -p #{PORT} --server thin"
end
task :open do
url = "http://localhost:#{PORT}"
puts "Opening test app at #{url} ..."
sleep 3
system( *browse_cmd(url) )
end
end
desc %{Regenerate and commit JavaScript file}
task :regenerate_javascript do
regenerate_javascript
end
Rake::Task[:build].instance_eval { @actions.clear }
task :build do
regenerate_javascript
perform_git_commit
Bundler::GemHelper.new(Dir.pwd).build_gem
end
def perform_git_commit
sh_with_code('git add vendor')
out, code = sh_with_code('git commit -m "Regenerated JavaScript"')
if code == 0
puts "Committed changes"
else
puts "Nothing to commit"
end
end
def regenerate_javascript
ClientSideValidations::Processor.run
puts 'Regenerated JavaScript'
end
def sh_with_code(cmd, &block)
cmd << " 2>&1"
outbuf = ''
Bundler.ui.debug(cmd)
Dir.chdir(Dir.pwd) {
outbuf = `#{cmd}`
if $? == 0
block.call(outbuf) if block
end
}
[outbuf, $?]
end
PORT = 4567
# Returns an array e.g.: ['open', 'http://example.com']
def browse_cmd(url)
require 'rbconfig'
browser = ENV['BROWSER'] ||
(RbConfig::CONFIG['host_os'].include?('darwin') && 'open') ||
(RbConfig::CONFIG['host_os'] =~ /msdos|mswin|djgpp|mingw|windows/ && 'start') ||
%w[xdg-open x-www-browser firefox opera mozilla netscape].find { |comm| which comm }
abort('ERROR: no web browser detected') unless browser
Array(browser) << url
end
# which('ruby') #=> /usr/bin/ruby
def which cmd
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
exts.each { |ext|
exe = "#{path}/#{cmd}#{ext}"
return exe if File.executable? exe
}
end
return nil
end
client_side_validations-3.2.6/client_side_validations.gemspec 0000664 0000000 0000000 00000002076 12202276743 0024637 0 ustar 00root root 0000000 0000000 # -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "client_side_validations/version"
Gem::Specification.new do |s|
s.name = "client_side_validations"
s.version = ClientSideValidations::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["Brian Cardarella"]
s.email = ["bcardarella@gmail.com"]
s.homepage = "https://github.com/bcardarella/client_side_validations"
s.summary = %q{Client Side Validations}
s.description = %q{Client Side Validations}
s.files = `git ls-files -- {lib/*,vendor/*,*.gemspec}`.split("\n")
s.require_paths = ["lib"]
s.add_development_dependency 'rails', '~> 3.2.0'
s.add_development_dependency 'sqlite3'
s.add_development_dependency 'mocha'
s.add_development_dependency 'm'
# For QUnit testing
s.add_development_dependency 'sinatra', '~> 1.0'
s.add_development_dependency 'shotgun'
s.add_development_dependency 'thin'
s.add_development_dependency 'json'
s.add_development_dependency 'coffee-script'
s.add_development_dependency 'jquery-rails'
end
client_side_validations-3.2.6/coffeescript/ 0000775 0000000 0000000 00000000000 12202276743 0021062 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/coffeescript/processor.rb 0000664 0000000 0000000 00000001413 12202276743 0023425 0 ustar 00root root 0000000 0000000 $:.unshift(File.expand_path('../../lib', __FILE__))
require 'client_side_validations/version'
require 'coffee_script'
require 'date'
require 'erb'
module ClientSideValidations
class Processor
def self.run
write_file
end
def self.root_path
File.expand_path('../..', __FILE__)
end
def self.file_name
'rails.validations'
end
def self.template
ERB.new(File.open(File.join(root_path, 'coffeescript', "#{file_name}.coffee")).read)
end
def self.compiled_coffeescript
CoffeeScript.compile(template.result(binding))
end
def self.write_file
file = File.new(File.join(root_path, "vendor/assets/javascripts/#{file_name}.js"), 'w')
file << compiled_coffeescript
file.close
end
end
end
client_side_validations-3.2.6/coffeescript/rails.validations.coffee 0000664 0000000 0000000 00000044621 12202276743 0025670 0 ustar 00root root 0000000 0000000 # Rails 3 Client Side Validations - v<%= ClientSideValidations::VERSION %>
# https://github.com/bcardarella/client_side_validations
#
# Copyright (c) <%= DateTime.now.year %> Brian Cardarella
# Licensed under the MIT license
# http://www.opensource.org/licenses/mit-license.php
$ = jQuery
$.fn.disableClientSideValidations = ->
ClientSideValidations.disable(@)
@
$.fn.enableClientSideValidations = ->
@filter(ClientSideValidations.selectors.forms).each ->
ClientSideValidations.enablers.form(@)
@filter(ClientSideValidations.selectors.inputs).each ->
ClientSideValidations.enablers.input(@)
@
$.fn.resetClientSideValidations = ->
@filter(ClientSideValidations.selectors.forms).each ->
ClientSideValidations.reset(@)
@
$.fn.validate = ->
@filter(ClientSideValidations.selectors.forms).each ->
$(@).enableClientSideValidations()
@
$.fn.isValid = (validators) ->
obj = $(@[0])
if obj.is('form')
validateForm(obj, validators)
else
validateElement(obj, validatorsFor(@[0].name, validators))
validatorsFor = (name, validators) ->
if captures = name.match /\[(\w+_attributes)\].*\[(\w+)\]$/
for validator_name, validator of validators
if validator_name.match "\\[#{captures[1]}\\].*\\[\\]\\[#{captures[2]}\\]$"
name = name.replace /\[[\da-z_]+\]\[(\w+)\]$/g, "[][$1]"
validators[name] || {}
validateForm = (form, validators) ->
form.trigger('form:validate:before.ClientSideValidations')
valid = true
form.find(ClientSideValidations.selectors.validate_inputs).each ->
valid = false unless $(@).isValid(validators)
# we don't want the loop to break out by mistake
true
if valid then form.trigger('form:validate:pass.ClientSideValidations') else form.trigger('form:validate:fail.ClientSideValidations')
form.trigger('form:validate:after.ClientSideValidations')
valid
validateElement = (element, validators) ->
element.trigger('element:validate:before.ClientSideValidations')
passElement = ->
element.trigger('element:validate:pass.ClientSideValidations').data('valid', null)
failElement = (message) ->
element.trigger('element:validate:fail.ClientSideValidations', message).data('valid', false)
false
afterValidate = ->
element.trigger('element:validate:after.ClientSideValidations').data('valid') != false
executeValidators = (context) ->
valid = true
for kind, fn of context
if validators[kind]
for validator in validators[kind]
if message = fn.call(context, element, validator)
valid = failElement(message)
break
unless valid
break
valid
# if _destroy for this input group == "1" pass with flying colours, it'll get deleted anyway..
destroyInputName = element.attr('name').replace(/\[([^\]]*?)\]$/, '[_destroy]')
if $("input[name='#{destroyInputName}']").val() == "1"
passElement()
return afterValidate()
# if the value hasn't changed since last validation, do nothing
unless element.data('changed') != false
return afterValidate()
element.data('changed', false)
local = ClientSideValidations.validators.local
remote = ClientSideValidations.validators.remote
if executeValidators(local) and executeValidators(remote)
passElement()
afterValidate()
if window.ClientSideValidations == undefined
window.ClientSideValidations = {}
if window.ClientSideValidations.forms == undefined
window.ClientSideValidations.forms = {}
window.ClientSideValidations.selectors =
inputs: ':input:not(button):not([type="submit"])[name]:visible:enabled'
validate_inputs: ':input:enabled:visible[data-validate]'
forms: 'form[data-validate]'
window.ClientSideValidations.reset = (form) ->
$form = $(form)
ClientSideValidations.disable(form)
for key of form.ClientSideValidations.settings.validators
form.ClientSideValidations.removeError($form.find("[name='#{key}']"))
ClientSideValidations.enablers.form(form)
window.ClientSideValidations.disable = (target) ->
$target = $(target)
$target.off('.ClientSideValidations')
if $target.is('form')
ClientSideValidations.disable($target.find(':input'))
else
$target.removeData('valid')
$target.removeData('changed')
$target.filter(':input').each ->
$(@).removeAttr('data-validate')
window.ClientSideValidations.enablers =
form: (form) ->
$form = $(form)
form.ClientSideValidations =
settings: window.ClientSideValidations.forms[$form.attr('id')]
addError: (element, message) ->
ClientSideValidations.formBuilders[form.ClientSideValidations.settings.type].add(element, form.ClientSideValidations.settings, message)
removeError: (element) ->
ClientSideValidations.formBuilders[form.ClientSideValidations.settings.type].remove(element, form.ClientSideValidations.settings)
# Set up the events for the form
$form.on(event, binding) for event, binding of {
'submit.ClientSideValidations' : (eventData) ->
unless $form.isValid(form.ClientSideValidations.settings.validators)
eventData.preventDefault()
eventData.stopImmediatePropagation()
'ajax:beforeSend.ClientSideValidations' : (eventData) -> $form.isValid(form.ClientSideValidations.settings.validators) if eventData.target == @
'form:validate:after.ClientSideValidations' : (eventData) -> ClientSideValidations.callbacks.form.after( $form, eventData)
'form:validate:before.ClientSideValidations': (eventData) -> ClientSideValidations.callbacks.form.before($form, eventData)
'form:validate:fail.ClientSideValidations' : (eventData) -> ClientSideValidations.callbacks.form.fail( $form, eventData)
'form:validate:pass.ClientSideValidations' : (eventData) -> ClientSideValidations.callbacks.form.pass( $form, eventData)
}
$form.find(ClientSideValidations.selectors.inputs).each ->
ClientSideValidations.enablers.input(@)
input: (input) ->
$input = $(input)
form = input.form
$form = $(form)
$input.filter(':not(:radio):not([id$=_confirmation])')
.each ->
$(@).attr('data-validate', true)
.on(event, binding) for event, binding of {
'focusout.ClientSideValidations': ->
$(@).isValid(form.ClientSideValidations.settings.validators)
'change.ClientSideValidations': -> $(@).data('changed', true)
# Callbacks
'element:validate:after.ClientSideValidations': (eventData) -> ClientSideValidations.callbacks.element.after($(@), eventData)
'element:validate:before.ClientSideValidations': (eventData) -> ClientSideValidations.callbacks.element.before($(@), eventData)
'element:validate:fail.ClientSideValidations': (eventData, message) ->
element = $(@)
ClientSideValidations.callbacks.element.fail(element, message, ->
form.ClientSideValidations.addError(element, message)
, eventData)
'element:validate:pass.ClientSideValidations': (eventData) ->
element = $(@)
ClientSideValidations.callbacks.element.pass(element, ->
form.ClientSideValidations.removeError(element)
, eventData)
}
$input.filter(':checkbox').on('click.ClientSideValidations', ->
$(@).isValid(form.ClientSideValidations.settings.validators)
# If we don't return true here the checkbox will immediately uncheck itself.
return true
)
# Inputs for confirmations
$input.filter('[id$=_confirmation]').each ->
confirmationElement = $(@)
element = $form.find("##{@id.match(/(.+)_confirmation/)[1]}:input")
if element[0]
$("##{confirmationElement.attr('id')}").on(event, binding) for event, binding of {
'focusout.ClientSideValidations': -> element.data('changed', true).isValid(form.ClientSideValidations.settings.validators)
'keyup.ClientSideValidations' : -> element.data('changed', true).isValid(form.ClientSideValidations.settings.validators)
}
window.ClientSideValidations.validators =
all: -> jQuery.extend({}, ClientSideValidations.validators.local, ClientSideValidations.validators.remote)
local:
presence: (element, options) ->
options.message if /^\s*$/.test(element.val() || '')
acceptance: (element, options) ->
switch element.attr('type')
when 'checkbox'
unless element.prop('checked')
return options.message
when 'text'
if element.val() != (options.accept?.toString() || '1')
return options.message
format: (element, options) ->
message = @presence(element, options)
if message
return if options.allow_blank == true
return message
return options.message if options.with and !options.with.test(element.val())
return options.message if options.without and options.without.test(element.val())
numericality: (element, options) ->
val = jQuery.trim(element.val())
unless ClientSideValidations.patterns.numericality.test(val)
return if options.allow_blank == true and @presence(element, {message: options.messages.numericality})
return options.messages.numericality
val = val.replace(new RegExp("\\#{ClientSideValidations.number_format.delimiter}",'g'),"").replace(new RegExp("\\#{ClientSideValidations.number_format.separator}",'g'),".")
if options.only_integer and !/^[+-]?\d+$/.test(val)
return options.messages.only_integer
CHECKS =
greater_than: '>'
greater_than_or_equal_to: '>='
equal_to: '=='
less_than: '<'
less_than_or_equal_to: '<='
form = $(element[0].form)
# options[check] may be 0 so we must check for undefined
for check, operator of CHECKS when options[check]?
if !isNaN(parseFloat(options[check])) && isFinite(options[check])
check_value = options[check]
else if form.find("[name*=#{options[check]}]").size() == 1
check_value = form.find("[name*=#{options[check]}]").val()
else
return
fn = new Function("return #{val} #{operator} #{check_value}")
return options.messages[check] unless fn()
if options.odd and !(parseInt(val, 10) % 2)
return options.messages.odd
if options.even and (parseInt(val, 10) % 2)
return options.messages.even
length: (element, options) ->
tokenizer = options.js_tokenizer || "split('')"
tokenized_length = new Function('element', "return (element.val().#{tokenizer} || '').length")(element)
CHECKS =
is: '=='
minimum: '>='
maximum: '<='
blankOptions = {}
blankOptions.message = if options.is
options.messages.is
else if options.minimum
options.messages.minimum
message = @presence(element, blankOptions)
if message
return if options.allow_blank == true
return message
for check, operator of CHECKS when options[check]
fn = new Function("return #{tokenized_length} #{operator} #{options[check]}")
return options.messages[check] unless fn()
exclusion: (element, options) ->
message = @presence(element, options)
if message
return if options.allow_blank == true
return message
if options.in
return options.message if element.val() in (option.toString() for option in options.in)
if options.range
lower = options.range[0]
upper = options.range[1]
return options.message if element.val() >= lower and element.val() <= upper
inclusion: (element, options) ->
message = @presence(element, options)
if message
return if options.allow_blank == true
return message
if options.in
return if element.val() in (option.toString() for option in options.in)
return options.message
if options.range
lower = options.range[0]
upper = options.range[1]
return if element.val() >= lower and element.val() <= upper
return options.message
confirmation: (element, options) ->
if element.val() != jQuery("##{element.attr('id')}_confirmation").val()
return options.message
uniqueness: (element, options) ->
name = element.attr('name')
# only check uniqueness if we're in a nested form
if /_attributes\]\[\d/.test(name)
matches = name.match(/^(.+_attributes\])\[\d+\](.+)$/)
name_prefix = matches[1]
name_suffix = matches[2]
value = element.val()
if name_prefix && name_suffix
form = element.closest('form')
valid = true
form.find(':input[name^="' + name_prefix + '"][name$="' + name_suffix + '"]').each ->
if $(@).attr('name') != name
if $(@).val() == value
valid = false
$(@).data('notLocallyUnique', true)
else
# items that were locally non-unique which become locally unique need to be
# marked as changed, so they will get revalidated and thereby have their
# error state cleared. but we should only do this once; therefore the
# notLocallyUnique flag.
if $(this).data('notLocallyUnique')
$(this)
.removeData('notLocallyUnique')
.data('changed', true)
if(!valid)
return options.message
remote:
uniqueness: (element, options) ->
message = ClientSideValidations.validators.local.presence(element, options)
if message
return if options.allow_blank == true
return message
data = {}
data.case_sensitive = !!options.case_sensitive
data.id = options.id if options.id
if options.scope
data.scope = {}
for key, scope_value of options.scope
scoped_name = element.attr('name').replace(/\[\w+\]$/, "[#{key}]")
scoped_element = jQuery("[name='#{scoped_name}']")
jQuery("[name='#{scoped_name}']:checkbox").each ->
if @.checked
scoped_element = @
if scoped_element[0] and scoped_element.val() != scope_value
data.scope[key] = scoped_element.val()
scoped_element.unbind("change.#{element.id}").bind "change.#{element.id}", ->
element.trigger('change.ClientSideValidations')
element.trigger('focusout.ClientSideValidations')
else
data.scope[key] = scope_value
# Kind of a hack but this will isolate the resource name and attribute.
# e.g. user[records_attributes][0][title] => records[title]
# e.g. user[record_attributes][title] => record[title]
# Server side handles classifying the resource properly
if /_attributes\]/.test(element.attr('name'))
name = element.attr('name').match(/\[\w+_attributes\]/g).pop().match(/\[(\w+)_attributes\]/).pop()
name += /(\[\w+\])$/.exec(element.attr('name'))[1]
else
name = element.attr('name')
# Override the name if a nested module class is passed
name = options['class'] + '[' + name.split('[')[1] if options['class']
data[name] = element.val()
if jQuery.ajax({
url: ClientSideValidations.remote_validators_url_for('uniqueness')
data: data,
async: false
cache: false
}).status == 200
return options.message
window.ClientSideValidations.remote_validators_url_for = (validator) ->
if ClientSideValidations.remote_validators_prefix?
"//#{window.location.host}/#{ClientSideValidations.remote_validators_prefix}/validators/#{validator}"
else
"//#{window.location.host}/validators/#{validator}"
window.ClientSideValidations.disableValidators = () ->
return if window.ClientSideValidations.disabled_validators == undefined
for validator, func of window.ClientSideValidations.validators.remote
if validator in window.ClientSideValidations.disabled_validators
delete window.ClientSideValidations.validators.remote[validator]
window.ClientSideValidations.formBuilders =
'ActionView::Helpers::FormBuilder':
add: (element, settings, message) ->
form = $(element[0].form)
if element.data('valid') != false and not form.find("label.message[for='#{element.attr('id')}']")[0]?
inputErrorField = jQuery(settings.input_tag)
labelErrorField = jQuery(settings.label_tag)
label = form.find("label[for='#{element.attr('id')}']:not(.message)")
element.attr('autofocus', false) if element.attr('autofocus')
element.before(inputErrorField)
inputErrorField.find('span#input_tag').replaceWith(element)
inputErrorField.find('label.message').attr('for', element.attr('id'))
labelErrorField.find('label.message').attr('for', element.attr('id'))
labelErrorField.insertAfter(label)
labelErrorField.find('label#label_tag').replaceWith(label)
form.find("label.message[for='#{element.attr('id')}']").text(message)
remove: (element, settings) ->
form = $(element[0].form)
errorFieldClass = jQuery(settings.input_tag).attr('class')
inputErrorField = element.closest(".#{errorFieldClass.replace(" ", ".")}")
label = form.find("label[for='#{element.attr('id')}']:not(.message)")
labelErrorField = label.closest(".#{errorFieldClass}")
if inputErrorField[0]
inputErrorField.find("##{element.attr('id')}").detach()
inputErrorField.replaceWith(element)
label.detach()
labelErrorField.replaceWith(label)
window.ClientSideValidations.patterns =
numericality: /^(-|\+)?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d*)?$/
window.ClientSideValidations.callbacks =
element:
after: (element, eventData) ->
before: (element, eventData) ->
fail: (element, message, addError, eventData) -> addError()
pass: (element, removeError, eventData) -> removeError()
form:
after: (form, eventData) ->
before: (form, eventData) ->
fail: (form, eventData) ->
pass: (form, eventData) ->
# Main hook
# If new forms are dynamically introduced into the DOM the .validate() method
# must be invoked on that form
$(->
ClientSideValidations.disableValidators()
$(ClientSideValidations.selectors.forms).validate()
)
client_side_validations-3.2.6/lib/ 0000775 0000000 0000000 00000000000 12202276743 0017154 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/client_side_validations.rb 0000664 0000000 0000000 00000000717 12202276743 0024365 0 ustar 00root root 0000000 0000000 module ClientSideValidations
end
require 'client_side_validations/config'
require 'client_side_validations/active_model' if defined?(::ActiveModel)
require 'client_side_validations/active_record' if defined?(::ActiveRecord)
require 'client_side_validations/action_view' if defined?(::ActionView)
if defined?(::Rails)
require 'client_side_validations/generators'
require 'client_side_validations/middleware'
require 'client_side_validations/engine'
end
client_side_validations-3.2.6/lib/client_side_validations/ 0000775 0000000 0000000 00000000000 12202276743 0024033 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/client_side_validations/action_view.rb 0000664 0000000 0000000 00000001101 12202276743 0026660 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActionView
module Helpers
end
end
require 'client_side_validations/core_ext'
require 'client_side_validations/action_view/form_helper'
require 'client_side_validations/action_view/form_tag_helper'
require 'client_side_validations/action_view/form_builder'
ActionView::Base.send(:include, ClientSideValidations::ActionView::Helpers::FormHelper)
ActionView::Base.send(:include, ClientSideValidations::ActionView::Helpers::FormTagHelper)
ActionView::Helpers::FormBuilder.send(:include, ClientSideValidations::ActionView::Helpers::FormBuilder)
client_side_validations-3.2.6/lib/client_side_validations/action_view/ 0000775 0000000 0000000 00000000000 12202276743 0026342 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/client_side_validations/action_view/form_builder.rb 0000664 0000000 0000000 00000012276 12202276743 0031350 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActionView::Helpers
module FormBuilder
def self.included(base)
(base.field_helpers.map(&:to_s) - %w(apply_form_for_options! label check_box radio_button fields_for hidden_field)).each do |selector|
base.class_eval <<-RUBY_EVAL
def #{selector}_with_client_side_validations(method, options = {})
build_validation_options(method, options)
options.delete(:validate)
#{selector}_without_client_side_validations(method, options)
end
RUBY_EVAL
base.class_eval { alias_method_chain selector, :client_side_validations }
end
base.class_eval do
alias_method_chain :initialize, :client_side_validations
alias_method_chain :fields_for, :client_side_validations
alias_method_chain :check_box, :client_side_validations
alias_method_chain :radio_button, :client_side_validations
alias_method_chain :select, :client_side_validations
alias_method_chain :collection_select, :client_side_validations
alias_method_chain :grouped_collection_select, :client_side_validations
alias_method_chain :time_zone_select, :client_side_validations
def client_side_form_settings(options, form_helper)
{
:type => self.class.to_s,
:input_tag => form_helper.class.field_error_proc.call(%{ }, Struct.new(:error_message, :tag_id).new([], "")),
:label_tag => form_helper.class.field_error_proc.call(%{ }, Struct.new(:error_message, :tag_id).new([], ""))
}
end
end
end
def validate(*attrs)
options = attrs.pop if attrs.last.is_a?(Hash)
(attrs.present? ? attrs : @object._validators.keys).each do |attr|
build_validation_options(attr, :validate => options)
end
nil
end
def initialize_with_client_side_validations(object_name, object, template, options, proc)
initialize_without_client_side_validations(object_name, object, template, options, proc)
@options[:validators] = { object => {} }
end
def fields_for_with_client_side_validations(record_or_name_or_array, *args, &block)
options = args.extract_options!
options[:validate] ||= @options[:validate] if @options[:validate] && !options.key?(:validate)
fields_for_without_client_side_validations(record_or_name_or_array, *(args << options), &block)
end
def check_box_with_client_side_validations(method, options = {}, checked_value = "1", unchecked_value = "0")
build_validation_options(method, options)
options.delete(:validate)
check_box_without_client_side_validations(method, options, checked_value, unchecked_value)
end
def radio_button_with_client_side_validations(method, tag_value, options = {})
build_validation_options(method, options)
options.delete(:validate)
radio_button_without_client_side_validations(method, tag_value, options)
end
def select_with_client_side_validations(method, choices, options = {}, html_options = {})
build_validation_options(method, html_options.merge(:name => options[:name]))
html_options.delete(:validate)
select_without_client_side_validations(method, choices, options, html_options)
end
def collection_select_with_client_side_validations(method, collection, value_method, text_method, options = {}, html_options = {})
build_validation_options(method, html_options.merge(:name => options[:name]))
html_options.delete(:validate)
collection_select_without_client_side_validations(method, collection, value_method, text_method, options, html_options)
end
def grouped_collection_select_with_client_side_validations(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
build_validation_options(method, html_options.merge(:name => options[:name]))
html_options.delete(:validate)
grouped_collection_select_without_client_side_validations(method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
end
def time_zone_select_with_client_side_validations(method, priority_zones = nil, options = {}, html_options = {})
build_validation_options(method, html_options.merge(:name => options[:name]))
html_options.delete(:validate)
time_zone_select_without_client_side_validations(method, priority_zones, options, html_options)
end
private
def build_validation_options(method, options = {})
if @options[:validate]
index = @default_options[:index].present? ? "[#{@default_options[:index]}]" : ''
name = options[:name] || "#{@object_name}#{index}[#{method}]"
child_index = @options[:child_index] ? "(\\d+|#{Regexp.escape(@options[:child_index].to_s)})" : "\\d+"
name = name.to_s.gsub(/_attributes\]\[#{child_index}\]/, '_attributes][]')
name = "#{name}#{options[:multiple] ? "[]" : nil}"
@options[:validators][@object][method] = { :name => name, :options => options[:validate] }
end
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/action_view/form_helper.rb 0000664 0000000 0000000 00000013003 12202276743 0031166 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActionView::Helpers
module FormHelper
class Error < StandardError; end
def form_for(record, *args, &block)
options = args.extract_options!
if options[:validate]
# Always turn off HTML5 Validations
options[:html] ||= {}
options[:html][:novalidate] = 'novalidate'
case record
when String, Symbol
raise ClientSideValidations::ActionView::Helpers::FormHelper::Error, 'Using form_for(:name, @resource) is not supported with ClientSideValidations. Please use form_for(@resource, :as => :name) instead.'
else
object = record.is_a?(Array) ? record.last : record
end
end
@validators = {}
# Order matters here. Rails mutates the options object
html_id = options[:html][:id] if options[:html]
form = super(record, *(args << options), &block)
build_bound_validators(options)
options[:id] = html_id if html_id
script = client_side_form_settings(object, options)
# Because of the load order requirement above this sub is necessary
# Would be nice to not do this
script = insert_validators_into_script(script)
if assign_script_to_content_for(options[:validate], script)
form.html_safe
else
"#{form}#{script}".html_safe
end
end
def assign_script_to_content_for(name, script)
if name && name != true
content_for(name) { script.html_safe }
true
end
end
def apply_form_for_options!(object_or_array, options)
super
options[:html][:validate] = true if options[:validate]
end
def fields_for(record_or_name_or_array, record_object = nil, options = {}, &block)
output = super
build_bound_validators(options)
output
end
private
def build_bound_validators(options)
if @validators
options[:validators].each do |key, value|
if @validators.key?(key)
@validators[key].merge! value
else
@validators[key] = value
end
end
end
end
def insert_validators_into_script(script)
# There is probably a more performant way of doing this
# But using String#sub has some issues. Undocumented "features"
if script
script = script.split(/"validator_hash"/)
script = "#{script[0]}#{construct_validators.to_json}#{script[1]}"
end
script
end
def construct_validators
@validators.inject({}) do |validator_hash, object_opts|
option_hash = object_opts[1].inject({}) do |option_hash, attr|
option_hash.merge!(attr[0] => attr[1][:options])
end
if object_opts[0].respond_to?(:client_side_validation_hash)
validation_hash = object_opts[0].client_side_validation_hash(option_hash)
else
validation_hash = {}
end
option_hash.each_key do |attr|
if validation_hash[attr]
validator_hash.merge!(object_opts[1][attr][:name] => validation_hash[attr])
end
end
validator_hash
end
end
def client_side_form_settings(object, options)
if options[:validate]
builder = options[:parent_builder]
if options[:id]
var_name = options[:id]
else
if Rails.version >= '3.2.0'
var_name = if object.respond_to?(:persisted?) && object.persisted?
options[:as] ? "edit_#{options[:as]}" : [options[:namespace], dom_id(object, :edit)].compact.join("_")
else
options[:as] ? "new_#{options[:as]}" : [options[:namespace], dom_id(object)].compact.join("_")
end
else
# This is to maintain backward compatibility with Rails 3.1
# see: https://github.com/rails/rails/commit/e29773f885fd500189ffd964550ae20061d745ba#commitcomment-948052
var_name = if object.respond_to?(:persisted?) && object.persisted?
options[:as] ? "#{options[:as]}_edit" : dom_id(object, :edit)
else
options[:as] ? "#{options[:as]}_new" : dom_id(object)
end
end
end
if ClientSideValidations::Config.number_format_with_locale and defined?(I18n)
number_format = I18n.t("number.format").slice(:separator, :delimiter)
else
number_format = {:separator=>".", :delimiter=>","}
end
patterns = {:numericality=>"/^(-|\\+)?(?:\\d+|\\d{1,3}(?:\\#{number_format[:delimiter]}\\d{3})+)(?:\\#{number_format[:separator]}\\d*)?$/"}
content_tag(:script) do
"// 'validator_hash').to_json};\n//]]>".html_safe
end
end
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/action_view/form_tag_helper.rb 0000664 0000000 0000000 00000000637 12202276743 0032032 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActionView::Helpers
module FormTagHelper
private
def html_options_for_form(url_for_options, options, *parameters_for_url)
options.stringify_keys!
html_options = {}
html_options['data-validate'] = options.delete('validate') if options['validate']
html_options.merge!(super(url_for_options, options, *parameters_for_url))
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/active_model.rb 0000664 0000000 0000000 00000010107 12202276743 0027012 0 ustar 00root root 0000000 0000000 require 'client_side_validations/core_ext'
module ClientSideValidations::ActiveModel
module Validator
def client_side_hash(model, attribute, force = nil)
build_client_side_hash(model, attribute, self.options.dup)
end
def copy_conditional_attributes(to, from)
[:if, :unless].each { |key| to[key] = from[key] if from[key].present? }
end
private
def build_client_side_hash(model, attribute, options)
{ :message => model.errors.generate_message(attribute, message_type, options) }.merge(options.except(*::ActiveModel::Errors::CALLBACKS_OPTIONS - [:allow_blank, :if, :unless]))
end
def message_type
kind
end
end
module Validations
def client_side_validation_hash(force = nil)
_validators.inject({}) do |attr_hash, attr|
unless [nil, :block].include?(attr[0])
validator_hash = attr[1].inject(Hash.new { |h,k| h[k] = []}) do |kind_hash, validator|
if can_use_for_client_side_validation?(attr[0], validator, force)
if client_side_hash = validator.client_side_hash(self, attr[0], extract_force_option(attr[0], force))
kind_hash[validator.kind] << client_side_hash.except(:on, :if, :unless)
end
end
kind_hash
end
if validator_hash.present?
attr_hash.merge!(attr[0] => validator_hash)
else
attr_hash
end
else
attr_hash
end
end
end
private
def extract_force_option(attr, force)
case force
when FalseClass, TrueClass, NilClass
force
when Hash
extract_force_option(nil, force[attr])
else
nil
end
end
def can_use_for_client_side_validation?(attr, validator, force)
if validator_turned_off?(attr, validator, force)
result = false
else
# Yeah yeah, #new_record? is not part of ActiveModel :p
result = ((self.respond_to?(:new_record?) && validator.options[:on] == (self.new_record? ? :create : :update)) || validator.options[:on].nil?)
result = result && validator.kind != :block
if validator.options[:if] || validator.options[:unless]
if validator.options[:if] && validator.options[:if] =~ /changed\?/
result = true
else result = can_force_validator?(attr, validator, force)
if validator.options[:if]
result = result && run_conditional(validator.options[:if])
end
if validator.options[:unless]
result = result && !run_conditional(validator.options[:unless])
end
end
end
end
result
end
def run_conditional(method_name_value_or_proc)
if method_name_value_or_proc.respond_to?(:call)
method_name_value_or_proc.call(self)
else
self.send(method_name_value_or_proc)
end
end
def validator_turned_off?(attr, validator, force)
case force
when FalseClass
true
when Hash
case force[attr]
when FalseClass
true
when Hash
force[attr][validator.kind] == false
else
false
end
else
::ClientSideValidations::Config.disabled_validators.include?(validator.kind)
end
end
def can_force_validator?(attr, validator, force)
case force
when TrueClass
true
when Hash
case force[attr]
when TrueClass
true
when Hash
force[attr][validator.kind]
else
false
end
else
false
end
end
end
end
ActiveModel::Validator.send(:include, ClientSideValidations::ActiveModel::Validator)
ActiveModel::Validations.send(:include, ClientSideValidations::ActiveModel::Validations)
%w{acceptance exclusion inclusion length format numericality presence}.each do |validator|
require "client_side_validations/active_model/#{validator}"
validator.capitalize!
eval "ActiveModel::Validations::#{validator}Validator.send(:include, ClientSideValidations::ActiveModel::#{validator})"
end
client_side_validations-3.2.6/lib/client_side_validations/active_model/ 0000775 0000000 0000000 00000000000 12202276743 0026466 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/client_side_validations/active_model/acceptance.rb 0000664 0000000 0000000 00000000203 12202276743 0031074 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActiveModel
module Acceptance
private
def message_type
:accepted
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/active_model/exclusion.rb 0000664 0000000 0000000 00000001130 12202276743 0031017 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActiveModel
module Exclusion
def client_side_hash(model, attribute, force = nil)
if options[:in].respond_to?(:call)
if force
options = self.options.dup
options[:in] = options[:in].call(model)
hash = build_client_side_hash(model, attribute, options)
else
return
end
else
hash = build_client_side_hash(model, attribute, self.options.dup)
end
if hash[:in].is_a?(Range)
hash[:range] = hash[:in]
hash.delete(:in)
end
hash
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/active_model/format.rb 0000664 0000000 0000000 00000001277 12202276743 0030312 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActiveModel
module Format
def client_side_hash(model, attribute, force = nil)
options = self.options.dup
if options[:with].respond_to?(:call)
if force
options[:with] = options[:with].call(model)
build_client_side_hash(model, attribute, options)
else
return
end
elsif options[:without].respond_to?(:call)
if force
options[:without] = options[:without].call(model)
build_client_side_hash(model, attribute, options)
else
return
end
else
super
end
end
private
def message_type
:invalid
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/active_model/inclusion.rb 0000664 0000000 0000000 00000001127 12202276743 0031017 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActiveModel
module Inclusion
def client_side_hash(model, attribute, force = nil)
if options[:in].respond_to?(:call)
if force
options = self.options.dup
options[:in] = options[:in].call(model)
hash = build_client_side_hash(model, attribute, options)
else
return
end
else
hash = build_client_side_hash(model, attribute, self.options.dup)
end
if hash[:in].is_a?(Range)
hash[:range] = hash[:in]
hash.delete(:in)
end
hash
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/active_model/length.rb 0000664 0000000 0000000 00000001462 12202276743 0030277 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActiveModel
module Length
def client_side_hash(model, attribute, force = nil)
options = self.options.dup
hash = { :messages => {} }
hash[:js_tokenizer] = options[:js_tokenizer] if options[:js_tokenizer]
hash[:allow_blank] = true if options[:allow_blank]
self.class::MESSAGES.each do |option, message_type|
if count = options[option]
options[:message] = options[message_type] if options[message_type].present?
options.delete(:message) if options[:message].nil?
hash[:messages][option] = model.errors.generate_message(attribute, message_type, options.merge(:count => count))
hash[option] = count
end
end
copy_conditional_attributes(hash, options)
hash
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/active_model/numericality.rb 0000664 0000000 0000000 00000002257 12202276743 0031526 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActiveModel
module Numericality
OPTION_MAP = {}
def self.included(base)
OPTION_MAP.merge!(base::CHECKS.keys.inject({}) { |hash, key| hash.merge!(key => key) })
end
def client_side_hash(model, attribute, force = nil)
options = self.options.dup
hash = { :messages => { :numericality => model.errors.generate_message(attribute, :not_a_number, options) } }
if options[:only_integer]
hash[:messages][:only_integer] = model.errors.generate_message(attribute, :not_an_integer, options)
hash[:only_integer] = true
end
hash[:allow_blank] = true if options[:allow_nil] || options[:allow_blank]
OPTION_MAP.each do |option, message_type|
if count = options[option]
if count.respond_to?(:call)
if force
count = count.call(model)
else
next
end
end
hash[:messages][option] = model.errors.generate_message(attribute, message_type, options.merge(:count => count))
hash[option] = count
end
end
copy_conditional_attributes(hash, options)
hash
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/active_model/presence.rb 0000664 0000000 0000000 00000000176 12202276743 0030623 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActiveModel
module Presence
private
def message_type
:blank
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/active_record.rb 0000664 0000000 0000000 00000001122 12202276743 0027165 0 ustar 00root root 0000000 0000000 require 'client_side_validations/active_model'
require 'client_side_validations/middleware'
require 'client_side_validations/active_record/middleware'
%w{uniqueness}.each do |validator|
require "client_side_validations/active_record/#{validator}"
validator.capitalize!
eval "ActiveRecord::Validations::#{validator}Validator.send(:include, ClientSideValidations::ActiveRecord::#{validator})"
end
ActiveRecord::Base.send(:include, ClientSideValidations::ActiveModel::Validations)
ClientSideValidations::Middleware::Uniqueness.register_orm(ClientSideValidations::ActiveRecord::Middleware)
client_side_validations-3.2.6/lib/client_side_validations/active_record/ 0000775 0000000 0000000 00000000000 12202276743 0026644 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/client_side_validations/active_record/middleware.rb 0000664 0000000 0000000 00000003501 12202276743 0031305 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActiveRecord
class Middleware
def self.is_class?(klass)
klass.abstract_class.blank? && klass < ::ActiveRecord::Base
end
def self.is_unique?(klass, attribute, value, params)
klass = find_topmost_superclass(klass)
value = type_cast_value(klass, attribute, value)
column = klass.columns_hash[attribute.to_s]
value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s if column.text?
t = klass.arel_table
if params[:case_sensitive] == 'true'
if t.engine.connection.adapter_name =~ /^mysql/i
relation = Arel::Nodes::SqlLiteral.new("BINARY #{t[attribute].eq(value).to_sql}")
else
relation = t[attribute].eq(value)
end
else
relation = t[attribute].matches(value)
end
if relation.is_a?(Arel::Nodes::SqlLiteral)
relation = Arel::Nodes::SqlLiteral.new("BINARY #{t[attribute].eq(value).to_sql} AND #{t[klass.primary_key].not_eq(params[:id]).to_sql}")
else
relation = relation.and(t[klass.primary_key].not_eq(params[:id])) if params[:id]
end
(params[:scope] || {}).each do |attribute, value|
value = type_cast_value(klass, attribute, value)
if relation.is_a?(Arel::Nodes::SqlLiteral)
relation = Arel::Nodes::SqlLiteral.new("#{relation} AND #{t[attribute].eq(value).to_sql}")
else
relation = relation.and(t[attribute].eq(value))
end
end
!klass.where(relation).exists?
end
private
def self.type_cast_value(klass, attribute, value)
klass.columns_hash[attribute].type_cast(value)
end
def self.find_topmost_superclass(klass)
if is_class?(klass.superclass)
find_topmost_superclass(klass.superclass)
else
klass
end
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/active_record/uniqueness.rb 0000664 0000000 0000000 00000002004 12202276743 0031364 0 ustar 00root root 0000000 0000000 module ClientSideValidations::ActiveRecord
module Uniqueness
def client_side_hash(model, attribute, force = nil)
hash = {}
hash[:message] = model.errors.generate_message(attribute, message_type, options.except(:scope))
hash[:case_sensitive] = options[:case_sensitive]
hash[:id] = model.id unless model.new_record?
hash[:allow_blank] = true if options[:allow_blank]
if options.key?(:client_validations) && options[:client_validations].key?(:class)
hash[:class] = options[:client_validations][:class].underscore
elsif model.class.name.demodulize != model.class.name
hash[:class] = model.class.name.underscore
end
if options.key?(:scope) && options[:scope].present?
hash[:scope] = Array.wrap(options[:scope]).inject({}) do |scope_hash, scope_item|
scope_hash.merge!(scope_item => model.send(scope_item))
end
end
hash
end
private
def message_type
:taken
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/config.rb 0000664 0000000 0000000 00000000457 12202276743 0025633 0 ustar 00root root 0000000 0000000 module ClientSideValidations
module Config
class << self
attr_accessor :disabled_validators
attr_accessor :number_format_with_locale
attr_accessor :root_path
end
self.disabled_validators = []
self.number_format_with_locale = false
self.root_path = nil
end
end
client_side_validations-3.2.6/lib/client_side_validations/core_ext.rb 0000664 0000000 0000000 00000000201 12202276743 0026161 0 ustar 00root root 0000000 0000000 require 'active_support/json'
require 'client_side_validations/core_ext/range'
require 'client_side_validations/core_ext/regexp'
client_side_validations-3.2.6/lib/client_side_validations/core_ext/ 0000775 0000000 0000000 00000000000 12202276743 0025643 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/client_side_validations/core_ext/range.rb 0000664 0000000 0000000 00000000207 12202276743 0027263 0 ustar 00root root 0000000 0000000 class Range
def as_json(options = nil)
[first, last]
end
def to_json(options = nil)
as_json(options).inspect
end
end
client_side_validations-3.2.6/lib/client_side_validations/core_ext/regexp.rb 0000664 0000000 0000000 00000000525 12202276743 0027464 0 ustar 00root root 0000000 0000000 class Regexp
def as_json(options = nil)
Regexp.new inspect.sub('\\A','^').sub('\\Z','$').sub('\\z','$').sub(/^\//,'').sub(/\/[a-z]*$/,'').gsub(/\(\?#.+\)/, '').gsub(/\(\?-\w+:/,'(').gsub(/\s/,''), self.options & 5
end
def to_json(options = nil)
as_json(options).inspect
end
def encode_json(encoder)
inspect
end
end
client_side_validations-3.2.6/lib/client_side_validations/engine.rb 0000664 0000000 0000000 00000000225 12202276743 0025624 0 ustar 00root root 0000000 0000000 module ClientSideValidations
class Engine < ::Rails::Engine
config.app_middleware.use ClientSideValidations::Middleware::Validators
end
end
client_side_validations-3.2.6/lib/client_side_validations/files.rb 0000664 0000000 0000000 00000000562 12202276743 0025465 0 ustar 00root root 0000000 0000000 # This is only used by dependant libraries that need to find the files
module ClientSideValidations
module Files
Initializer = File.expand_path(File.dirname(__FILE__) + '/../generators/templates/client_side_validations/initializer.rb')
Javascript = File.expand_path(File.dirname(__FILE__) + '/../../vendor/assets/javascripts/rails.validations.js')
end
end
client_side_validations-3.2.6/lib/client_side_validations/generators.rb 0000664 0000000 0000000 00000000332 12202276743 0026527 0 ustar 00root root 0000000 0000000 module ClientSideValidations
module Generators
Assets = []
def self.register_assets(klass)
Assets.push(*klass.assets)
end
end
end
require 'client_side_validations/generators/rails_validations'
client_side_validations-3.2.6/lib/client_side_validations/generators/ 0000775 0000000 0000000 00000000000 12202276743 0026204 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/client_side_validations/generators/rails_validations.rb 0000664 0000000 0000000 00000000477 12202276743 0032250 0 ustar 00root root 0000000 0000000 module ClientSideValidations
module Generators
class RailsValidations
def self.assets
[{
:path => File.expand_path('../../../../vendor/assets/javascripts', __FILE__),
:file => 'rails.validations.js'
}]
end
Generators.register_assets(self)
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/middleware.rb 0000664 0000000 0000000 00000010117 12202276743 0026475 0 ustar 00root root 0000000 0000000 # encoding: utf-8
require 'client_side_validations/core_ext'
module ClientSideValidations
module Middleware
class Validators
def initialize(app)
@app = app
end
def call(env)
if matches = /\A\/validators\/(\w+)\z/.match(env['PATH_INFO'])
process_request(matches.captures.first, env)
else
@app.call(env)
end
end
def process_request(validation, env)
if disabled_validators.include?(validation)
error_resp
else
klass_name = validation.camelize
klass_name = "::ClientSideValidations::Middleware::#{klass_name}"
klass_name.constantize.new(env).response
end
rescue => e
error_resp
end
def disabled_validators
ClientSideValidations::Config.disabled_validators.map(&:to_s)
end
def error_resp
[500, {'Content-Type' => 'application/json', 'Content-Length' => '0'}, ['']]
end
end
class Base
attr_accessor :request, :body, :status
def initialize(env)
# Filter out cache buster
env['QUERY_STRING'] = env['QUERY_STRING'].split('&').select { |p| !p.match(/^_=/) }.join('&')
self.body = ''
self.status = 200
self.request = ActionDispatch::Request.new(env)
end
def response
[status, {'Content-Type' => content_type, 'Content-Length' => body.length.to_s}, [body]]
end
def content_type
'application/json'
end
end
class Uniqueness < Base
IGNORE_PARAMS = %w{case_sensitive id scope}
REGISTERED_ORMS = []
class NotValidatable < StandardError; end
def response
begin
if is_unique?
self.status = 404
self.body = 'true'
else
self.status = 200
self.body = 'false'
end
rescue NotValidatable
self.status = 500
self.body = ''
end
super
end
def self.register_orm(orm)
registered_orms << orm
end
def self.registered_orms
REGISTERED_ORMS
end
def registered_orms
self.class.registered_orms
end
private
def is_unique?
convert_scope_value_from_null_to_nil
klass, attribute, value = extract_resources
middleware_class = nil
unless Array.wrap(klass._validators[attribute.to_sym]).find { |v| v.kind == :uniqueness }
raise NotValidatable
end
registered_orms.each do |orm|
if orm.is_class?(klass)
middleware_class = orm
break
end
end
middleware_class.is_unique?(klass, attribute, value, request.params)
end
def convert_scope_value_from_null_to_nil
if request.params['scope']
request.params['scope'].each do |key, value|
if value == 'null'
request.params['scope'][key] = nil
end
end
end
end
def extract_resources
parent_key = (request.params.keys - IGNORE_PARAMS).first
if nested?(request.params[parent_key], 1)
klass, attribute, value = uproot(request.params[parent_key])
klass = klass.classify.constantize
else
klass = parent_key.classify.constantize
attribute = request.params[parent_key].keys.first
value = request.params[parent_key][attribute]
end
[klass, attribute, value]
end
def uproot(nested_hash = nil)
uproot_helper(nested_hash)[-3..-1]
end
def uproot_helper(nested_hash = nil, keys = [])
if nested_hash.respond_to?(:keys)
keys << nested_hash.keys.first
uproot_helper(nested_hash[nested_hash.keys.first], keys)
else
keys << nested_hash
end
end
def nested?(hash = nil, levels = 0)
i = 0
until !(hash.respond_to? :keys)
hash = hash[hash.keys.first]
i += 1
end
i > levels
end
end
end
end
client_side_validations-3.2.6/lib/client_side_validations/version.rb 0000664 0000000 0000000 00000000065 12202276743 0026046 0 ustar 00root root 0000000 0000000 module ClientSideValidations
VERSION = '3.2.6'
end
client_side_validations-3.2.6/lib/generators/ 0000775 0000000 0000000 00000000000 12202276743 0021325 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/generators/client_side_validations/ 0000775 0000000 0000000 00000000000 12202276743 0026204 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/generators/client_side_validations/copy_assets_generator.rb 0000664 0000000 0000000 00000002472 12202276743 0033140 0 ustar 00root root 0000000 0000000 module ClientSideValidations
module Generators
class CopyAssetsGenerator < Rails::Generators::Base
def copy_javascript_asset
if self.class == CopyAssetsGenerator || !asset_pipeline_enabled?
assets.each do |asset|
source_paths << asset[:path]
copy_file asset[:file], "#{asset_directory}/#{asset[:file]}"
end
end
end
private
def self.asset_directory
if asset_pipeline_enabled?
"app#{Rails.configuration.assets.prefix}/javascripts"
else
'public/javascripts'
end
end
def asset_directory
CopyAssetsGenerator.asset_directory
end
def self.assets
Assets
end
def assets
CopyAssetsGenerator.assets
end
def self.asset_file_names
assets.map { |asset| asset[:file] }.join(', ')
end
def self.asset_pipeline_enabled?
if Rails.application
(Rails.configuration.respond_to?(:assets) ? (Rails.configuration.assets || {}) : {})[:enabled]
end
end
def asset_pipeline_enabled?
self.class.asset_pipeline_enabled?
end
def self.installation_message
"Copies #{asset_file_names} to #{asset_directory}"
end
desc installation_message
end
end
end
client_side_validations-3.2.6/lib/generators/client_side_validations/install_generator.rb 0000664 0000000 0000000 00000001075 12202276743 0032250 0 ustar 00root root 0000000 0000000 require 'generators/client_side_validations/copy_assets_generator'
module ClientSideValidations
module Generators
class InstallGenerator < CopyAssetsGenerator
def copy_initializer
source_paths << File.expand_path('../../templates/client_side_validations', __FILE__)
copy_file 'initializer.rb', 'config/initializers/client_side_validations.rb'
end
private
def self.installation_message
"Copies initializer into config/initializers and #{super.downcase}"
end
desc installation_message
end
end
end
client_side_validations-3.2.6/lib/generators/templates/ 0000775 0000000 0000000 00000000000 12202276743 0023323 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/generators/templates/client_side_validations/ 0000775 0000000 0000000 00000000000 12202276743 0030202 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/lib/generators/templates/client_side_validations/initializer.rb 0000664 0000000 0000000 00000001617 12202276743 0033057 0 ustar 00root root 0000000 0000000 # ClientSideValidations Initializer
# Uncomment to disable uniqueness validator, possible security issue
# ClientSideValidations::Config.disabled_validators = [:uniqueness]
# Uncomment to validate number format with current I18n locale
# ClientSideValidations::Config.number_format_with_locale = true
# Uncomment the following block if you want each input field to have the validation messages attached.
#
# Note: client_side_validation requires the error to be encapsulated within
#
#
# ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
# unless html_tag =~ /^#{html_tag}#{instance.error_message.first} }.html_safe
# else
# %{#{html_tag}
}.html_safe
# end
# end
client_side_validations-3.2.6/test/ 0000775 0000000 0000000 00000000000 12202276743 0017365 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/action_view/ 0000775 0000000 0000000 00000000000 12202276743 0021674 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/action_view/cases/ 0000775 0000000 0000000 00000000000 12202276743 0022772 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/action_view/cases/helper.rb 0000664 0000000 0000000 00000012472 12202276743 0024604 0 ustar 00root root 0000000 0000000 require 'base_helper'
require 'action_view'
require 'action_view/template'
require 'action_view/models'
require 'client_side_validations/action_view'
module ActionController
class Base
include ActionDispatch::Routing::RouteSet.new.url_helpers
end
end
module ActionViewTestSetup
include ::ClientSideValidations::ActionView::Helpers::FormHelper
include ::ClientSideValidations::ActionView::Helpers::FormTagHelper
def form_for(*)
@output_buffer = super
end
Routes = ActionDispatch::Routing::RouteSet.new
Routes.draw do
resources :posts do
resources :comments
end
root :to => 'main#index'
end
def url_for(object)
@url_for_options = object
if object.is_a?(Hash) && object[:use_route].blank? && object[:controller].blank?
object.merge!(:controller => "main", :action => "index")
end
super
end
def _routes
Routes
end
# Rails 3.2.0 dropped size from the form elements
def legacy_size
if Rails.version < '3.2.0'
'size="30" '
end
end
def hidden_input_for_select(name)
if Rails.version >= '3.2.0'
%{ }
end
end
include Routes.url_helpers
def setup
super
# Create 'label' locale for testing I18n label helpers
I18n.backend.store_translations 'label', {
:activemodel => {
:attributes => {
:post => {
:cost => 'Total cost'
}
}
},
:helpers => {
:label => {
:post => {
:body => 'Write entire text here'
}
}
}
}
# Create "submit" locale for testing I18n submit helpers
I18n.backend.store_translations 'submit', {
:helpers => {
:submit => {
:create => 'Create %{model}',
:update => 'Confirm %{model} changes',
:submit => 'Save changes',
:another_post => {
:update => 'Update your %{model}'
}
}
}
}
@post = Post.new
@comment = Comment.new
if defined?(ActionView::OutputFlow)
@view_flow = ActionView::OutputFlow.new
else
@_content_for = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new }
end
end
def snowman(method = nil)
txt = %{}
txt << %{ }
txt << %{ } if method
txt << %{
}
end
def form_text(action = "http://www.example.com", id = nil, html_class = nil, remote = nil, validators = nil, file = nil)
txt = %{"
if options.is_a?(Hash) && options[:validators]
build_script_tag(html, id, options[:validators])
else
html
end
end
def build_script_tag(html, id, validators)
number_format = {:separator => '.', :delimiter => ','}
patterns = {:numericality=>"/^(-|\\+)?(?:\\d+|\\d{1,3}(?:\\#{number_format[:delimiter]}\\d{3})+)(?:\\#{number_format[:separator]}\\d*)?$/"}
(html || '') + %Q{}
end
protected
def comments_path(post)
"/posts/#{post.id}/comments"
end
alias_method :post_comments_path, :comments_path
def comment_path(post, comment)
"/posts/#{post.id}/comments/#{comment.id}"
end
alias_method :post_comment_path, :comment_path
def admin_comments_path(post)
"/admin/posts/#{post.id}/comments"
end
alias_method :admin_post_comments_path, :admin_comments_path
def admin_comment_path(post, comment)
"/admin/posts/#{post.id}/comments/#{comment.id}"
end
alias_method :admin_post_comment_path, :admin_comment_path
def posts_path(options={})
"/posts"
end
def post_path(post, options = {})
if options[:format]
"/posts/#{post.id}.#{options[:format]}"
else
"/posts/#{post.id}"
end
end
def protect_against_forgery?
false
end
end
client_side_validations-3.2.6/test/action_view/cases/test_helpers.rb 0000664 0000000 0000000 00000053350 12202276743 0026026 0 ustar 00root root 0000000 0000000 require 'action_view/cases/helper'
class ClientSideValidations::ActionViewHelpersTest < ActionView::TestCase
include ActionViewTestSetup
cattr_accessor :field_error_proc
@@field_error_proc = Proc.new { |html_tag, instance| html_tag }
def client_side_form_settings_helper
{
:type => "ActionView::Helpers::FormBuilder",
:input_tag => %{ },
:label_tag => %{ }
}
end
def test_text_field
form_for(@post, :validate => true) do |f|
concat f.text_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_password_field
form_for(@post, :validate => true) do |f|
concat f.password_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_file_field
form_for(@post, :validate => true, :html => {:multipart => true}) do |f|
concat f.file_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators, :file => true) do
%{ }
end
assert_equal expected, output_buffer
end
def test_search_field
form_for(@post, :validate => true) do |f|
concat f.search_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_telephone_field
form_for(@post, :validate => true) do |f|
concat f.telephone_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_phone_field
form_for(@post, :validate => true) do |f|
concat f.phone_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_url_field
form_for(@post, :validate => true) do |f|
concat f.url_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_email_field
form_for(@post, :validate => true) do |f|
concat f.email_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_number_field
form_for(@post, :validate => true) do |f|
concat f.number_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_range_field
form_for(@post, :validate => true) do |f|
concat f.range_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_check_box
form_for(@post, :validate => true) do |f|
concat f.check_box(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ } +
%{ }
end
assert_equal expected, output_buffer
end
def test_check_box_ensure_no_validate_attribute
form_for(@post, :validate => true) do |f|
concat f.check_box(:cost, :validate => true)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ } +
%{ }
end
assert_equal expected, output_buffer
end
def test_radio_button
form_for(@post, :validate => true) do |f|
concat f.radio_button(:cost, "10")
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_radio_button_ensure_no_validate_attribute
form_for(@post, :validate => true) do |f|
concat f.radio_button(:cost, "10", :validate => true)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_field_without_validations
form_for(@post, :validate => true) do |f|
concat f.text_field(:title)
end
expected = whole_form('/posts', 'new_post', 'new_post', :validators => {}) do
%{ }
end
assert_equal expected, output_buffer
end
def test_text_field_with_validations_turned_off
form_for(@post, :validate => true) do |f|
concat f.text_field(:cost, :validate => false)
end
expected = whole_form('/posts', 'new_post', 'new_post', :validators => {}) do
%{ }
end
assert_equal expected, output_buffer
end
def test_nested_fields_for_inherit_validation_settings
form_for(@post, :validate => true) do |f|
concat f.fields_for(:comment, @comment) { |c|
concat c.text_field(:title)
}
end
validators = {'post[comment][title]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{}
end
assert_equal expected, output_buffer
end
def test_multiple_nested_fields_for_inherit_validation_settings
form_for(@post, :validate => true) do |f|
concat f.fields_for(:comment, @comment) { |c|
concat c.text_field(:title)
}
concat f.fields_for(:comment, @comment) { |c|
concat c.text_field(:body)
}
end
validators = {'post[comment][title]' => {:presence => [{:message => "can't be blank"}]}, 'post[comment][body]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{} +
%{ }
end
assert_equal expected, output_buffer
end
def test_nested_fields_for_with_nested_attributes
form_for(@post, :validate => true) do |f|
concat f.fields_for(:comments, [@comment]) { |c|
concat c.text_field(:title)
}
end
validators = {'post[comments_attributes][][title]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{}
end
assert_equal expected, output_buffer
end
def test_nested_fields_for_with_nested_attributes_with_child_index
form_for(@post, :validate => true) do |f|
concat f.fields_for(:comments, [Comment.new], :child_index => '__INDEX__') { |c|
concat c.text_field(:title)
}
end
validators = {'post[comments_attributes][][title]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{}
end
assert_equal expected, output_buffer
end
def test_nested_fields_for_dont_overwrite_validation_with_inheritance
form_for(@post, :validate => true) do |f|
concat f.fields_for(:comment, @comment, :validate => false) { |c|
concat c.text_field(:title)
}
end
expected = whole_form('/posts', 'new_post', 'new_post', :validators => {}) do
%{}
end
assert_equal expected, output_buffer
end
def test_with_custom_id_for_form
form_for(@post, :validate => true, :html => { :id => 'some_form' }) do |f|
concat f.text_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'some_form', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_select
form_for(@post, :validate => true) do |f|
concat f.select(:cost, [])
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_select_with_validate_options
form_for(@post, :validate => true) do |f|
concat f.select(:cost, [], {}, :validate => false)
end
expected = whole_form('/posts', 'new_post', 'new_post', :validators => {}) do
%{ }
end
assert_equal expected, output_buffer
end
def test_select_multiple
form_for(@post, :validate => true) do |f|
concat f.select(:cost, [], {}, :multiple => true)
end
validators = {'post[cost][]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{#{hidden_input_for_select('post[cost][]')} }
end
assert_equal expected, output_buffer
end
def test_collection_select
form_for(@post, :validate => true) do |f|
concat f.collection_select(:cost, [], :id, :name)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_collection_select_with_validate_options
form_for(@post, :validate => true) do |f|
concat f.collection_select(:cost, [], :id, :name, {}, :validate => false)
end
expected = whole_form('/posts', 'new_post', 'new_post', :validators => {}) do
%{ }
end
assert_equal expected, output_buffer
end
def test_grouped_collection_select
form_for(@post, :validate => true) do |f|
concat f.grouped_collection_select(:cost, [], :group_method, :group_label_method, :id, :name)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_grouped_collection_select_with_validate_options
form_for(@post, :validate => true) do |f|
concat f.grouped_collection_select(:cost, [], :group_method, :group_label_method, :id, :name, {}, :validate => false)
end
expected = whole_form('/posts', 'new_post', 'new_post', :validators => {}) do
%{ }
end
assert_equal expected, output_buffer
end
def test_time_zone_select
zones = mock('TimeZones')
zones.stubs(:all).returns([])
form_for(@post, :validate => true) do |f|
concat f.time_zone_select(:cost, nil, :model => zones)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_time_zone_select_with_validate_options
zones = mock('TimeZones')
zones.stubs(:all).returns([])
form_for(@post, :validate => true) do |f|
concat f.time_zone_select(:cost, nil, { :model => zones }, { :validate => false })
end
expected = whole_form('/posts', 'new_post', 'new_post', :validators => {}) do
%{ }
end
assert_equal expected, output_buffer
end
def test_pushing_script_to_content_for
form_for(@post, :validate => :post) do |f|
concat f.text_field(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = %{}
assert_equal expected, output_buffer
assert_equal build_script_tag(nil, 'new_post', validators), content_for(:post)
end
if Rails.version >= '3.2.0'
def test_text_area
form_for(@post, :validate => true) do |f|
concat f.text_area(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{}
end
assert_equal expected, output_buffer
end
def test_as_form_option_with_new_record_rails
test_buffer = form_for(@post, :as => :article, :validate => true) do |f|
concat content_tag(:span, 'Dummy Content')
end
expected = whole_form('/posts', 'new_article', 'new_article', :validators => {}) do
%{Dummy Content }
end
assert_equal expected, output_buffer
end
def test_as_form_option_with_existing_record_rails
@post.stubs(:persisted?).returns(true)
@post.stubs(:id).returns(123)
test_buffer = form_for(@post, :as => :article, :validate => true) do |f|
concat content_tag(:span, 'Dummy Content')
end
expected = whole_form('/posts/123', 'edit_article', 'edit_article', :method => 'put', :validators => {}) do
%{Dummy Content }
end
assert_equal expected, output_buffer
end
def test_namespace_form_option_with_new_record
test_buffer = form_for(Post.new, :namespace => :blog, :validate => true) do |f|
concat content_tag(:span, 'Dummy Content')
end
expected = whole_form('/posts', 'blog_new_post', 'new_post', :validators => {}) do
%{Dummy Content }
end
assert_equal expected, output_buffer
end
def test_namespace_form_option_with_existing_record
@post.stubs(:persisted?).returns(true)
@post.stubs(:id).returns(123)
test_buffer = form_for(@post, :namespace => :blog, :validate => true) do |f|
concat content_tag(:span, 'Dummy Content')
end
expected = whole_form('/posts/123', 'blog_edit_post_123', 'edit_post', :method => 'put', :validators => {}) do
%{Dummy Content }
end
assert_equal expected, output_buffer
end
elsif Rails.version >= '3.1.0' && Rails.version < '3.2.0'
def test_text_area
form_for(@post, :validate => true) do |f|
concat f.text_area(:cost)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :method => 'post', :validators => validators) do
%{}
end
assert_equal expected, output_buffer
end
def test_as_form_option_with_new_record_rails
test_buffer = form_for(Post.new, :as => :article, :validate => true) do |f|
concat content_tag(:span, "Dummy Content")
end
expected = whole_form("/posts", "article_new", "article_new", :validators => {}) do
%{Dummy Content }
end
assert_equal expected, output_buffer
end
def test_as_form_option_with_existing_record_rails
test_buffer = form_for(@post, :as => :article, :validate => true) do |f|
concat content_tag(:span, "Dummy Content")
end
expected = whole_form('/posts', "article_edit", "article_edit", :method => 'post', :validators => {}) do
%{Dummy Content }
end
assert_equal expected, output_buffer
end
end
def test_string_as_record
assert_raise ClientSideValidations::ActionView::Helpers::FormHelper::Error do
form_for('post', :validate => true) do |f|
concat f.text_field(:cost)
end
end
end
def test_symbol_as_record
assert_raise ClientSideValidations::ActionView::Helpers::FormHelper::Error do
form_for(:post, :validate => true) do |f|
concat f.text_field(:cost)
end
end
end
def test_text_field_with_custom_name
form_for(@post, :validate => true) do |f|
concat f.text_field(:cost, :name => :postcost)
end
validators = {'postcost' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{ }
end
assert_equal expected, output_buffer
end
def test_added_validators
form_for(@post, :validate => true) do |f|
concat f.validate(:cost, :body, :title)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}, 'post[body]' => {:presence => [{:message => "can't be blank"}], :length => [{:messages => {:minimum => 'is too short (minimum is 200 characters)'}, :minimum => 200}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators)
assert_equal expected, output_buffer
end
def test_added_validators_defaulting_to_all
form_for(@post, :validate => true) do |f|
concat f.fields_for(:comment, @comment) { |c|
concat c.validate
}
end
validators = {'post[comment][title]' => {:presence => [{:message => "can't be blank"}]},'post[comment][body]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators)
assert_equal expected, output_buffer
end
def test_added_validators_with_filters
form_for(@post, :validate => true) do |f|
concat f.validate(:cost, :body, :title, :length => false)
end
validators = {'post[cost]' => {:presence => [{:message => "can't be blank"}]}, 'post[body]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators)
assert_equal expected, output_buffer
end
def test_field_with_index_set
form_for(@post, :validate => true) do |f|
concat f.fields_for(:comment, @comment, :index => 5) { |c|
concat c.text_field(:title)
}
end
validators = {'post[comment][5][title]' => {:presence => [{:message => "can't be blank"}]}}
expected = whole_form('/posts', 'new_post', 'new_post', :validators => validators) do
%{}
end
assert_equal expected, output_buffer
end
def test_object_without_client_side_validation_hash_method
@post.singleton_class.send(:undef_method, :client_side_validation_hash)
form_for(@post, :validate => true) do |f|
concat f.text_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post', :validators => {}) do
%{ }
end
assert_equal expected, output_buffer
end
end
client_side_validations-3.2.6/test/action_view/cases/test_legacy_helpers.rb 0000664 0000000 0000000 00000015235 12202276743 0027352 0 ustar 00root root 0000000 0000000 require 'action_view/cases/helper'
class ClientSideValidations::LegacyActionViewHelpersTest < ActionView::TestCase
include ActionViewTestSetup
def test_text_field
form_for(@post) do |f|
concat f.text_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_password_field
form_for(@post) do |f|
concat f.password_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_file_field
form_for(@post, :html => {:multipart => true}) do |f|
concat f.file_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post', :file => true) do
%{ }
end
assert_equal expected, output_buffer
end
if Rails.version >= '3.2.0'
def test_text_area
form_for(@post) do |f|
concat f.text_area(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{}
end
assert_equal expected, output_buffer
end
elsif Rails.version >= '3.1.0'
def test_text_area
form_for(@post) do |f|
concat f.text_area(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{}
end
assert_equal expected, output_buffer
end
end
def test_search_field
form_for(@post) do |f|
concat f.search_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_telephone_field
form_for(@post) do |f|
concat f.telephone_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_phone_field
form_for(@post) do |f|
concat f.phone_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_url_field
form_for(@post) do |f|
concat f.url_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_email_field
form_for(@post) do |f|
concat f.email_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_number_field
form_for(@post) do |f|
concat f.number_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_range_field
form_for(@post) do |f|
concat f.range_field(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_check_box
form_for(@post) do |f|
concat f.check_box(:cost)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ } +
%{ }
end
assert_equal expected, output_buffer
end
def test_radio_button
form_for(@post) do |f|
concat f.radio_button(:cost, "10")
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_fields_for
result = fields_for(@comment) do |c|
c.text_field(:title)
end
expected = %{}
assert_equal expected, result
end
def test_select
form_for(@post) do |f|
concat f.select(:cost, [])
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_select_multiple
form_for(@post) do |f|
concat f.select(:cost, [], {}, :multiple => true)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{#{hidden_input_for_select('post[cost][]')} }
end
assert_equal expected, output_buffer
end
def test_collection_select
form_for(@post) do |f|
concat f.collection_select(:cost, [], :id, :name)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_grouped_collection_select
form_for(@post) do |f|
concat f.grouped_collection_select(:cost, [], :group_method, :group_label_method, :id, :name)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_time_zone_select
zones = mock('TimeZones')
zones.stubs(:all).returns([])
form_for(@post) do |f|
concat f.time_zone_select(:cost, nil, :model => zones)
end
expected = whole_form('/posts', 'new_post', 'new_post') do
%{ }
end
assert_equal expected, output_buffer
end
def test_string_as_record
form_for('post') do |f|
concat f.text_field(:cost)
end
expected = whole_form('/') do
%{ }
end
assert_equal expected, output_buffer
end
def test_symbol_as_record
form_for(:post) do |f|
concat f.text_field(:cost)
end
expected = whole_form('/') do
%{ }
end
assert_equal expected, output_buffer
end
end
client_side_validations-3.2.6/test/action_view/models.rb 0000664 0000000 0000000 00000000215 12202276743 0023502 0 ustar 00root root 0000000 0000000 require 'active_model'
require 'client_side_validations/active_model'
require 'action_view/models/comment'
require 'action_view/models/post'
client_side_validations-3.2.6/test/action_view/models/ 0000775 0000000 0000000 00000000000 12202276743 0023157 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/action_view/models/comment.rb 0000664 0000000 0000000 00000000623 12202276743 0025147 0 ustar 00root root 0000000 0000000 class Comment
extend ActiveModel::Naming
extend ActiveModel::Translation
include ActiveModel::Validations
include ActiveModel::Conversion
attr_reader :id, :post_id, :title, :body
validates :title, :body, :presence => true
def initialize(params={})
params.each do |attr, value|
self.public_send("#{attr}=", value)
end if params
end
def persisted?
false
end
end
client_side_validations-3.2.6/test/action_view/models/post.rb 0000664 0000000 0000000 00000001065 12202276743 0024473 0 ustar 00root root 0000000 0000000 class Post
extend ActiveModel::Naming
extend ActiveModel::Translation
include ActiveModel::Validations
include ActiveModel::Conversion
attr_accessor :title, :author_name, :body, :secret, :written_on, :cost
validates :cost, :body, :presence => true
validates :body, :length => { :minimum => 200 }
def initialize(params={})
params.each do |attr, value|
self.public_send("#{attr}=", value)
end if params
end
def persisted?
false
end
attr_accessor :comments, :comment_ids
def comments_attributes=(attributes); end
end
client_side_validations-3.2.6/test/active_model/ 0000775 0000000 0000000 00000000000 12202276743 0022020 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/active_model/cases/ 0000775 0000000 0000000 00000000000 12202276743 0023116 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/active_model/cases/helper.rb 0000664 0000000 0000000 00000000201 12202276743 0024713 0 ustar 00root root 0000000 0000000 require 'base_helper'
require 'active_model'
require 'client_side_validations/active_model'
require 'active_model/models/person'
client_side_validations-3.2.6/test/active_model/cases/test_acceptance_validator.rb 0000664 0000000 0000000 00000001202 12202276743 0030630 0 ustar 00root root 0000000 0000000 require 'active_model/cases/test_base'
class ActiveModel::AcceptanceValidatorTest < ClientSideValidations::ActiveModelTestBase
def test_acceptance_client_side_hash
expected_hash = { :message => "must be accepted", :accept => "1" }
assert_equal expected_hash, AcceptanceValidator.new(:attributes => [:name]).client_side_hash(@person, :age)
end
def test_acceptance_client_side_hash_with_custom_message
expected_hash = { :message => "you must accept", :accept => "1" }
assert_equal expected_hash, AcceptanceValidator.new(:attributes => [:name], :message => "you must accept").client_side_hash(@person, :age)
end
end
client_side_validations-3.2.6/test/active_model/cases/test_base.rb 0000664 0000000 0000000 00000000303 12202276743 0025410 0 ustar 00root root 0000000 0000000 require 'active_model/cases/helper'
class ClientSideValidations::ActiveModelTestBase < ActiveModel::TestCase
include ActiveModel::Validations
def setup
@person = Person.new
end
end
client_side_validations-3.2.6/test/active_model/cases/test_confirmation_validator.rb 0000664 0000000 0000000 00000001170 12202276743 0031236 0 ustar 00root root 0000000 0000000 require 'active_model/cases/test_base'
class ActiveModel::ConfirmationValidatorTest < ClientSideValidations::ActiveModelTestBase
def test_confirmation_client_side_hash
expected_hash = { :message => "doesn't match confirmation" }
assert_equal expected_hash, ConfirmationValidator.new(:attributes => [:name]).client_side_hash(@person, :age)
end
def test_confirmation_client_side_hash_with_custom_message
expected_hash = { :message => "you must confirm" }
assert_equal expected_hash, ConfirmationValidator.new(:attributes => [:name], :message => "you must confirm").client_side_hash(@person, :age)
end
end
client_side_validations-3.2.6/test/active_model/cases/test_exclusion_validator.rb 0000664 0000000 0000000 00000002710 12202276743 0030560 0 ustar 00root root 0000000 0000000 require 'active_model/cases/test_base'
class ActiveModel::ExclusionValidatorTest < ClientSideValidations::ActiveModelTestBase
def test_exclusion_client_side_hash
expected_hash = { :message => "is reserved", :in => [1, 2] }
assert_equal expected_hash, ExclusionValidator.new(:attributes => [:name], :in => [1, 2]).client_side_hash(@person, :age)
end
def test_exclusion_client_side_hash_with_custom_message
expected_hash = { :message => "is exclusive", :in => [1, 2] }
assert_equal expected_hash, ExclusionValidator.new(:attributes => [:name], :in => [1, 2], :message => "is exclusive").client_side_hash(@person, :age)
end
def test_exclusion_client_side_hash_with_ranges
expected_hash = { :message => "is reserved", :range => 1..2 }
assert_equal expected_hash, ExclusionValidator.new(:attributes => [:name], :in => 1..2).client_side_hash(@person, :age)
end
def test_exclusion_client_side_hash_ignore_proc
@person.stubs(:range).returns([1,2])
expected_hash = nil
assert_equal expected_hash, ExclusionValidator.new(:attributes => [:name], :in => Proc.new { |o| o.range }).client_side_hash(@person, :age)
end
def test_exclusion_client_side_hash_observe_proc
@person.stubs(:range).returns([1,2])
expected_hash = { :message => "is reserved", :in => [1, 2] }
assert_equal expected_hash, ExclusionValidator.new(:attributes => [:name], :in => Proc.new { |o| o.range }).client_side_hash(@person, :age, true)
end
end
client_side_validations-3.2.6/test/active_model/cases/test_format_validator.rb 0000664 0000000 0000000 00000004021 12202276743 0030034 0 ustar 00root root 0000000 0000000 require 'active_model/cases/test_base'
class ActiveModel::FormatValidatorTest < ClientSideValidations::ActiveModelTestBase
def test_format_client_side_hash
expected_hash = { :message => "is invalid", :with => /.+/ }
assert_equal expected_hash, FormatValidator.new(:attributes => [:name], :with => /.+/).client_side_hash(@person, :age)
end
def test_format_client_side_hash_without
expected_hash = { :message => "is invalid", :without => /.+/ }
assert_equal expected_hash, FormatValidator.new(:attributes => [:name], :without => /.+/).client_side_hash(@person, :age)
end
def test_format_client_side_hash_with_custom_message
expected_hash = { :message => "is wrong format", :with => /.+/ }
assert_equal expected_hash, FormatValidator.new(:attributes => [:name], :with => /.+/, :message => "is wrong format").client_side_hash(@person, :age)
end
def test_format_client_side_hash_ignore_proc
@person.stubs(:matcher).returns(/.+/)
expected_hash = nil
assert_equal expected_hash, FormatValidator.new(:attributes => [:name], :with => Proc.new { |o| o.matcher }).client_side_hash(@person, :age)
end
def test_format_client_side_hash_without_ignore_proc
@person.stubs(:matcher).returns(/.+/)
expected_hash = nil
assert_equal expected_hash, FormatValidator.new(:attributes => [:name], :without => Proc.new { |o| o.matcher }).client_side_hash(@person, :age)
end
def test_format_client_side_hash_observe_proc
@person.stubs(:matcher).returns(/.+/)
expected_hash = { :message => "is invalid", :with => /.+/ }
assert_equal expected_hash, FormatValidator.new(:attributes => [:name], :with => Proc.new { |o| o.matcher }).client_side_hash(@person, :age, true)
end
def test_format_client_side_hash_without_observe_proc
@person.stubs(:matcher).returns(/.+/)
expected_hash = { :message => "is invalid", :without => /.+/ }
assert_equal expected_hash, FormatValidator.new(:attributes => [:name], :without => Proc.new { |o| o.matcher }).client_side_hash(@person, :age, true)
end
end
client_side_validations-3.2.6/test/active_model/cases/test_inclusion_validator.rb 0000664 0000000 0000000 00000002774 12202276743 0030564 0 ustar 00root root 0000000 0000000 require 'active_model/cases/test_base'
class ActiveModel::InclusionValidatorTest < ClientSideValidations::ActiveModelTestBase
def test_inclusion_client_side_hash
expected_hash = { :message => "is not included in the list", :in => [1, 2] }
assert_equal expected_hash, InclusionValidator.new(:attributes => [:name], :in => [1, 2]).client_side_hash(@person, :age)
end
def test_inclusion_client_side_hash_with_custom_message
expected_hash = { :message => "is not a choice", :in => [1, 2] }
assert_equal expected_hash, InclusionValidator.new(:attributes => [:name], :in => [1, 2], :message => "is not a choice").client_side_hash(@person, :age)
end
def test_inclusion_client_side_hash_with_range
expected_hash = { :message => "is not included in the list", :range => 1..2 }
assert_equal expected_hash, InclusionValidator.new(:attributes => [:name], :in => 1..2).client_side_hash(@person, :age)
end
def test_inclusion_client_side_hash_ignore_proc
@person.stubs(:range).returns([1,2])
expected_hash = nil
assert_equal expected_hash, InclusionValidator.new(:attributes => [:name], :in => Proc.new { |o| o.range }).client_side_hash(@person, :age)
end
def test_inclusion_client_side_hash_observe_proc
@person.stubs(:range).returns([1,2])
expected_hash = { :message => "is not included in the list", :in => [1, 2] }
assert_equal expected_hash, InclusionValidator.new(:attributes => [:name], :in => Proc.new { |o| o.range }).client_side_hash(@person, :age, true)
end
end
client_side_validations-3.2.6/test/active_model/cases/test_length_validator.rb 0000664 0000000 0000000 00000005514 12202276743 0030035 0 ustar 00root root 0000000 0000000 require 'active_model/cases/test_base'
class ActiveModel::LengthValidatorTest < ClientSideValidations::ActiveModelTestBase
def test_length_client_side_hash
expected_hash = {
:messages => {
:is => "is the wrong length (should be 10 characters)"
},
:is => 10
}
assert_equal expected_hash, LengthValidator.new(:attributes => [:age], :is => 10).client_side_hash(@person, :first_name)
end
def test_length_client_side_hash_with_custom_message
expected_hash = {
:messages => {
:is => "is the wrong length (should be 10 words)"
},
:is => 10
}
assert_equal expected_hash, LengthValidator.new(:attributes => [:age], :is => 10, :wrong_length => "is the wrong length (should be %{count} words)").client_side_hash(@person, :first_name)
end
def test_length_client_side_hash_with_custom_general_message
expected_hash = {
:messages => {
:minimum => "is not the correct length",
:maximum => "is way too long"
},
:minimum => 4,
:maximum => 10
}
assert_equal expected_hash, LengthValidator.new(:attributes => [:age], :minimum => 4, :maximum => 10, :message => "is not the correct length", :too_long => "is way too long").client_side_hash(@person, :first_name)
end
def test_length_client_side_hash_with_js_tokenizer
expected_hash = {
:messages => {
:is => "is the wrong length (should be 10 characters)"
},
:is => 10,
:js_tokenizer => %q{match(/\w+/g)}
}
assert_equal expected_hash, LengthValidator.new(:attributes => [:age], :is => 10, :tokenizer => proc { |value| value.split(/\w+/) }, :js_tokenizer => %q{match(/\w+/g)}).client_side_hash(@person, :first_name)
end
def test_length_client_side_hash_with_minimum_and_maximum
expected_hash = {
:messages => {
:minimum => "is too short (minimum is 5 characters)",
:maximum => "is too long (maximum is 10 characters)"
},
:minimum => 5,
:maximum => 10
}
assert_equal expected_hash, LengthValidator.new(:attributes => [:age], :minimum => 5, :maximum => 10).client_side_hash(@person, :first_name)
end
def test_length_client_side_hash_with_range
expected_hash = {
:messages => {
:minimum => "is too short (minimum is 5 characters)",
:maximum => "is too long (maximum is 10 characters)"
},
:minimum => 5,
:maximum => 10
}
assert_equal expected_hash, LengthValidator.new(:attributes => [:age], :within => 5..10).client_side_hash(@person, :first_name)
end
def test_length_client_side_hash
expected_hash = {
:messages => {
:is => "is the wrong length (should be 10 characters)"
},
:is => 10
}
assert_equal expected_hash, LengthValidator.new(:attributes => [:age], :is => 10).client_side_hash(@person, :first_name)
end
end
client_side_validations-3.2.6/test/active_model/cases/test_numericality_validator.rb 0000664 0000000 0000000 00000006020 12202276743 0031252 0 ustar 00root root 0000000 0000000 require 'active_model/cases/test_base'
class ActiveModel::NumericalityValidatorTest < ClientSideValidations::ActiveModelTestBase
def test_numericality_client_side_hash
expected_hash = { :messages => { :numericality => "is not a number" } }
assert_equal expected_hash, NumericalityValidator.new(:attributes => [:age]).client_side_hash(@person, :age)
end
def test_numericality_client_side_hash_with_allow_nil
expected_hash = { :messages => { :numericality => "is not a number" }, :allow_blank => true }
assert_equal expected_hash, NumericalityValidator.new(:attributes => [:age], :allow_nil => true).client_side_hash(@person, :age)
end
def test_numericality_client_side_hash_with_custom_message
expected_hash = { :messages => { :numericality => "bad number" } }
assert_equal expected_hash, NumericalityValidator.new(:attributes => [:age], :message => "bad number").client_side_hash(@person, :age)
end
def test_numericality_client_side_hash_with_options
expected_hash = {
:messages => {
:numericality => "is not a number",
:only_integer => "must be an integer",
:greater_than => "must be greater than 10",
:greater_than_or_equal_to => "must be greater than or equal to 10",
:equal_to => "must be equal to 10",
:less_than => "must be less than 10",
:less_than_or_equal_to => "must be less than or equal to 10",
:odd => "must be odd",
:even => "must be even"
},
:only_integer => true,
:greater_than => 10,
:greater_than_or_equal_to => 10,
:equal_to => 10,
:less_than => 10,
:less_than_or_equal_to => 10,
:odd => true,
:even => true
}
test_hash = NumericalityValidator.new(:attributes => [:age],
:only_integer => true, :greater_than => 10, :greater_than_or_equal_to => 10,
:equal_to => 10, :less_than => 10, :less_than_or_equal_to => 10,
:odd => true, :even => true).client_side_hash(@person, :age)
assert_equal expected_hash, test_hash
end
def test_numericality_message_always_present
expected_hash = { :messages => { :numericality => 'is not a number', :only_integer => 'must be an integer' }, :only_integer => true }
assert_equal expected_hash, NumericalityValidator.new(:attributes => [:age], :only_integer => true).client_side_hash(@person, :age)
end
def test_numericality_client_side_hash_ignore_proc
@person.stubs(:years).returns(5)
expected_hash = { :messages => { :numericality => "is not a number" } }
assert_equal expected_hash, NumericalityValidator.new(:attributes => [:age], :equal_to => Proc.new { |o| o.years }).client_side_hash(@person, :age)
end
def test_numericality_client_side_hash_observe_proc
@person.stubs(:years).returns(5)
expected_hash = { :messages => { :numericality => "is not a number", :equal_to => 'must be equal to 5' }, :equal_to => 5 }
assert_equal expected_hash, NumericalityValidator.new(:attributes => [:age], :equal_to => Proc.new { |o| o.years }).client_side_hash(@person, :age, true)
end
end
client_side_validations-3.2.6/test/active_model/cases/test_presence_validator.rb 0000664 0000000 0000000 00000001116 12202276743 0030352 0 ustar 00root root 0000000 0000000 require 'active_model/cases/test_base'
class ActiveModel::PresenceValidatorTest < ClientSideValidations::ActiveModelTestBase
def test_presence_client_side_hash
expected_hash = { :message => "can't be blank" }
assert_equal expected_hash, PresenceValidator.new(:attributes => [:name]).client_side_hash(@person, :age)
end
def test_presence_client_side_hash_with_custom_message
expected_hash = { :message => "is required" }
assert_equal expected_hash, PresenceValidator.new(:attributes => [:name], :message => "is required").client_side_hash(@person, :age)
end
end
client_side_validations-3.2.6/test/active_model/cases/test_validations.rb 0000664 0000000 0000000 00000025125 12202276743 0027024 0 ustar 00root root 0000000 0000000 require 'active_model/cases/test_base'
class ActiveModel::ValidationsTest < ClientSideValidations::ActiveModelTestBase
class Person
include ::ActiveModel::Validations
attr_accessor :first_name, :last_name, :age, :weight
def self.name
"Person"
end
def new_record?
true
end
end
def new_person
person = Class.new(Person)
yield(person)
person.new
end
def test_validations_to_client_side_hash
person = new_person do |p|
p.validates_presence_of :first_name
end
expected_hash = {
:first_name => {
:presence => [{
:message => "can't be blank"
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash
end
def test_validations_to_client_side_hash_with_validations_allow_blank
person = new_person do |p|
p.validates_length_of :first_name, :is => 10, :allow_blank => true
p.validates_format_of :first_name, :with => //, :allow_blank => true
end
expected_hash = {
:first_name => {
:length => [{
:messages => { :is => 'is the wrong length (should be 10 characters)'},
:is => 10,
:allow_blank => true
}],
:format => [{
:message => 'is invalid',
:with => //,
:allow_blank => true
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash
end
def test_validations_to_client_side_hash_with_validations_on_create
person = new_person do |p|
p.validates_length_of :first_name, :is => 10, :on => :create
p.validates_length_of :last_name, :is => 10, :on => :update
p.validates_format_of :first_name, :with => //, :on => :update
p.validates_format_of :last_name, :with => //, :on => :create
p.validates_numericality_of :age, :on => :create, :allow_blank => true
p.validates_numericality_of :weight, :on => :update
p.class_eval do
def new_record?
true
end
end
end
expected_hash = {
:first_name => {
:length => [{
:messages => { :is => 'is the wrong length (should be 10 characters)'},
:is => 10,
}],
},
:last_name => {
:format => [{
:message => 'is invalid',
:with => //,
}]
},
:age => {
:numericality => [{
:messages => { :numericality => 'is not a number' },
:allow_blank => true
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash
end
def test_validations_to_client_side_hash_with_validations_on_update
person = new_person do |p|
p.validates_length_of :first_name, :is => 10, :on => :update
p.validates_length_of :last_name, :is => 10, :on => :create
p.validates_format_of :first_name, :with => //, :on => :create
p.validates_format_of :last_name, :with => //, :on => :update
p.validates_numericality_of :age, :on => :update
p.validates_numericality_of :weight, :on => :create
p.class_eval do
def new_record?
false
end
end
end
expected_hash = {
:first_name => {
:length => [{
:messages => { :is => 'is the wrong length (should be 10 characters)'},
:is => 10,
}],
},
:last_name => {
:format => [{
:message => 'is invalid',
:with => //,
}]
},
:age => {
:numericality => [{
:messages => { :numericality => 'is not a number' },
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash
end
def test_validates_with_should_be_ignored
person = new_person do |p|
p.validates_with PersonValidator
end
expected_hash = {}
assert_equal expected_hash, person.client_side_validation_hash
end
def test_generic_block_validators_should_be_ignored
person = new_person do |p|
p.validates_each(:first_name) do |record, attr, value|
record.errors.add(:first_name, "failed")
end
end
expected_hash = {}
assert_equal expected_hash, person.client_side_validation_hash
end
def test_conditionals_when_not_forced
person = new_person do |p|
p.validates :first_name, :presence => { :if => :can_validate? }
p.validates :last_name, :presence => { :unless => :cannot_validate? }
p.class_eval do
def can_validate?
true
end
def cannot_validate?
false
end
end
end
expected_hash = {}
assert_equal expected_hash, person.client_side_validation_hash
end
def test_conditionals_when_all_forced_on
person = new_person do |p|
p.validates :first_name, :presence => { :if => :can_validate? }
p.validates :last_name, :presence => { :unless => :cannot_validate? }
p.class_eval do
def can_validate?
true
end
def cannot_validate?
false
end
end
end
expected_hash = {
:first_name => {
:presence => [{
:message => "can't be blank"
}]
},
:last_name => {
:presence => [{
:message => "can't be blank"
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash(true)
end
def test_conditionals_forcing_individual_attributes_on
person = new_person do |p|
p.validates :first_name, :presence => { :if => :can_validate? }, :length => { :is => 5, :if => :can_validate? }
p.validates :last_name, :presence => { :unless => :cannot_validate? }, :length => { :is => 10, :unless => :cannot_validate? }
p.class_eval do
def can_validate?
true
end
def cannot_validate?
true
end
end
end
expected_hash = {
:first_name => {
:presence => [{
:message => "can't be blank"
}],
:length => [{
:messages => { :is => 'is the wrong length (should be 5 characters)' },
:is => 5
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash(:first_name => true)
end
def test_conditionals_forcing_individual_validators_on
person = new_person do |p|
p.validates :first_name, :presence => { :if => :can_validate? }, :length => { :is => 5, :if => :can_validate? }
p.validates :last_name, :presence => { :unless => :cannot_validate? }, :length => { :is => 10, :unless => :cannot_validate? }
p.class_eval do
def can_validate?
true
end
def cannot_validate?
true
end
end
end
expected_hash = {
:first_name => {
:presence => [{
:message => "can't be blank"
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash(:first_name => { :presence => true }, :last_name => { :presence => true })
end
def test_forcing_all_validators_off
person = new_person do |p|
p.validates :first_name, :presence => true
p.validates :last_name, :presence => true
p.class_eval do
def can_validate?
true
end
def cannot_validate?
true
end
end
end
expected_hash = {}
assert_equal expected_hash, person.client_side_validation_hash(false)
end
def test_conditionals_forcing_individual_attributes_off
person = new_person do |p|
p.validates :first_name, :presence => true
p.validates :last_name, :presence => true
p.class_eval do
def can_validate?
true
end
def cannot_validate?
true
end
end
end
expected_hash = {
:last_name => {
:presence => [{
:message => "can't be blank"
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash(:first_name => false)
end
def test_conditionals_forcing_individual_validators_off
person = new_person do |p|
p.validates :first_name, :presence => true, :length => { :is => 5 }
p.class_eval do
def can_validate?
true
end
def cannot_validate?
true
end
end
end
expected_hash = {
:first_name => {
:presence => [{
:message => "can't be blank"
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash(:first_name => { :length => false })
end
def test_conditional_proc_validators
person = new_person do |p|
p.validates :first_name, :presence => { :if => Proc.new { |o| o.can_validate? } }
p.validates :last_name, :presence => { :unless => Proc.new { |o| o.cannot_validate? } }
p.class_eval do
def can_validate?
true
end
def cannot_validate?
false
end
end
end
expected_hash = {
:first_name => {
:presence => [{
:message => "can't be blank"
}]
},
:last_name => {
:presence => [{
:message => "can't be blank"
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash(true)
end
def test_conditionals_forced_when_used_changed_helpers
person = new_person do |p|
p.validates :first_name, :presence => { :if => :first_name_changed? }
p.validates :last_name, :presence => { :unless => :last_name_changed? }
end
expected_hash = {
:first_name => {
:presence => [{
:message => "can't be blank"
}]
},
}
assert_equal expected_hash, person.client_side_validation_hash
end
def test_multiple_validators_of_same_type_on_same_attribute
person = new_person do |p|
p.validates :first_name, :format => /\d/
p.validates :first_name, :format => /\w/
end
expected_hash = {
:first_name => {
:format => [{
:message => 'is invalid',
:with => /\d/,
},
{
:message => 'is invalid',
:with => /\w/
}]
}
}
assert_equal expected_hash, person.client_side_validation_hash
end
def test_ignored_procs_validators
person = new_person do |p|
p.validates :first_name, :format => Proc.new { |o| o.matcher }
def matcher
/\d/
end
end
expected_hash = {}
assert_equal expected_hash, person.client_side_validation_hash
end
def test_validations_to_client_side_hash_with_validator_is_disabled
::ClientSideValidations::Config.stubs(:disabled_validators).returns([:presence])
person = new_person do |p|
p.validates_presence_of :first_name
end
expected_hash = {}
assert_equal expected_hash, person.client_side_validation_hash
end
end
client_side_validations-3.2.6/test/active_model/models/ 0000775 0000000 0000000 00000000000 12202276743 0023303 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/active_model/models/person.rb 0000664 0000000 0000000 00000000530 12202276743 0025134 0 ustar 00root root 0000000 0000000 class PersonValidator < ActiveModel::Validator
def validate(record)
end
end
class Person
include ActiveModel::Validations
attr_accessor :first_name, :last_name, :email, :age
validates_presence_of :first_name
validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
def new_record?
true
end
end
client_side_validations-3.2.6/test/active_record/ 0000775 0000000 0000000 00000000000 12202276743 0022176 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/active_record/cases/ 0000775 0000000 0000000 00000000000 12202276743 0023274 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/active_record/cases/helper.rb 0000664 0000000 0000000 00000000612 12202276743 0025077 0 ustar 00root root 0000000 0000000 require 'base_helper'
require 'active_record'
require 'client_side_validations/active_record'
# Connection must be establised before anything else
ActiveRecord::Base.establish_connection(
:adapter => defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3',
:database => ':memory:'
)
require 'active_record/models/user'
require 'active_record/models/guid'
require 'active_record/models/thing'
client_side_validations-3.2.6/test/active_record/cases/test_base.rb 0000664 0000000 0000000 00000000303 12202276743 0025566 0 ustar 00root root 0000000 0000000 require 'active_record/cases/helper'
class ClientSideValidations::ActiveRecordTestBase < ActiveRecord::TestCase
include ActiveRecord::Validations
def setup
@user = User.new
end
end
client_side_validations-3.2.6/test/active_record/cases/test_middleware.rb 0000664 0000000 0000000 00000016645 12202276743 0027011 0 ustar 00root root 0000000 0000000 # encoding: utf-8
require 'middleware/cases/helper'
require 'active_record/cases/helper'
class ClientSideValidationsActiveRecordMiddlewareTest < Test::Unit::TestCase
include Rack::Test::Methods
def teardown
User.delete_all
end
def with_kcode(kcode)
if RUBY_VERSION < '1.9'
orig_kcode, $KCODE = $KCODE, kcode
begin
yield
ensure
$KCODE = orig_kcode
end
else
yield
end
end
def app
app = Proc.new { |env| [200, {}, ['success']] }
ClientSideValidations::Middleware::Validators.new(app)
end
def test_uniqueness_when_resource_exists
User.create(:email => 'user@test.com')
get '/validators/uniqueness', { 'user[email]' => 'user@test.com', 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
end
def test_uniqueness_when_resource_exists_and_param_order_is_backwards
User.create(:email => 'user@test.com')
get '/validators/uniqueness', { 'case_sensitive' => true, 'user[email]' => 'user@test.com' }
assert_equal 'false', last_response.body
assert last_response.ok?
end
def test_uniqueness_when_resource_does_not_exist
get '/validators/uniqueness', { 'user[email]' => 'user@test.com', 'case_sensitive' => true }
assert_equal 'true', last_response.body
assert last_response.not_found?
end
def test_uniqueness_when_value_must_be_typecast
User.create(:active => false)
get '/validators/uniqueness', { 'user[active]' => 'false', 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
end
def test_uniqueness_when_id_is_given
user = User.create(:email => 'user@test.com')
get '/validators/uniqueness', { 'user[email]' => 'user@test.com', 'id' => user.id, 'case_sensitive' => true }
assert_equal 'true', last_response.body
assert last_response.not_found?
end
def test_mysql_adapter_uniqueness_when_id_is_given
user = User.create(:email => 'user@test.com')
User.connection.stubs('adapter_name').returns('Mysql2')
sql_without_binary = "#{User.arel_table["email"].eq(user.email).to_sql} AND #{User.arel_table.primary_key.not_eq(user.id).to_sql}"
relation = Arel::Nodes::SqlLiteral.new("BINARY #{sql_without_binary}")
# NOTE: Stubs User#where because SQLite3 don't know BINARY
result = User.where(sql_without_binary)
User.expects(:where).with(relation).returns(result)
get '/validators/uniqueness', { 'user[email]' => user.email, 'case_sensitive' => true, 'id' => user.id}
assert_equal 'true', last_response.body
end
def test_mysql_adapter_uniqueness_when_id_is_given_with_scope
user = User.create(:email => 'user@test.com', :name => 'Brian')
User.connection.stubs('adapter_name').returns('Mysql2')
sql_without_binary = "#{User.arel_table["email"].eq(user.email).to_sql} AND #{User.arel_table.primary_key.not_eq(user.id).to_sql} AND #{User.arel_table["name"].eq(user.name).to_sql}"
relation = Arel::Nodes::SqlLiteral.new("BINARY #{sql_without_binary}")
#NOTE: Stubs User#where because SQLite3 don't know BINARY
result = User.where(sql_without_binary)
User.expects(:where).with(relation).returns(result)
get '/validators/uniqueness', { 'user[email]' => user.email, 'scope' => {'name' => user.name}, 'case_sensitive' => true, 'id' => user.id}
assert_equal 'true', last_response.body
end
def test_uniqueness_when_scope_is_given
User.create(:email => 'user@test.com', :age => 25)
get '/validators/uniqueness', { 'user[email]' => 'user@test.com', 'scope' => { 'age' => 30 }, 'case_sensitive' => true }
assert_equal 'true', last_response.body
assert last_response.not_found?
end
def test_uniqueness_when_scope_is_given_and_value_must_be_typecast
User.create(:email => 'user@test.com', :active => true)
get '/validators/uniqueness', { 'user[email]' => 'user@test.com', 'scope' => { 'active' => 'true' }, 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
end
def test_uniqueness_when_multiple_scopes_are_given
User.create(:email => 'user@test.com', :age => 30, :name => 'Brian')
get '/validators/uniqueness', { 'user[email]' => 'user@test.com', 'scope' => { 'age' => 30, 'name' => 'Robert' }, 'case_sensitive' => true }
assert_equal 'true', last_response.body
assert last_response.not_found?
end
def test_uniqueness_when_case_insensitive
User.create(:name => 'Brian')
get '/validators/uniqueness', { 'user[name]' => 'BRIAN', 'case_sensitive' => false }
assert_equal 'false', last_response.body
assert last_response.ok?
end
def test_uniqueness_when_attribute_passes_as_an_integer
User.create(:name => 123)
get '/validators/uniqueness', { 'user[name]' => 123, 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
end
def test_uniqueness_when_attribute_passes_as_an_integer
User.create(:name => 123)
get '/validators/uniqueness', { 'user[name]' => 123, 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
end
def test_uniqueness_with_columns_which_are_sql_keywords
Guid.validates_uniqueness_of :key
assert_nothing_raised do
get '/validators/uniqueness', { 'guid[key]' => 'test', 'case_sensitive' => true }
end
end
def test_uniqueness_with_limit
# User.title is limited to 5 characters
User.create(:title => "abcde")
get '/validators/uniqueness', { 'user[title]' => 'abcdefgh', 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
end
def test_uniqueness_with_limit_and_utf8
with_kcode('UTF8') do
# User.title is limited to 5 characters
User.create(:title => "一二三四五")
get '/validators/uniqueness', { 'user[title]' => '一二三四五六七八', 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
end
end
def test_validate_straight_inheritance_uniqueness
get '/validators/uniqueness', { 'inept_wizard[name]' => 'Rincewind', 'case_sensitive' => true }
assert_equal 'true', last_response.body
assert last_response.not_found?
IneptWizard.create(:name => 'Rincewind')
get '/validators/uniqueness', { 'inept_wizard[name]' => 'Rincewind', 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
get '/validators/uniqueness', { 'conjurer[name]' => 'Rincewind', 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
Conjurer.create(:name => 'The Amazing Bonko')
get '/validators/uniqueness', { 'thaumaturgist[name]' => 'The Amazing Bonko', 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
end
def test_uniqueness_when_resource_is_a_nested_module
ActiveRecordTestModule::User2.create(:email => 'user@test.com')
get '/validators/uniqueness', { 'active_record_test_module/user2[email]' => 'user@test.com', 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
end
def test_uniqueness_when_resource_descends_from_an_abstract_base_class
Thing.create(:name => 'name_to_be_duplicated')
get '/validators/uniqueness', { 'thing[name]' => 'name_to_be_duplicated', 'case_sensitive' => true }
assert_equal 'false', last_response.body
assert last_response.ok?
end
end
client_side_validations-3.2.6/test/active_record/cases/test_uniqueness_validator.rb 0000664 0000000 0000000 00000006202 12202276743 0031124 0 ustar 00root root 0000000 0000000 require 'active_record/cases/test_base'
class ActiveRecord::UniquenessValidatorTest < ClientSideValidations::ActiveRecordTestBase
def test_uniqueness_client_side_hash
expected_hash = { :message => "has already been taken", :case_sensitive => true }
assert_equal expected_hash, UniquenessValidator.new(:attributes => [:name]).client_side_hash(@user, :name)
end
def test_uniqueness_client_side_hash_allowing_blank
expected_hash = { :message => "has already been taken", :case_sensitive => true, :allow_blank => true }
assert_equal expected_hash, UniquenessValidator.new(:attributes => [:name], :allow_blank => true).client_side_hash(@user, :name)
end
def test_uniqueness_client_side_hash_with_custom_message
expected_hash = { :message => "is not available", :case_sensitive => true }
assert_equal expected_hash, UniquenessValidator.new(:attributes => [:name], :message => "is not available").client_side_hash(@user, :name)
end
def test_uniqueness_client_side_hash
@user.stubs(:new_record?).returns(false)
@user.stubs(:id).returns(1)
expected_hash = { :message => "has already been taken", :case_sensitive => true, :id => 1 }
assert_equal expected_hash, UniquenessValidator.new(:attributes => [:name]).client_side_hash(@user, :name)
end
def test_uniqueness_client_side_hash_with_single_scope_item
@user.stubs(:age).returns(30)
@user.stubs(:title).returns("test title")
expected_hash = { :message => "has already been taken", :case_sensitive => true, :scope => {:title => "test title"} }
result_hash = UniquenessValidator.new(:attributes => [:name], :scope => :title).client_side_hash(@user, :name)
assert_equal expected_hash, result_hash
end
def test_uniqueness_client_side_hash_with_multiple_scope_items
@user.stubs(:age).returns(30)
@user.stubs(:title).returns("test title")
expected_hash = { :message => "has already been taken", :case_sensitive => true, :scope => {:age => 30, :title => "test title"} }
result_hash = UniquenessValidator.new(:attributes => [:name], :scope => [:age, :title]).client_side_hash(@user, :name)
assert_equal expected_hash, result_hash
end
def test_uniqueness_client_side_hash_with_empty_scope_array
expected_hash = { :message => "has already been taken", :case_sensitive => true }
result_hash = UniquenessValidator.new(:attributes => [:name], :scope => []).client_side_hash(@user, :name)
assert_equal expected_hash, result_hash
end
def test_uniqueness_client_side_hash_when_nested_module
@user = ActiveRecordTestModule::User2.new
expected_hash = { :message => "has already been taken", :case_sensitive => true, :class => 'active_record_test_module/user2' }
assert_equal expected_hash, UniquenessValidator.new(:attributes => [:name]).client_side_hash(@user, :name)
end
def test_uniqueness_client_side_hash_with_class_from_options
@user = UserForm.new
expected_hash = { :message => "has already been taken", :case_sensitive => true, :class => 'user' }
assert_equal expected_hash, UniquenessValidator.new(:attributes => [:name], :client_validations => { :class => 'User' } ).client_side_hash(@user, :name)
end
end
client_side_validations-3.2.6/test/active_record/models/ 0000775 0000000 0000000 00000000000 12202276743 0023461 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/active_record/models/guid.rb 0000664 0000000 0000000 00000000242 12202276743 0024734 0 ustar 00root root 0000000 0000000 guids_table = %{CREATE TABLE guids (id INTEGER PRIMARY KEY, key text);}
ActiveRecord::Base.connection.execute(guids_table)
class Guid < ActiveRecord::Base
end
client_side_validations-3.2.6/test/active_record/models/thing.rb 0000664 0000000 0000000 00000000417 12202276743 0025121 0 ustar 00root root 0000000 0000000 things_table = %{CREATE TABLE things (id INTEGER PRIMARY KEY, name text);}
ActiveRecord::Base.connection.execute(things_table)
class AbstractThing < ActiveRecord::Base
self.abstract_class = true
end
class Thing < AbstractThing
validates_uniqueness_of :name
end
client_side_validations-3.2.6/test/active_record/models/user.rb 0000664 0000000 0000000 00000001342 12202276743 0024764 0 ustar 00root root 0000000 0000000 users_table = %{CREATE TABLE users (id INTEGER PRIMARY KEY, age INTEGER, name TEXT, email TEXT, title VARCHAR(5), parent_id INTEGER, active BOOLEAN, type VARCHAR(255));}
ActiveRecord::Base.connection.execute(users_table)
class User < ActiveRecord::Base
validates :email, :title, :active, :name, :uniqueness => { :allow_nil => true }
end
class IneptWizard < User; end
class Conjurer < IneptWizard; end
class Thaumaturgist < Conjurer; end
module ActiveRecordTestModule
class User2 < User; end
end
class UserForm
include ActiveRecord::Validations
attr_accessor :name
validates_uniqueness_of :name, :client_validations => { :class => User }
def self.i18n_scope
:activerecord
end
def new_record?
true
end
end
client_side_validations-3.2.6/test/base_helper.rb 0000664 0000000 0000000 00000000645 12202276743 0022170 0 ustar 00root root 0000000 0000000 require 'rubygems'
require 'bundler/setup'
require 'test/unit'
if RUBY_VERSION >= '1.9.3'
require 'debugger'
end
require 'mocha/setup'
require 'rails'
require 'client_side_validations/config'
module TestApp
class Application < Rails::Application
config.root = File.dirname(__FILE__)
config.active_support.deprecation = :log
config.logger = Logger.new(STDOUT)
end
end
module ClientSideValidations; end
client_side_validations-3.2.6/test/core_ext/ 0000775 0000000 0000000 00000000000 12202276743 0021175 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/core_ext/cases/ 0000775 0000000 0000000 00000000000 12202276743 0022273 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/core_ext/cases/test_core_ext.rb 0000664 0000000 0000000 00000003106 12202276743 0025467 0 ustar 00root root 0000000 0000000 require 'base_helper'
require 'client_side_validations/core_ext'
class CoreExtTest < Test::Unit::TestCase
def test_regexp_as_json
regexp = //
assert_equal regexp, regexp.as_json
end
def test_regexp_replace_A_and_Z
test_regexp = /\A\Z/
expected_regexp = /^$/
assert_equal expected_regexp, test_regexp.as_json
end
def test_regexp_replace_a_and_z
test_regexp = /\A\z/
expected_regexp = /^$/
assert_equal expected_regexp, test_regexp.as_json
end
def test_regexp_to_json
assert_equal "/^$/", /\A\Z/.to_json(nil)
end
def test_regexp_encode_json
assert_equal "//", //.encode_json(nil)
end
def test_regexp_remove_comment
assert_equal "//", /(?# comment)/.to_json(nil)
end
def test_regexp_remove_group_options
assert_equal "/(something)/", /(?-mix:something)/.to_json(nil)
end
def test_regexp_as_jason_with_options
assert_equal //i, //i.as_json
end
def test_range_as_json
assert_equal [1,3], (1..3).as_json
end
def test_range_to_json
assert_equal '[1, 3]', (1..3).to_json(nil)
end
def test_range_as_json_with_floats
assert_equal [0.5,5.5], (0.5..5.5).as_json
end
def test_multiline_regexp_as_json
test_regexp = /
/
expected_regexp = //
assert_equal expected_regexp, test_regexp.as_json
end
def test_regexp_modifiers_as_json
# JS allows /i and /m modifiers, all other lead to error
assert_equal(//i, //i.as_json)
assert_equal(//m, //m.as_json)
assert_equal(//im, //im.as_json)
assert_equal(//, //x.as_json)
assert_equal(//i, //ix.as_json)
end
end
client_side_validations-3.2.6/test/generators/ 0000775 0000000 0000000 00000000000 12202276743 0021536 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/generators/cases/ 0000775 0000000 0000000 00000000000 12202276743 0022634 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/generators/cases/test_generators.rb 0000664 0000000 0000000 00000005325 12202276743 0026376 0 ustar 00root root 0000000 0000000 require 'rails/generators/test_case'
require 'client_side_validations'
require 'generators/client_side_validations/copy_assets_generator'
require 'generators/client_side_validations/install_generator'
class InstallGeneratorTest < Rails::Generators::TestCase
tests ClientSideValidations::Generators::InstallGenerator
destination File.expand_path('../../tmp', __FILE__)
setup :prepare_destination
test 'Assert all files are properly created when no asset pipeline present' do
stub_configuration
run_generator
assert_file 'config/initializers/client_side_validations.rb'
assert_file 'public/javascripts/rails.validations.js'
end
test 'Assert all files are properly created when asset pipeline present and disabled' do
stub_configuration
configuration = {:enabled => false}
configuration.stubs(:prefix).returns('/assets')
Rails.configuration.stubs(:assets).returns(configuration)
run_generator
assert_file 'config/initializers/client_side_validations.rb'
assert_file 'public/javascripts/rails.validations.js'
end
test 'Assert all files are properly created when asset pipeline present and enabled' do
stub_configuration
configuration = {:enabled => true}
configuration.stubs(:prefix).returns('/assets')
Rails.configuration.stubs(:assets).returns(configuration)
run_generator
assert_file 'config/initializers/client_side_validations.rb'
assert_no_file 'app/assets/javascripts/rails.validations.js'
end
def stub_configuration
Rails.stubs(:configuration).returns(mock('Configuration'))
end
end
class CopyAssetsGeneratorTest < Rails::Generators::TestCase
tests ClientSideValidations::Generators::CopyAssetsGenerator
destination File.expand_path('../../tmp', __FILE__)
setup :prepare_destination
test 'Assert file is properly created when no asset pipeline present' do
stub_configuration
run_generator
assert_file 'public/javascripts/rails.validations.js'
end
test 'Assert file is properly created when asset pipeline present and disabled' do
stub_configuration
configuration = {:enabled => false}
configuration.stubs(:prefix).returns('/assets')
Rails.configuration.stubs(:assets).returns(configuration)
run_generator
assert_file 'public/javascripts/rails.validations.js'
end
test 'Assert file is properly created when asset pipeline present and enabled' do
stub_configuration
configuration = {:enabled => true}
configuration.stubs(:prefix).returns('/assets')
Rails.configuration.stubs(:assets).returns(configuration)
run_generator
assert_file 'app/assets/javascripts/rails.validations.js'
end
def stub_configuration
Rails.stubs(:configuration).returns(mock('Configuration'))
end
end
client_side_validations-3.2.6/test/javascript/ 0000775 0000000 0000000 00000000000 12202276743 0021533 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/javascript/config.ru 0000664 0000000 0000000 00000000136 12202276743 0023350 0 ustar 00root root 0000000 0000000 $LOAD_PATH.unshift File.expand_path('..', __FILE__)
require 'server'
run Sinatra::Application
client_side_validations-3.2.6/test/javascript/public/ 0000775 0000000 0000000 00000000000 12202276743 0023011 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/javascript/public/test/ 0000775 0000000 0000000 00000000000 12202276743 0023770 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/javascript/public/test/callbacks/ 0000775 0000000 0000000 00000000000 12202276743 0025707 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/javascript/public/test/callbacks/elementAfter.js 0000664 0000000 0000000 00000003155 12202276743 0030664 0 ustar 00root root 0000000 0000000 module('Element Validate After Callback', {
setup: function() {
ClientSideValidations.forms['new_user'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: {"user[name]":{"presence":[{"message": "must be present"}]}}
}
$('#qunit-fixture')
.append($(' '))
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user'
}))
.find('form')
.append($(' ', {
name: 'user[name]',
id: 'user_name',
type: 'text'
}))
.append($('Name '));
ClientSideValidations.callbacks.element.after = function(element, message) {
$('#result').text('Element Validate After ' + element.attr('id'));
}
$('form#new_user').validate();
},
teardown: function() {
ClientSideValidations.callbacks.element.after = function(element, eventData) {}
}
});
test('runs callback when form element validate', function() {
var input = $('input');
equal($('#result').text(), '');
input.trigger('focusout');
equal($('#result').text(), 'Element Validate After user_name');
});
test('runs callback when form validates', function() {
var form = $('form'), input = form.find('input');
equal($('#result').text(), '');
form.submit();
equal($('#result').text(), 'Element Validate After user_name');
});
client_side_validations-3.2.6/test/javascript/public/test/callbacks/elementBefore.js 0000664 0000000 0000000 00000003153 12202276743 0031023 0 ustar 00root root 0000000 0000000 module('Element Validate Before Callback', {
setup: function() {
ClientSideValidations.forms['new_user'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: {"user[name]":{"{presence":[{"message": "must be present"}]}}
}
$('#qunit-fixture')
.append($(' '))
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user'
}))
.find('form')
.append($(' ', {
name: 'user[name]',
id: 'user_name',
type: 'text'
}))
.append($('Name '));
ClientSideValidations.callbacks.element.before = function(element) {
$('#result').text('Element Validate Before ' + element.attr('id'));
}
$('form#new_user').validate();
},
teardown: function() {
ClientSideValidations.callbacks.element.before = function(element, eventData) {}
}
});
test('runs callback when form element validate', function() {
var input = $('input');
equal($('#result').text(), '');
input.trigger('focusout');
equal($('#result').text(), 'Element Validate Before user_name');
});
test('runs callback when form validates', function() {
var form = $('form'), input = form.find('input');
equal($('#result').text(), '');
form.submit();
equal($('#result').text(), 'Element Validate Before user_name');
});
client_side_validations-3.2.6/test/javascript/public/test/callbacks/elementFail.js 0000664 0000000 0000000 00000003750 12202276743 0030477 0 ustar 00root root 0000000 0000000 module('Element Validate Fail Callback', {
setup: function() {
ClientSideValidations.forms['new_user'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: {"user[name]":{"presence":[{"message": "must be present"}]}}
}
$('#qunit-fixture')
.append($(' '))
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user'
}))
.find('form')
.append($(' ', {
name: 'user[name]',
id: 'user_name',
type: 'text'
}))
.append($('Name '));
ClientSideValidations.callbacks.element.fail = function(element, message) {
$('#result').text('Element Validate Fail ' + element.attr('id') + ' ' + message);
}
$('form#new_user').validate();
},
teardown: function() {
ClientSideValidations.callbacks.element.fail = function(element, message, callback) { callback(); }
}
});
test('runs callback when form element validate', function() {
var input = $('input');
equal($('#result').text(), '');
input.val('test')
input.trigger('change');
input.trigger('focusout');
equal($('#result').text(), '');
input.val('')
input.trigger('change');
input.trigger('focusout');
equal($('#result').text(), 'Element Validate Fail user_name must be present');
});
test('runs callback when form validates', function() {
var form = $('form'), input = form.find('input');
equal($('#result').text(), '');
input.val('test')
input.trigger('change');
form.trigger('submit');
equal($('#result').text(), '');
input.val('')
input.trigger('change');
form.trigger('submit');
equal($('#result').text(), 'Element Validate Fail user_name must be present');
});
client_side_validations-3.2.6/test/javascript/public/test/callbacks/elementPass.js 0000664 0000000 0000000 00000003645 12202276743 0030535 0 ustar 00root root 0000000 0000000 module('Element Validate Pass Callback', {
setup: function() {
ClientSideValidations.forms['new_user'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: {"user[name]":{"presence":[{"message": "must be present"}]}}
}
$('#qunit-fixture')
.append($(' '))
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user'
}))
.find('form')
.append($(' ', {
name: 'user[name]',
id: 'user_name',
type: 'text'
}))
.append($('Name '));
ClientSideValidations.callbacks.element.pass = function(element) {
$('#result').text('Element Validate Pass ' + element.attr('id'));
}
$('form#new_user').validate();
},
teardown: function() {
ClientSideValidations.callbacks.element.pass = function(element, callback) { callback() }
}
});
test('runs callback when form element validate', function() {
var input = $('input');
equal($('#result').text(), '');
input.val('')
input.trigger('change');
input.trigger('focusout');
equal($('#result').text(), '');
input.val('test')
input.trigger('change');
input.trigger('focusout');
equal($('#result').text(), 'Element Validate Pass user_name');
});
test('runs callback when form validates', function() {
var form = $('form'), input = form.find('input');
equal($('#result').text(), '');
input.val('')
input.trigger('change');
form.trigger('submit');
equal($('#result').text(), '');
input.val('test')
input.trigger('change');
form.trigger('submit');
equal($('#result').text(), 'Element Validate Pass user_name');
});
client_side_validations-3.2.6/test/javascript/public/test/callbacks/formAfter.js 0000664 0000000 0000000 00000002540 12202276743 0030173 0 ustar 00root root 0000000 0000000 module('Form Validate After Callback', {
setup: function() {
ClientSideValidations.forms['new_user'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: {"user[name]":{"presence":[{"message": "must be present"}]}}
}
$('#qunit-fixture')
.append($(' '))
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user'
}))
.find('form')
.append($(' ', {
name: 'user[name]',
id: 'user_name',
type: 'text'
}))
.append($('Name '));
ClientSideValidations.callbacks.form.after = function(form, message) {
$('#result').text('Form Validate After ' + form.attr('id'));
}
$('form#new_user').validate();
},
teardown: function() {
ClientSideValidations.callbacks.form.after = function(form, eventData) {}
}
});
test('runs callback', function() {
var form = $('form'), input = form.find('input');
equal($('#result').text(), '');
form.submit();
equal($('#result').text(), 'Form Validate After new_user');
});
client_side_validations-3.2.6/test/javascript/public/test/callbacks/formBefore.js 0000664 0000000 0000000 00000002545 12202276743 0030341 0 ustar 00root root 0000000 0000000 module('Form Validate Before Callback', {
setup: function() {
ClientSideValidations.forms['new_user'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: {"user[name]":{"presence":[{"message": "must be present"}]}}
}
$('#qunit-fixture')
.append($(' '))
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user'
}))
.find('form')
.append($(' ', {
name: 'user[name]',
id: 'user_name',
type: 'text'
}))
.append($('Name '));
ClientSideValidations.callbacks.form.before = function(form, message) {
$('#result').text('Form Validate Before ' + form.attr('id'));
}
$('form#new_user').validate();
},
teardown: function() {
ClientSideValidations.callbacks.form.before = function(form, eventData) {}
}
});
test('runs callback', function() {
var form = $('form'), input = form.find('input');
equal($('#result').text(), '');
form.submit();
equal($('#result').text(), 'Form Validate Before new_user');
});
client_side_validations-3.2.6/test/javascript/public/test/callbacks/formFail.js 0000664 0000000 0000000 00000002730 12202276743 0030006 0 ustar 00root root 0000000 0000000 module('Form Validate Fail Callback', {
setup: function() {
ClientSideValidations.forms['new_user'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: {"user[name]":{"presence":[{"message": "must be present"}]}}
}
$('#qunit-fixture')
.append($(' '))
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user'
}))
.find('form')
.append($(' ', {
name: 'user[name]',
id: 'user_name',
type: 'text'
}))
.append($('Name '));
ClientSideValidations.callbacks.form.fail = function(form, message) {
$('#result').text('Form Validate Fail ' + form.attr('id'));
}
$('form#new_user').validate();
},
teardown: function() {
ClientSideValidations.callbacks.form.fail = function(form, eventData) {}
}
});
test('runs callback', function() {
var form = $('form'), input = form.find('input');
equal($('#result').text(), '');
form.submit();
equal($('#result').text(), 'Form Validate Fail new_user');
$('#result').text('');
input.val('test');
input.trigger('change');
form.submit();
equal($('#result').text(), '');
});
client_side_validations-3.2.6/test/javascript/public/test/callbacks/formPass.js 0000664 0000000 0000000 00000002677 12202276743 0030053 0 ustar 00root root 0000000 0000000 module('Form Validate Pass Callback', {
setup: function() {
ClientSideValidations.forms['new_user'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: {"user[name]":{"presence":[{"message": "must be present"}]}}
}
$('#qunit-fixture')
.append($(' '))
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user'
}))
.find('form')
.append($(' ', {
name: 'user[name]',
id: 'user_name',
type: 'text'
}))
.append($('Name '));
ClientSideValidations.callbacks.form.pass = function(form, message) {
$('#result').text('Form Validate Pass ' + form.attr('id'));
}
$('form#new_user').validate();
},
teardown: function() {
ClientSideValidations.callbacks.form.pass = function(form, eventData) {}
}
});
test('runs callback', function() {
var form = $('form'), input = form.find('input');
equal($('#result').text(), '');
form.submit();
equal($('#result').text(), '');
input.val('test');
input.trigger('change');
form.submit();
equal($('#result').text(), 'Form Validate Pass new_user');
});
client_side_validations-3.2.6/test/javascript/public/test/disableValidators.js 0000664 0000000 0000000 00000002051 12202276743 0027760 0 ustar 00root root 0000000 0000000 module('Disabling validators', {
setup: function() {
ClientSideValidations.validators = {
local: {
test: function(){},
test2: function(){}
},
remote: {
test: function(){},
test3: function(){}
}
}
}
});
test('when some validators are disabled', function() {
var keys = []; for(var k in ClientSideValidations.validators.remote) keys.push(k);
deepEqual(keys, ['test', 'test3']);
ClientSideValidations.disabled_validators = ['test'];
ClientSideValidations.disableValidators();
keys = []; for(var k in ClientSideValidations.validators.remote) keys.push(k);
deepEqual(keys, ['test3']);
});
test('when none of validators are disabled', function() {
var keys = []; for(var k in ClientSideValidations.validators.remote) keys.push(k);
deepEqual(keys, ['test', 'test3']);
ClientSideValidations.disabled_validators = [];
ClientSideValidations.disableValidators();
keys = []; for(var k in ClientSideValidations.validators.remote) keys.push(k);
deepEqual(keys, ['test', 'test3']);
});
client_side_validations-3.2.6/test/javascript/public/test/form_builders/ 0000775 0000000 0000000 00000000000 12202276743 0026624 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/javascript/public/test/form_builders/validateForm.js 0000664 0000000 0000000 00000012243 12202276743 0031601 0 ustar 00root root 0000000 0000000 module('Validate Form', {
setup: function() {
ClientSideValidations.forms['new_user'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: {'user[name]':{"presence":[{"message": "must be present"}]}}
}
$('#qunit-fixture')
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user'
}))
.find('form')
.append($(' ', {
name: 'user[name]',
id: 'user_name',
type: 'text'
}))
.append($('Name '));
$('form#new_user').validate();
}
});
asyncTest('Validate form with invalid form', 4, function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
form.trigger('submit');
setTimeout(function() {
start();
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
ok(input.parent().find('label:contains("must be present")')[0]);
ok(!$('iframe').contents().find('p:contains("Form submitted")')[0]);
}, 60);
});
asyncTest('Validate form with valid form', 1, function() {
var form = $('form#new_user'), input = form.find('input#user_name');
input.val('Test');
form.trigger('submit');
setTimeout(function() {
start();
ok($('iframe').contents().find('p:contains("Form submitted")')[0]);
}, 60);
});
asyncTest('Validate form with an input changed to false', 1, function() {
var form = $('form#new_user'), input = form.find('input#user_name');
input.val('Test');
input.attr('changed', false);
input.attr('data-valid', true);
form.trigger('submit');
setTimeout(function() {
start();
ok($('iframe').contents().find('p:contains("Form submitted")')[0]);
}, 60);
});
asyncTest('Ensure ajax:beforeSend is not from a bubbled event', 1, function() {
var form = $('form#new_user'), input = form.find('input#user_name');
form
.append(' ')
.find('a').trigger('ajax:beforeSend');
setTimeout(function() {
start();
ok(!input.parent().hasClass('field_with_errors'));
});
});
asyncTest('Validate form with invalid form and disabling validations', 1, function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
form.disableClientSideValidations();
form.trigger('submit');
setTimeout(function() {
start();
ok($('iframe').contents().find('p:contains("Form submitted")')[0]);
}, 100);
});
test('Resetting client side validations', 9, function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
form.trigger('submit');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
ok(input.parent().find('label:contains("must be present")')[0]);
form.resetClientSideValidations();
ok(!input.parent().hasClass('field_with_errors'));
ok(!label.parent().hasClass('field_with_errors'));
ok(!input.parent().find('label:contains("must be present")')[0]);
form.trigger('submit');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
ok(input.parent().find('label:contains("must be present")')[0]);
});
test('Disable client side validations on all child inputs', 3, function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
form.disableClientSideValidations();
input.trigger('focusout');
ok(!input.parent().hasClass('field_with_errors'));
ok(!label.parent().hasClass('field_with_errors'));
ok(!input.parent().find('label:contains("must be present")')[0]);
});
asyncTest('Handle disable-with', 1, function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
form.append($(' ', {
type: 'submit',
'data-disable-with': 'Waiting...',
name: 'commit',
value: 'Save',
id: 'submit_button'
}));
form.trigger('submit');
setTimeout(function() {
start();
ok($('#submit_button').attr('disabled') === undefined)
}, 60);
});
asyncTest('Disabled inputs do not stop form submission', 1, function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
input.disableClientSideValidations()
form.trigger('submit');
setTimeout(function() {
start();
ok($('iframe').contents().find('p:contains("Form submitted")')[0]);
}, 60);
});
asyncTest('Decorative (without name) inputs aren\'t validated', 1, function() {
var form = $('form#new_user'), input = form.find('input#user_name');
input.val('Test');
form.append($(' ', {type: 'text'})).validate();
form.trigger('submit');
setTimeout(function() {
start();
ok($('iframe').contents().find('p:contains("Form submitted")')[0]);
}, 60);
});
client_side_validations-3.2.6/test/javascript/public/test/settings.js 0000664 0000000 0000000 00000001034 12202276743 0026164 0 ustar 00root root 0000000 0000000 // hijacks normal form submit; lets it submit to an iframe to prevent
// navigating away from the test suite
$(document).bind('submit', function(e) {
if (!e.isDefaultPrevented()) {
var form = $(e.target), action = form.attr('action'),
name = 'form-frame' + jQuery.guid++,
iframe = $('');
if (action.indexOf('iframe') < 0) form.attr('action', action + '?iframe=true')
form.attr('target', name);
$('#qunit-fixture').append(iframe);
form.trigger('iframe:loading');
}
});
client_side_validations-3.2.6/test/javascript/public/test/utilities.js 0000664 0000000 0000000 00000000760 12202276743 0026344 0 ustar 00root root 0000000 0000000 module('Utilities');
test('Remote Validator Url without setting', function() {
ClientSideValidations.remote_validators_prefix = undefined;
equal(ClientSideValidations.remote_validators_url_for('test'), '//'+window.location.host+'/validators/test');
});
test('Remote Validator Url with setting', function() {
ClientSideValidations.remote_validators_prefix = 'other';
equal(ClientSideValidations.remote_validators_url_for('test'), '//'+window.location.host+'/other/validators/test');
});
client_side_validations-3.2.6/test/javascript/public/test/validateElement.js 0000664 0000000 0000000 00000034612 12202276743 0027437 0 ustar 00root root 0000000 0000000 module('Validate Element', {
setup: function() {
ClientSideValidations.forms['new_user'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: {
'user[name]':{"presence":[{"message": "must be present"}], "format":[{"message":"is invalid","with":/\d+/}]},
'user[password]':{"confirmation":[{"message": "must match confirmation"}]},
'user[agree]':{"acceptance": [{"message": "must be accepted"}]},
'user[email]':{"uniqueness":[{"message": "must be unique"}],"presence":[{"message": "must be present"}]},
'user[info_attributes][eye_color]':{"presence":[{"message": "must be present"}]},
'user[phone_numbers_attributes][][number]':{"presence":[{"message": "must be present"}]},
'user[phone_numbers_attributes][country_code][][code]':{"presence":[{"message": "must be present"}]},
'user[phone_numbers_attributes][deeply][nested][][attribute]':{"presence":[{"message": "must be present"}]}
}
}
$('#qunit-fixture')
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user'
}))
.find('form')
.append($('Name '))
.append($(' ', {
name: 'user[name]',
id: 'user_name',
type: 'text'
}))
.append($('Password '))
.append($(' ', {
name: 'user[password]',
id: 'user_password',
type: 'password'
}))
.append($('Password Confirmation '))
.append($(' ', {
name: 'user[password_confirmation]',
id: 'user_password_confirmation',
type: 'password'
}))
.append($('Agree '))
.append($(' ', {
name: 'user[agree]',
id: 'user_agree',
type: 'checkbox',
value: 1
}))
.append($(' ', {
name: 'user[email]',
id: 'user_email',
type: 'text'
}))
.append($('Phone Number '))
.append($(' ', {
name: 'user[phone_numbers_attributes][0][number]',
id: 'user_phone_numbers_attributes_0_number',
type: 'text'
})
.append($(' ', {
name: 'user[phone_numbers_attributes][0][_destroy]',
id: 'user_phone_numbers_attributes_0__destroy',
type: 'hidden',
value: "1"
})))
.append($('Phone Number '))
.append($(' ', {
name: 'user[phone_numbers_attributes][1][number]',
id: 'user_phone_numbers_attributes_1_number',
type: 'text'
}))
.append($('Phone Number '))
.append($(' ', {
name: 'user[phone_numbers_attributes][new_1234][number]',
id: 'user_phone_numbers_attributes_new_1234_number',
type: 'text'
}))
.append($('Country code '))
.append($(' ', {
name: 'user[phone_numbers_attributes][country_code][0][code]',
id: 'user_phone_numbers_attributes_country_code_0_code',
type: 'text'
}))
.append($('Deeply nested attribute '))
.append($(' ', {
name: 'user[phone_numbers_attributes][deeply][nested][0][attribute]',
id: 'user_phone_numbers_attributes_deeply_nested_0_attribute',
type: 'text'
}))
.append($('Deeply nested attribute '))
.append($(' ', {
name: 'user[phone_numbers_attributes][deeply][nested][5154ce728c06dedad4000001][attribute]',
id: 'user_phone_numbers_attributes_deeply_nested_5154ce728c06dedad4000001_attribute',
type: 'text'
}))
.append($('Eye Color '))
.append($(' ', {
name: 'user[info_attributes][eye_color]',
id: 'user_info_attributes_eye_color',
type: 'text'
}));
$('form#new_user').validate();
},
teardown: function() {
$('#qunit-fixture').remove('form');
delete ClientSideValidations.forms.new_user;
}
});
test('Validate when focusouting', function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
input.trigger('focusout');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
});
test('Validate when checkbox is clicked', function() {
var form = $('form#new_user'), input = form.find('input#user_agree');
var label = $('label[for="user_agree"]');
input.prop('checked', false)
input.trigger('click');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
});
test('Validate when focusout on confirmation', function() {
var form = $('form#new_user'), password = form.find('input#user_password'), confirmation = form.find('input#user_password_confirmation');
var label = $('label[for="user_password"]');
password.val('password');
confirmation.trigger('focusout');
ok(password.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
});
test('Validate nested attributes', function() {
var form = $('form#new_user'), input, label;
input = form.find('input#user_phone_numbers_attributes_1_number');
label = $('label[for="user_phone_numbers_attributes_1_number"]');
input.trigger('focusout');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
input = form.find('input#user_phone_numbers_attributes_0_number');
label = $('label[for="user_phone_numbers_attributes_0_number"]');
input.trigger('focusout');
ok(!input.parent().hasClass('field_with_errors'));
ok(!label.parent().hasClass('field_with_errors'));
input = form.find('input#user_phone_numbers_attributes_new_1234_number');
label = $('label[for="user_phone_numbers_attributes_new_1234_number"]');
input.trigger('focusout');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
input = form.find('input#user_phone_numbers_attributes_country_code_0_code');
label = $('label[for="user_phone_numbers_attributes_country_code_0_code"]');
input.trigger('focusout');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
input = form.find('input#user_phone_numbers_attributes_deeply_nested_0_attribute');
label = $('label[for="user_phone_numbers_attributes_deeply_nested_0_attribute"]');
input.trigger('focusout');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
input = form.find('input#user_phone_numbers_attributes_deeply_nested_5154ce728c06dedad4000001_attribute');
label = $('label[for="user_phone_numbers_attributes_deeply_nested_5154ce728c06dedad4000001_attribute"]');
input.trigger('focusout');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
});
test('Validate additional attributes', function() {
var form = $('form#new_user'), input, label;
input = form.find('input#user_info_attributes_eye_color');
label = $('label[for="user_info_attributes_eye_color"]');
input.trigger('focusout');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
});
test('Validate when keyup on confirmation', function() {
var form = $('form#new_user'), password = form.find('input#user_password'), confirmation = form.find('input#user_password_confirmation');
var label = $('label[for="user_password"]');
password.val('password');
confirmation.trigger('keyup');
ok(password.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
confirmation.val('password')
confirmation.trigger('keyup');
ok(!password.parent().hasClass('field_with_errors'));
ok(!label.parent().hasClass('field_with_errors'));
});
test('Forcing remote validators to run last', function() {
var form = $('form#new_user'), input = form.find('input#user_email');
input.trigger('focusout');
equal(input.parent().find('label').text(), "must be present")
});
test("Don't validate when value hasn't changed", function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
input.trigger('focusout');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
input.val('123');
input.trigger('focusout');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
input.trigger('change');
input.trigger('focusout');
ok(!input.parent().hasClass('field_with_errors'));
ok(!label.parent().hasClass('field_with_errors'));
});
test('Validate when error message needs to change', function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
input.trigger('focusout');
equal(input.parent().find('label.message').text(), "must be present");
input.val('abc');
input.trigger('change')
input.trigger('focusout');
equal(input.parent().find('label.message').text(), "is invalid");
})
test("Don't validate confirmation when not a validatable input", function() {
$('#qunit-fixture')
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user_2'
}))
.find('form')
.append($('Password '))
.append($(' ', {
name: 'user_2[password]',
id: 'user_2_password',
type: 'password'
}))
.append($('Password Confirmation '))
.append($(' ', {
name: 'user_2[password_confirmation]',
id: 'user_2_password_confirmation',
type: 'password'
}))
ClientSideValidations.forms['new_user_2'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: { }
}
$('form#new_user_2').validate();
var form = $('form#new_user_2'), input = form.find('input#user_2_password_confirmation');
input.val('123');
input.trigger('focusout');
ok(!input.parent().hasClass('field_with_errors'));
});
test("Don't validate disabled inputs", function() {
$('#qunit-fixture')
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user_2'
}))
.find('form')
.append($('name '))
.append($(' ', {
name: 'user_2[name]',
id: 'user_2_name',
type: 'name',
disabled: 'disabled'
}))
ClientSideValidations.forms['new_user_2'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: { 'user_2[name]':{"presence":{"message": "must be present"}}}
}
$('form#new_user_2').validate();
var form = $('form#new_user_2'), input = form.find('input#user_2_name');
input.val('');
input.trigger('focusout');
ok(!input.parent().hasClass('field_with_errors'));
});
test("Don't validate dynamically disabled inputs", function() {
$('#qunit-fixture')
.append($('', {
action: '/users',
'data-validate': true,
method: 'post',
id: 'new_user_2'
}))
.find('form')
.append($('name '))
.append($(' ', {
name: 'user_2[name]',
id: 'user_2_name',
type: 'name',
}))
ClientSideValidations.forms['new_user_2'] = {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '
',
label_tag: '
',
validators: { 'user_2[name]':{"presence":{"message": "must be present"}}}
}
$('form#new_user_2').validate();
var form = $('form#new_user_2'), input = form.find('input#user_2_name');
input.attr('disabled', 'disabled');
input.val('');
input.trigger('focusout');
ok(!input.parent().hasClass('field_with_errors'));
});
test('ensure label is scoped to form', function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
$('#qunit-fixture')
.prepend($('', { id: 'other_form', 'data-validate': true })
.append($('Name ')));
var otherLabel = $('form#other_form').find('label')
input.trigger('focusout');
ok(!otherLabel.parent().hasClass('field_with_errors'));
});
test("Return validation result", function() {
var input = $('#user_name');
ok(!input.isValid(ClientSideValidations.forms['new_user'].validators));
input.val('123').data('changed', true);
ok(input.isValid(ClientSideValidations.forms['new_user'].validators));
});
test('Validate when focusouting and field has disabled validations', function() {
var form = $('form#new_user'), input = form.find('input#user_name');
var label = $('label[for="user_name"]');
input.disableClientSideValidations();
input.trigger('focusout');
ok(!input.parent().hasClass('field_with_errors'));
ok(!label.parent().hasClass('field_with_errors'));
input.enableClientSideValidations();
input.trigger('focusout');
ok(input.parent().hasClass('field_with_errors'));
ok(label.parent().hasClass('field_with_errors'));
});
client_side_validations-3.2.6/test/javascript/public/test/validators/ 0000775 0000000 0000000 00000000000 12202276743 0026140 5 ustar 00root root 0000000 0000000 client_side_validations-3.2.6/test/javascript/public/test/validators/acceptance.js 0000664 0000000 0000000 00000003150 12202276743 0030563 0 ustar 00root root 0000000 0000000 module('Acceptance options');
test('when checkbox and checked', function() {
var element = $(' ');
var options = { message: "failed validation" };
element.prop('checked', true)
equal(ClientSideValidations.validators.local.acceptance(element, options), undefined);
});
test('when checkbox and not checked', function() {
var element = $(' ');
var options = { message: "failed validation" };
equal(ClientSideValidations.validators.local.acceptance(element, options), "failed validation");
});
test('when text and value default of 1', function() {
var element = $(' ');
var options = { message: "failed validation" };
element.val("1");
equal(ClientSideValidations.validators.local.acceptance(element, options), undefined);
});
test('when text and value 2 and accept value is 2', function() {
var element = $(' ');
var options = { message: "failed validation", accept: 1 };
element.val("1");
equal(ClientSideValidations.validators.local.acceptance(element, options), undefined);
});
test('when text and value empty', function() {
var element = $(' ');
var options = { message: "failed validation" };
equal(ClientSideValidations.validators.local.acceptance(element, options), "failed validation");
});
test('when text and value 1 and accept value is 2', function() {
var element = $(' ');
var options = { message: "failed validation", accept: 2 };
element.val("1");
equal(ClientSideValidations.validators.local.acceptance(element, options), "failed validation");
});
client_side_validations-3.2.6/test/javascript/public/test/validators/confirmation.js 0000664 0000000 0000000 00000001741 12202276743 0031171 0 ustar 00root root 0000000 0000000 module('Confirmation options', {
setup: function() {
$('#qunit-fixture')
.append(' ')
.append(' ')
}
});
test('when values match', function() {
var password_element = $('#password');
var password_confirmation_element = $('#password_confirmation');
var options = { message: "failed validation" };
password_element.val('test');
password_confirmation_element.val('test');
equal(ClientSideValidations.validators.local.confirmation(password_element, options), undefined);
});
test('when values do not match', function() {
var password_element = $('#password');
var password_confirmation_element = $('#password_confirmation');
var options = { message: "failed validation" };
password_element.val('test');
password_confirmation_element.val('bad test');
equal(ClientSideValidations.validators.local.confirmation(password_element, options), "failed validation");
});
client_side_validations-3.2.6/test/javascript/public/test/validators/exclusion.js 0000664 0000000 0000000 00000003216 12202276743 0030511 0 ustar 00root root 0000000 0000000 module('Exclusion options');
test('when value is not in the list', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'in': [1, 2, 3] };
element.val('4');
equal(ClientSideValidations.validators.local.exclusion(element, options), undefined);
});
test('when value is not in the range', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'range': [1, 3] };
element.val('4');
equal(ClientSideValidations.validators.local.exclusion(element, options), undefined);
});
test('when value is in the list', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'in': [1, 2, 3] };
element.val('1');
equal(ClientSideValidations.validators.local.exclusion(element, options), "failed validation");
});
test('when value is in the range', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'range': [1, 3] };
element.val('1');
equal(ClientSideValidations.validators.local.exclusion(element, options), "failed validation");
});
test('when allowing blank', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'in': [1, 2, 3], allow_blank: true };
equal(ClientSideValidations.validators.local.exclusion(element, options), undefined);
});
test('when not allowing blank', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'in': [1, 2, 3] };
equal(ClientSideValidations.validators.local.exclusion(element, options), "failed validation");
});
client_side_validations-3.2.6/test/javascript/public/test/validators/format.js 0000664 0000000 0000000 00000002101 12202276743 0027760 0 ustar 00root root 0000000 0000000 module('Format options');
test('when matching format', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'with': /\d+/ };
element.val('123');
equal(ClientSideValidations.validators.local.format(element, options), undefined);
});
test('when not matching format', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'with': /\d+/ };
element.val('abc');
equal(ClientSideValidations.validators.local.format(element, options), "failed validation");
});
test('when allowing blank', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'with': /\d+/, 'allow_blank': true };
equal(ClientSideValidations.validators.local.format(element, options), undefined);
});
test('when not allowing blank', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'with': /\d+/ };
equal(ClientSideValidations.validators.local.format(element, options), "failed validation");
});
client_side_validations-3.2.6/test/javascript/public/test/validators/inclusion.js 0000664 0000000 0000000 00000003217 12202276743 0030504 0 ustar 00root root 0000000 0000000 module('Inclusion options');
test('when value is in the list', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'in': [1, 2, 3] };
element.val('1');
equal(ClientSideValidations.validators.local.inclusion(element, options), undefined);
});
test('when value is in the range', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'range': [1, 3] };
element.val('1');
equal(ClientSideValidations.validators.local.inclusion(element, options), undefined);
});
test('when value is not in the list', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'in': [1, 2, 3] };
element.val('4');
equal(ClientSideValidations.validators.local.inclusion(element, options), "failed validation");
});
test('when value is not in the range', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'range': [1, 3] };
element.val('4');
equal(ClientSideValidations.validators.local.inclusion(element, options), "failed validation");
});
test('when allowing blank', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'in': [1, 2, 3], allow_blank: true };
equal(ClientSideValidations.validators.local.inclusion(element, options), undefined);
});
test('when not allowing blank', function() {
var element = $(' ');
var options = { 'message': "failed validation", 'in': [1, 2, 3] };
equal(ClientSideValidations.validators.local.inclusion(element, options), "failed validation");
});
client_side_validations-3.2.6/test/javascript/public/test/validators/length.js 0000664 0000000 0000000 00000006544 12202276743 0027770 0 ustar 00root root 0000000 0000000 module('Length options');
test('when allowed length is 3 and value length is 3', function() {
var element = $(' ');
var options = { messages: { is: "failed validation" }, is: 3 };
element.val('123');
equal(ClientSideValidations.validators.local.length(element, options), undefined);
});
test('when allowed length is 3 and value length is 4', function() {
var element = $(' ');
var options = { messages: { is: "failed validation" }, is: 3 };
element.val('1234');
equal(ClientSideValidations.validators.local.length(element, options), "failed validation");
});
test('when allowed length is 3 and value length is 2', function() {
var element = $(' ');
var options = { messages: { is: "failed validation" }, is: 3 };
element.val('12');
equal(ClientSideValidations.validators.local.length(element, options), "failed validation");
});
test('when allowing blank and allowed length is 3', function() {
var element = $(' ');
var options = { messages: { is: "failed validation" }, is: 3, allow_blank: true };
equal(ClientSideValidations.validators.local.length(element, options), undefined);
});
test('when allowing blank and minimum length is 3 and maximum length is 100', function() {
var element = $(' ');
var options = { messages: { minimum: "failed minimum validation", maximum: "failed maximum validation" }, minimum: 3, maximum: 100, allow_blank: true };
equal(ClientSideValidations.validators.local.length(element, options), undefined);
});
test('when not allowing blank and allowed length is 3', function() {
var element = $(' ');
var options = { messages: { is: "failed validation" }, is: 3 };
equal(ClientSideValidations.validators.local.length(element, options), "failed validation");
});
test('when allowed length is 3 and a differnet tokenizer', function() {
var element = $(' ');
element.val("one two three");
var options = { messages: { is: "failed validation" }, is: 3, js_tokenizer: "match(/\\w+/g)" };
equal(ClientSideValidations.validators.local.length(element, options), undefined);
});
test('when allowed length minimum is 3 and value length is 3', function() {
var element = $(' ');
var options = { messages: { is: "failed validation" }, is: 3 };
element.val('123');
equal(ClientSideValidations.validators.local.length(element, options), undefined);
});
test('when allowed length minimum is 3 and value length is 2', function() {
var element = $(' ');
var options = { messages: { minimum: "failed validation" }, minimum: 3 };
element.val('12');
equal(ClientSideValidations.validators.local.length(element, options), "failed validation");
});
test('when allowed length maximum is 3 and value length is 3', function() {
var element = $(' ');
var options = { messages: { is: "failed validation" }, is: 3 };
element.val('123');
equal(ClientSideValidations.validators.local.length(element, options), undefined);
});
test('when allowed length maximum is 3 and value length is 4', function() {
var element = $(' ');
var options = { messages: { maximum: "failed validation" }, maximum: 3 };
element.val('1234');
equal(ClientSideValidations.validators.local.length(element, options), "failed validation");
});
client_side_validations-3.2.6/test/javascript/public/test/validators/numericality.js 0000664 0000000 0000000 00000026054 12202276743 0031212 0 ustar 00root root 0000000 0000000 module('Numericality options');
// test('when value is a number', function() {
// var element = $(' ');
// var options = { messages: { numericality: "failed validation" } };
// element.val('123');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when value is a decimal number', function() {
// var element = $(' ');
// var options = { messages: { numericality: "failed validation" } };
// element.val('123.456');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when there is a custom numericality pattern', function() {
// var element = $(' ');
// var options = { messages: { numericality: "failed validation" } };
// var oldPattern = ClientSideValidations.patterns.numericality;
// element.val('123,45');
// ClientSideValidations.patterns.numericality = /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d*)?$/;
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// ClientSideValidations.patterns.numericality = oldPattern;
// });
// test('when value is not a number', function() {
// var element = $(' ');
// var options = { messages: { numericality: "failed validation" } };
// element.val('abc123');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when no value', function() {
// var element = $(' ');
// var options = { messages: { numericality: "failed validation" } };
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
test('when no value and allowing blank', function() {
var element = $(' ');
var options = { messages: { numericality: "failed validation" }, allow_blank: true };
equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
});
// test('when bad value and allowing blank', function() {
// var element = $(' ');
// var options = { messages: { numericality: "failed validation" }, allow_blank: true };
// element.val('abc123');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when only allowing integers and value is integer', function() {
// var element = $(' ');
// var options = { messages: { only_integer: "failed validation", numericality: "failed validation" }, only_integer: true };
// element.val('123');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when only allowing integers and value is integer with whitespace', function() {
// var element = $(' ');
// var options = { messages: { only_integer: "failed validation", numericality: "failed validation" }, only_integer: true };
// element.val(' 123 ');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when only allowing integers and value has a negative or positive sign', function() {
// var element = $(' ');
// var options = { messages: { only_integer: "failed validation", numericality: "failed validation" }, only_integer: true };
// element.val('-23');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// element.val('+23');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when only allowing integers and value is not integer', function() {
// var element = $(' ');
// var options = { messages: { only_integer: "failed validation", numericality: "failed validation" }, only_integer: true };
// element.val('123.456');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when only allowing values greater than 10 and value is greater than 10', function() {
// var element = $(' ');
// var options = { messages: { greater_than: "failed validation", numericality: "failed validation" }, greater_than: 10 };
// element.val('11');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when only allowing values greater than 10 and value is 10', function() {
// var element = $(' ');
// var options = { messages: { greater_than: "failed validation", numericality: "failed validation" }, greater_than: 10 };
// element.val('10');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when only allowing values greater than or equal to 10 and value is 10', function() {
// var element = $(' ');
// var options = { messages: { greater_than_or_equal_to: "failed validation", numericality: "failed validation" }, greater_than_or_equal_to: 10 };
// element.val('10');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when only allowing values greater than or equal to 10 and value is 9', function() {
// var element = $(' ');
// var options = { messages: { greater_than_or_equal_to: "failed validation", numericality: "failed validation" }, greater_than_or_equal_to: 10 };
// element.val('9');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when only allowing values less than 10 and value is less than 10', function() {
// var element = $(' ');
// var options = { messages: { less_than: "failed validation", numericality: "failed validation" }, less_than: 10 };
// element.val('9');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when only allowing values less than 10 and value is 10', function() {
// var element = $(' ');
// var options = { messages: { less_than: "failed validation", numericality: "failed validation" }, less_than: 10 };
// element.val('10');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when only allowing values less than or equal to 10 and value is 10', function() {
// var element = $(' ');
// var options = { messages: { less_than_or_equal_to: "failed validation", numericality: "failed validation" }, less_than_or_equal_to: 10 };
// element.val('10');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when only allowing values less than or equal to 10 and value is 11', function() {
// var element = $(' ');
// var options = { messages: { less_than_or_equal_to: "failed validation", numericality: "failed validation" }, less_than_or_equal_to: 10 };
// element.val('11');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when only allowing values equal to 10 and value is 10', function() {
// var element = $(' ');
// var options = { messages: { equal_to: "failed validation", numericality: "failed validation" }, equal_to: 10 };
// element.val('10');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when only allowing values equal to 10 and value is 11', function() {
// var element = $(' ');
// var options = { messages: { equal_to: "failed validation", numericality: "failed validation" }, equal_to: 10 };
// element.val('11');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when only allowing value equal to 0 and value is 1', function() {
// var element = $(' ');
// var options = { messages: { equal_to: "failed validation", numericality: "failed validation" }, equal_to: 0 };
// element.val('1');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when only allowing odd values and the value is odd', function() {
// var element = $(' ');
// var options = { messages: { odd: "failed validation", numericality: "failed validation" }, odd: true };
// element.val('11');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when only allowing odd values and the value is even', function() {
// var element = $(' ');
// var options = { messages: { odd: "failed validation", numericality: "failed validation" }, odd: true };
// element.val('10');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when only allowing even values and the value is even', function() {
// var element = $(' ');
// var options = { messages: { even: "failed validation", numericality: "failed validation" }, even: true };
// element.val('10');
// equal(ClientSideValidations.validators.local.numericality(element, options), undefined);
// });
// test('when only allowing even values and the value is odd', function() {
// var element = $(' ');
// var options = { messages: { even: "failed validation", numericality: "failed validation" }, even: true };
// element.val('11');
// equal(ClientSideValidations.validators.local.numericality(element, options), "failed validation");
// });
// test('when value refers to another present input', function() {
// var form = $('')
// var element_1 = $(' ');
// var element_2 = $(' ');
// var options = { messages: { greater_than: "failed to be greater", numericality: "failed validation" }, greater_than: 'points_2' };
// form.append(element_1).append(element_2);
// $('#qunit-fixture')
// .append(form);
// element_1.val(0)
// element_2.val(1)
// equal(ClientSideValidations.validators.local.numericality(element_1, options), "failed to be greater");
// element_1.val(2)
// equal(ClientSideValidations.validators.local.numericality(element_1, options), undefined);
// });
// test('when value refers to another present input but with more than one match', function() {
// var form = $('')
// var element_1 = $(' ');
// var element_2 = $(' ');
// var element_3 = $(' ');
// var options = { messages: { greater_than: "failed to be greater", numericality: "failed validation" }, greater_than: 'points_2' };
// form.append(element_1).append(element_2).append(element_3);
// $('#qunit-fixture')
// .append(form);
// element_1.val(1)
// element_2.val(2)
// element_3.val(0)
// equal(ClientSideValidations.validators.local.numericality(element_1, options), undefined);
// });
client_side_validations-3.2.6/test/javascript/public/test/validators/presence.js 0000664 0000000 0000000 00000001450 12202276743 0030302 0 ustar 00root root 0000000 0000000 module('Presence options');
test('when value is not empty', function() {
var element = $(' ');
var options = { message: "failed validation" };
element.val('not empty');
equal(ClientSideValidations.validators.local.presence(element, options), undefined);
});
test('when value is empty', function() {
var element = $(' ');
var options = { message: "failed validation" };
equal(ClientSideValidations.validators.local.presence(element, options), "failed validation");
});
test('when value is null from non-selected multi-select element', function() {
var element = $('