judge 0.5.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. data/.gitignore +8 -0
  2. data/.travis.yml +2 -1
  3. data/Gemfile +1 -10
  4. data/Rakefile +9 -44
  5. data/judge.gemspec +17 -164
  6. data/lib/generators/judge/templates/json2.js +46 -42
  7. data/lib/generators/judge/templates/judge.js +42 -41
  8. data/lib/generators/judge/templates/underscore.js +219 -97
  9. data/lib/judge.rb +6 -4
  10. data/lib/judge/form_builder.rb +75 -0
  11. data/lib/judge/{utils.rb → message_collection.rb} +45 -28
  12. data/lib/judge/validator.rb +21 -0
  13. data/lib/judge/validator_collection.rb +28 -0
  14. data/lib/judge/version.rb +3 -0
  15. data/spec/javascripts/JudgeSpec.js +25 -23
  16. data/test/expected_elements.rb +235 -0
  17. data/test/factories.rb +23 -0
  18. data/test/setup.rb +70 -0
  19. data/test/test_form_builder.rb +69 -0
  20. data/test/test_helper.rb +8 -20
  21. data/test/test_message_collection.rb +84 -0
  22. data/test/test_validator.rb +37 -0
  23. data/test/test_validator_collection.rb +19 -0
  24. metadata +46 -137
  25. data/.document +0 -5
  26. data/Gemfile.lock +0 -116
  27. data/VERSION +0 -1
  28. data/docs/docco.css +0 -196
  29. data/docs/judge.html +0 -280
  30. data/lib/judge/form.rb +0 -59
  31. data/test/dummy/Gemfile +0 -3
  32. data/test/dummy/Gemfile.lock +0 -75
  33. data/test/dummy/Rakefile +0 -7
  34. data/test/dummy/app/controllers/application_controller.rb +0 -3
  35. data/test/dummy/app/controllers/foos_controller.rb +0 -11
  36. data/test/dummy/app/helpers/application_helper.rb +0 -2
  37. data/test/dummy/app/models/city.rb +0 -5
  38. data/test/dummy/app/models/continent.rb +0 -4
  39. data/test/dummy/app/models/country.rb +0 -6
  40. data/test/dummy/app/models/fake.rb +0 -2
  41. data/test/dummy/app/models/foo.rb +0 -19
  42. data/test/dummy/app/views/foos/new.html.erb +0 -71
  43. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  44. data/test/dummy/config.ru +0 -4
  45. data/test/dummy/config/application.rb +0 -45
  46. data/test/dummy/config/boot.rb +0 -10
  47. data/test/dummy/config/database.yml +0 -22
  48. data/test/dummy/config/environment.rb +0 -5
  49. data/test/dummy/config/environments/development.rb +0 -26
  50. data/test/dummy/config/environments/production.rb +0 -49
  51. data/test/dummy/config/environments/test.rb +0 -35
  52. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  53. data/test/dummy/config/initializers/inflections.rb +0 -10
  54. data/test/dummy/config/initializers/mime_types.rb +0 -5
  55. data/test/dummy/config/initializers/secret_token.rb +0 -7
  56. data/test/dummy/config/initializers/session_store.rb +0 -8
  57. data/test/dummy/config/locales/en.yml +0 -12
  58. data/test/dummy/config/routes.rb +0 -3
  59. data/test/dummy/db/development.sqlite3 +0 -0
  60. data/test/dummy/db/migrate/20110624115516_create_foos.rb +0 -26
  61. data/test/dummy/db/migrate/20110724201117_create_fake_collections.rb +0 -14
  62. data/test/dummy/db/migrate/20110724201548_rename_fake_collection_to_fake.rb +0 -9
  63. data/test/dummy/db/migrate/20110725082530_create_continent_country_and_city_tables.rb +0 -24
  64. data/test/dummy/db/schema.rb +0 -55
  65. data/test/dummy/db/test.sqlite3 +0 -0
  66. data/test/dummy/log/server.log +0 -0
  67. data/test/dummy/public/404.html +0 -26
  68. data/test/dummy/public/422.html +0 -26
  69. data/test/dummy/public/500.html +0 -26
  70. data/test/dummy/public/favicon.ico +0 -0
  71. data/test/dummy/public/javascripts/application.js +0 -2
  72. data/test/dummy/public/javascripts/controls.js +0 -965
  73. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  74. data/test/dummy/public/javascripts/effects.js +0 -1123
  75. data/test/dummy/public/javascripts/prototype.js +0 -6001
  76. data/test/dummy/public/javascripts/rails.js +0 -175
  77. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  78. data/test/dummy/script/rails +0 -6
  79. data/test/judge_test.rb +0 -186
@@ -1,175 +0,0 @@
1
- (function() {
2
- // Technique from Juriy Zaytsev
3
- // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
4
- function isEventSupported(eventName) {
5
- var el = document.createElement('div');
6
- eventName = 'on' + eventName;
7
- var isSupported = (eventName in el);
8
- if (!isSupported) {
9
- el.setAttribute(eventName, 'return;');
10
- isSupported = typeof el[eventName] == 'function';
11
- }
12
- el = null;
13
- return isSupported;
14
- }
15
-
16
- function isForm(element) {
17
- return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM'
18
- }
19
-
20
- function isInput(element) {
21
- if (Object.isElement(element)) {
22
- var name = element.nodeName.toUpperCase()
23
- return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA'
24
- }
25
- else return false
26
- }
27
-
28
- var submitBubbles = isEventSupported('submit'),
29
- changeBubbles = isEventSupported('change')
30
-
31
- if (!submitBubbles || !changeBubbles) {
32
- // augment the Event.Handler class to observe custom events when needed
33
- Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
34
- function(init, element, eventName, selector, callback) {
35
- init(element, eventName, selector, callback)
36
- // is the handler being attached to an element that doesn't support this event?
37
- if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
38
- (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
39
- // "submit" => "emulated:submit"
40
- this.eventName = 'emulated:' + this.eventName
41
- }
42
- }
43
- )
44
- }
45
-
46
- if (!submitBubbles) {
47
- // discover forms on the page by observing focus events which always bubble
48
- document.on('focusin', 'form', function(focusEvent, form) {
49
- // special handler for the real "submit" event (one-time operation)
50
- if (!form.retrieve('emulated:submit')) {
51
- form.on('submit', function(submitEvent) {
52
- var emulated = form.fire('emulated:submit', submitEvent, true)
53
- // if custom event received preventDefault, cancel the real one too
54
- if (emulated.returnValue === false) submitEvent.preventDefault()
55
- })
56
- form.store('emulated:submit', true)
57
- }
58
- })
59
- }
60
-
61
- if (!changeBubbles) {
62
- // discover form inputs on the page
63
- document.on('focusin', 'input, select, texarea', function(focusEvent, input) {
64
- // special handler for real "change" events
65
- if (!input.retrieve('emulated:change')) {
66
- input.on('change', function(changeEvent) {
67
- input.fire('emulated:change', changeEvent, true)
68
- })
69
- input.store('emulated:change', true)
70
- }
71
- })
72
- }
73
-
74
- function handleRemote(element) {
75
- var method, url, params;
76
-
77
- var event = element.fire("ajax:before");
78
- if (event.stopped) return false;
79
-
80
- if (element.tagName.toLowerCase() === 'form') {
81
- method = element.readAttribute('method') || 'post';
82
- url = element.readAttribute('action');
83
- params = element.serialize();
84
- } else {
85
- method = element.readAttribute('data-method') || 'get';
86
- url = element.readAttribute('href');
87
- params = {};
88
- }
89
-
90
- new Ajax.Request(url, {
91
- method: method,
92
- parameters: params,
93
- evalScripts: true,
94
-
95
- onComplete: function(request) { element.fire("ajax:complete", request); },
96
- onSuccess: function(request) { element.fire("ajax:success", request); },
97
- onFailure: function(request) { element.fire("ajax:failure", request); }
98
- });
99
-
100
- element.fire("ajax:after");
101
- }
102
-
103
- function handleMethod(element) {
104
- var method = element.readAttribute('data-method'),
105
- url = element.readAttribute('href'),
106
- csrf_param = $$('meta[name=csrf-param]')[0],
107
- csrf_token = $$('meta[name=csrf-token]')[0];
108
-
109
- var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
110
- element.parentNode.insert(form);
111
-
112
- if (method !== 'post') {
113
- var field = new Element('input', { type: 'hidden', name: '_method', value: method });
114
- form.insert(field);
115
- }
116
-
117
- if (csrf_param) {
118
- var param = csrf_param.readAttribute('content'),
119
- token = csrf_token.readAttribute('content'),
120
- field = new Element('input', { type: 'hidden', name: param, value: token });
121
- form.insert(field);
122
- }
123
-
124
- form.submit();
125
- }
126
-
127
-
128
- document.on("click", "*[data-confirm]", function(event, element) {
129
- var message = element.readAttribute('data-confirm');
130
- if (!confirm(message)) event.stop();
131
- });
132
-
133
- document.on("click", "a[data-remote]", function(event, element) {
134
- if (event.stopped) return;
135
- handleRemote(element);
136
- event.stop();
137
- });
138
-
139
- document.on("click", "a[data-method]", function(event, element) {
140
- if (event.stopped) return;
141
- handleMethod(element);
142
- event.stop();
143
- });
144
-
145
- document.on("submit", function(event) {
146
- var element = event.findElement(),
147
- message = element.readAttribute('data-confirm');
148
- if (message && !confirm(message)) {
149
- event.stop();
150
- return false;
151
- }
152
-
153
- var inputs = element.select("input[type=submit][data-disable-with]");
154
- inputs.each(function(input) {
155
- input.disabled = true;
156
- input.writeAttribute('data-original-value', input.value);
157
- input.value = input.readAttribute('data-disable-with');
158
- });
159
-
160
- var element = event.findElement("form[data-remote]");
161
- if (element) {
162
- handleRemote(element);
163
- event.stop();
164
- }
165
- });
166
-
167
- document.on("ajax:after", "form", function(event, element) {
168
- var inputs = element.select("input[type=submit][disabled=true][data-disable-with]");
169
- inputs.each(function(input) {
170
- input.value = input.readAttribute('data-original-value');
171
- input.removeAttribute('data-original-value');
172
- input.disabled = false;
173
- });
174
- });
175
- })();
File without changes
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
-
4
- APP_PATH = File.expand_path('../../config/application', __FILE__)
5
- require File.expand_path('../../config/boot', __FILE__)
6
- require 'rails/commands'
data/test/judge_test.rb DELETED
@@ -1,186 +0,0 @@
1
- require 'test_helper'
2
-
3
- class JudgeTest < ActionController::TestCase
4
- tests FoosController
5
-
6
- context "JSONified validators" do
7
-
8
- setup { get :new }
9
-
10
- should "include allow_blank validation in data attribute" do
11
- validators = validators_from("input#foo_two_foobar")
12
- assert validators.first["options"]["allow_blank"]
13
- end
14
-
15
- should "include length (within range) validation in data attribute" do
16
- validators = validators_from("input#foo_two_foobar")
17
- assert_equal "length", validators.first["kind"]
18
- assert_equal Fixnum, validators.first["options"]["minimum"].class
19
- assert_equal Fixnum, validators.first["options"]["maximum"].class
20
-
21
- assert validators.first["options"]["allow_blank"]
22
- end
23
-
24
- should "include exclusion validation in data atribute" do
25
- validators = validators_from("select#foo_three")
26
- assert_equal "exclusion", validators.first["kind"]
27
- assert_equal Array, validators.first["options"]["in"].class
28
- end
29
-
30
- should "include numericality validation in data attribute" do
31
- validator = validators_from("textarea#foo_four").first
32
- assert_equal "numericality", validator["kind"]
33
- assert validator["options"]["only_integer"]
34
- assert validator["options"]["odd"]
35
- assert_equal false, validator["options"]["allow_nil"]
36
- assert_equal Fixnum, validator["options"]["less_than_or_equal_to"].class
37
- end
38
-
39
- should "include exclusion validation in data attribute" do
40
- validator = validators_from("textarea#foo_four")[1]
41
- assert_equal "exclusion", validator["kind"]
42
- assert_equal Array, validator["options"]["in"].class
43
- end
44
-
45
- should "include format validator in data attribute" do
46
- validator = validators_from("select#foo_five").first
47
- assert_equal "format", validator["kind"]
48
- assert_match /\(.+\:.+\)/, validator["options"]["without"]
49
- end
50
-
51
- should "include acceptance validator in data attribute" do
52
- validator = validators_from("input#foo_six").first
53
- assert_equal "acceptance", validator["kind"]
54
- assert validator["options"]["accept"]
55
- end
56
-
57
- should "include confirmation validator in data attribute" do
58
- validator = validators_from("input#foo_seven").first
59
- assert_equal "confirmation", validator["kind"]
60
- validator2 = validators_from("input#foo_eight").first
61
- assert_equal "confirmation", validator2["kind"]
62
- end
63
-
64
- should "not include uniqueness validator in data attribute" do
65
- validators = validators_from("#foo_nine")
66
- assert_equal 0, validators.select{ |v| v["kind"] == "uniqueness" }.length
67
- end
68
-
69
- end
70
-
71
- context "form builder" do
72
- setup do
73
- get :new
74
- @form = Nokogiri::HTML(css_select("form").first.to_s)
75
- end
76
-
77
- should "do validated_select" do
78
- assert_equal 1, @form.css("select#foo_one").length
79
- assert_kind "select#foo_one"
80
- end
81
-
82
- should "do validated_radio_button" do
83
- assert_equal 1, @form.css("input#foo_two_foobar").length
84
- assert_kind "input#foo_two_foobar"
85
- end
86
-
87
- should "do validated_collection_select" do
88
- assert_equal 1, @form.css("select#foo_three").length
89
- assert_kind "select#foo_three"
90
- end
91
-
92
- should "do validated_text_area" do
93
- assert_equal 1, @form.css("textarea#foo_four").length
94
- assert_kind "textarea#foo_four"
95
- end
96
-
97
- should "do validated_grouped_collection_select" do
98
- assert_equal 1, @form.css("select#foo_five").length
99
- assert_kind "select#foo_five"
100
- end
101
-
102
- should "do validated_check_box" do
103
- assert_equal 1, @form.css("input#foo_six").length
104
- assert_kind "input#foo_six"
105
- end
106
-
107
- should "do validated_text_field" do
108
- assert_equal 1, @form.css("input#foo_seven").length
109
- assert_kind "input#foo_seven"
110
- end
111
-
112
- should "do validated_password_field" do
113
- assert_equal 1, @form.css("input#foo_eight").length
114
- assert_kind "input#foo_eight"
115
- end
116
-
117
- should "do validated_time_zone_select" do
118
- assert_equal 1, @form.css("select#foo_nine").length
119
- assert_kind "select#foo_nine"
120
- end
121
-
122
- should "do validated_time_select" do
123
- assert_equal 2, @form.css("select[id^=foo_ten]").length
124
- assert_kind "select[id^=foo_ten]"
125
- end
126
-
127
- should "do validated_datetime_select" do
128
- assert_equal 5, @form.css("select[id^=foo_eleven]").length
129
- assert_kind "select[id^=foo_eleven]"
130
- end
131
-
132
- should "do validated_date_select" do
133
- assert_equal 3, @form.css("select[id^=foo_twelve]").length
134
- assert_kind "select[id^=foo_twelve]"
135
- end
136
-
137
- end
138
-
139
- context "data attribute messages option" do
140
-
141
- setup do
142
- get :new
143
- @exclusion_validator = validators_from("select#foo_three").first
144
- end
145
-
146
- should "be present" do
147
- assert_equal Hash, @exclusion_validator["messages"].class
148
- end
149
-
150
- should "include base message" do
151
- assert @exclusion_validator["messages"]["exclusion"], "base message not found"
152
- end
153
-
154
- should "lookup i18n error message" do
155
- assert_equal "activerecord errors messages blank", @exclusion_validator["messages"]["blank"]
156
- end
157
-
158
- should "not include blank message if allow_blank is true" do
159
- length_validator = validators_from("input#foo_two_foobar").first
160
- assert_equal nil, length_validator["messages"]["blank"]
161
- end
162
-
163
- should "include not_an_integer message if only_integer is true" do
164
- numericality_validator = validators_from("textarea#foo_four").first
165
- assert numericality_validator["messages"]["not_an_integer"], "not_an_integer message not found"
166
- end
167
-
168
- end
169
-
170
- def validators_from(selector)
171
- form = Nokogiri::HTML(css_select("form").first.to_s)
172
- data_attribute = form.css(selector).first["data-validate"]
173
- JSON.parse(data_attribute)
174
- end
175
-
176
- def error_messages
177
- form = Nokogiri::HTML(css_select("form").first.to_s)
178
- data_attribute = form.css("form").first["data-error-messages"]
179
- JSON.parse(data_attribute)
180
- end
181
-
182
- def assert_kind(selector)
183
- assert validators_from(selector).first["kind"], "kind of validator not found"
184
- end
185
-
186
- end