validation_sync 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/generate_validations.js.erb +138 -0
  3. data/app/assets/javascripts/validation_sync.js +2 -1
  4. data/app/helpers/validation_sync_form_helper.rb +12 -71
  5. data/lib/validation_sync/engine.rb +2 -0
  6. data/lib/validation_sync/validation_builder.rb +139 -0
  7. data/lib/validation_sync/version.rb +1 -1
  8. data/lib/validation_sync.rb +1 -0
  9. data/spec/dummy/app/controllers/posts_controller.rb +1 -1
  10. data/spec/dummy/app/controllers/users_controller.rb +58 -0
  11. data/spec/dummy/app/models/post.rb +15 -4
  12. data/spec/dummy/app/models/user.rb +11 -0
  13. data/spec/dummy/app/views/posts/_form.html.erb +8 -0
  14. data/spec/dummy/app/views/posts/show.html.erb +5 -0
  15. data/spec/dummy/app/views/users/_form.html.erb +33 -0
  16. data/spec/dummy/app/views/users/edit.html.erb +6 -0
  17. data/spec/dummy/app/views/users/index.html.erb +29 -0
  18. data/spec/dummy/app/views/users/new.html.erb +5 -0
  19. data/spec/dummy/app/views/users/show.html.erb +14 -0
  20. data/spec/dummy/config/application.rb +1 -0
  21. data/spec/dummy/config/routes.rb +3 -0
  22. data/spec/dummy/db/development.sqlite3 +0 -0
  23. data/spec/dummy/db/migrate/20140211200846_create_users.rb +10 -0
  24. data/spec/dummy/db/migrate/20140212170448_add_order_to_posts.rb +5 -0
  25. data/spec/dummy/db/migrate/20140212173012_add_user_id_to_posts.rb +5 -0
  26. data/spec/dummy/db/schema.rb +10 -1
  27. data/spec/dummy/db/test.sqlite3 +0 -0
  28. data/spec/dummy/log/development.log +7256 -0
  29. data/spec/dummy/log/test.log +6037 -0
  30. data/spec/dummy/spec/factories/posts.rb +26 -0
  31. data/spec/dummy/spec/factories/users.rb +14 -0
  32. data/spec/dummy/spec/models/post_spec.rb +98 -0
  33. data/spec/dummy/spec/models/user_spec.rb +27 -0
  34. data/spec/dummy/tmp/cache/assets/development/sprockets/10c6f05e183df4466be1e0171868fbd3 +0 -0
  35. data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  36. data/spec/dummy/tmp/cache/assets/development/sprockets/254f7fcb30f60607963da8bbb320eb25 +0 -0
  37. data/spec/dummy/tmp/cache/assets/development/sprockets/256916ba749d0c14e36b55d4b382e9f5 +0 -0
  38. data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  39. data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  40. data/spec/dummy/tmp/cache/assets/development/sprockets/38ec44893aed52b20a20a929a47e0ad9 +0 -0
  41. data/spec/dummy/tmp/cache/assets/development/sprockets/4a4d6fda449d6b443e5b29ccb755c732 +0 -0
  42. data/spec/dummy/tmp/cache/assets/development/sprockets/513dd40b9b52367f54d64438a9d802b9 +0 -0
  43. data/spec/dummy/tmp/cache/assets/development/sprockets/56146675dbad13c72d3eb9ebd823dc11 +0 -0
  44. data/spec/dummy/tmp/cache/assets/development/sprockets/7aaf7da4e6ec4c84cc7948fb20c35064 +0 -0
  45. data/spec/dummy/tmp/cache/assets/development/sprockets/ba165ee56ce37f61865fe03d6503539b +0 -0
  46. data/spec/dummy/tmp/cache/assets/development/sprockets/bfaeb96080cc4d8ba400fbdcd1d4aab2 +0 -0
  47. data/spec/dummy/tmp/cache/assets/development/sprockets/c4f1b332263aa5004a8ac54ca9530510 +0 -0
  48. data/spec/dummy/tmp/cache/assets/development/sprockets/c63406c52c03bbb24922ded6ebb0e0a2 +0 -0
  49. data/spec/dummy/tmp/cache/assets/development/sprockets/cbc66bd36b3aa4411f9ce20da0fd37a0 +0 -0
  50. data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  51. data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  52. data/spec/dummy/tmp/cache/assets/development/sprockets/d7874cf8a5946ec3899e5bb627905ca5 +0 -0
  53. data/spec/dummy/tmp/cache/assets/development/sprockets/e1d4998592ddfea795aca82d742d9478 +0 -0
  54. data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  55. data/spec/dummy/tmp/cache/assets/test/sprockets/0f11e0b3e0ece93d6c047318f2e5497d +0 -0
  56. data/spec/dummy/tmp/cache/assets/test/sprockets/10c6f05e183df4466be1e0171868fbd3 +0 -0
  57. data/spec/dummy/tmp/cache/assets/test/sprockets/122e92d06837af295d6c941999a8d48f +0 -0
  58. data/spec/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  59. data/spec/dummy/tmp/cache/assets/test/sprockets/254f7fcb30f60607963da8bbb320eb25 +0 -0
  60. data/spec/dummy/tmp/cache/assets/test/sprockets/256916ba749d0c14e36b55d4b382e9f5 +0 -0
  61. data/spec/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  62. data/spec/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  63. data/spec/dummy/tmp/cache/assets/test/sprockets/4a4d6fda449d6b443e5b29ccb755c732 +0 -0
  64. data/spec/dummy/tmp/cache/assets/test/sprockets/56146675dbad13c72d3eb9ebd823dc11 +0 -0
  65. data/spec/dummy/tmp/cache/assets/test/sprockets/bfaeb96080cc4d8ba400fbdcd1d4aab2 +0 -0
  66. data/spec/dummy/tmp/cache/assets/test/sprockets/c4f1b332263aa5004a8ac54ca9530510 +0 -0
  67. data/spec/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  68. data/spec/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  69. data/spec/dummy/tmp/cache/assets/test/sprockets/d7874cf8a5946ec3899e5bb627905ca5 +0 -0
  70. data/spec/dummy/tmp/cache/assets/test/sprockets/e1d4998592ddfea795aca82d742d9478 +0 -0
  71. data/spec/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  72. data/spec/dummy/tmp/capybara/capybara-201402111733312899331645.html +39 -0
  73. data/spec/dummy/tmp/capybara/capybara-201402111742049902988712.html +39 -0
  74. data/spec/dummy/tmp/capybara/capybara-201402111743461497527818.html +39 -0
  75. data/spec/dummy/tmp/capybara/capybara-201402121034216891460553.html +39 -0
  76. data/spec/dummy/tmp/capybara/capybara-201402121100145511229652.html +39 -0
  77. data/spec/dummy/tmp/capybara/capybara-20140212110749239625833.html +39 -0
  78. data/spec/dummy/tmp/capybara/capybara-201402121110009350488348.html +39 -0
  79. data/spec/dummy/tmp/capybara/capybara-201402121242315707153414.html +54 -0
  80. data/spec/dummy/tmp/capybara/capybara-2014021212463939561980.html +47 -0
  81. data/spec/dummy/tmp/capybara/capybara-201402121308362867044001.html +47 -0
  82. data/spec/dummy/tmp/capybara/capybara-201402121309286432044699.html +47 -0
  83. data/spec/dummy/tmp/capybara/capybara-201402121506235794052148.html +39 -0
  84. data/spec/dummy/tmp/capybara/capybara-201402121507316558835315.html +27 -0
  85. data/spec/dummy/tmp/capybara/capybara-201402121512202956445364.html +39 -0
  86. data/spec/dummy/tmp/capybara/capybara-201402121517176338336364.html +39 -0
  87. data/spec/dummy/tmp/capybara/capybara-201402121518121290133083.html +39 -0
  88. data/spec/dummy/tmp/pids/server.pid +1 -0
  89. data/spec/features/form_interactions_spec.rb +153 -0
  90. data/spec/features/generate_validations_spec.rb +26 -0
  91. data/spec/helpers/validation_sync_form_helper_spec.rb +24 -0
  92. data/spec/lib/validation_builder_spec.rb +173 -0
  93. data/spec/spec_helper.rb +7 -1
  94. metadata +120 -11
  95. data/app/assets/javascripts/validations.js.coffee.erb +0 -51
  96. data/spec/dummy/app/assets/javascripts/posts.js +0 -2
  97. data/spec/dummy/app/assets/stylesheets/posts.css +0 -4
  98. data/spec/features/form_validation_spec.rb +0 -53
  99. data/spec/helpers/form_helper_spec.rb +0 -4
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html><html><head>
2
+ <title>Dummy</title>
3
+ <link data-turbolinks-track="true" href="/assets/application.css" media="all" rel="stylesheet">
4
+ <script data-turbolinks-track="true" src="/assets/application.js"></script>
5
+
6
+ </head>
7
+ <body>
8
+
9
+ <h1>New post</h1>
10
+
11
+ <form accept-charset="UTF-8" action="/posts" class="new_post" data-sync-validations="true" id="new_post" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
12
+
13
+ <div class="field">
14
+ <label for="post_title">Title</label><br>
15
+ <input id="post_title" name="post[title]" type="text" class="valid">
16
+ </div>
17
+ <div class="field">
18
+ <label for="post_content">Content</label><br>
19
+ <textarea id="post_content" name="post[content]" class="valid"></textarea>
20
+ </div>
21
+ <div class="field">
22
+ <label for="post_view_count">View count</label><br>
23
+ <input id="post_view_count" name="post[view_count]" type="text" class="valid">
24
+ </div>
25
+ <div class="field">
26
+ <label for="post_order">Order</label><br>
27
+ <input id="post_order" name="post[order]" type="text" class="valid">
28
+ </div>
29
+ <div class="field">
30
+ <label for="post_author_email">Author email</label><br>
31
+ <input id="post_author_email" name="post[author_email]" type="text" class="error"><label for="post_author_email" class="error"></label>
32
+ </div>
33
+ <div class="field">
34
+ <label for="post_user_id">User</label><br>
35
+ <input id="post_user_id" name="post[user_id]" type="text" class="error"><label for="post_user_id" class="error"></label>
36
+ </div>
37
+ <div class="actions">
38
+ <input name="commit" type="submit" value="Create Post">
39
+ </div>
40
+ </form>
41
+
42
+ <a href="/posts">Back</a>
43
+
44
+
45
+
46
+
47
+ </body></html>
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html><html><head>
2
+ <title>Dummy</title>
3
+ <link data-turbolinks-track="true" href="/assets/application.css" media="all" rel="stylesheet">
4
+ <script data-turbolinks-track="true" src="/assets/application.js"></script>
5
+
6
+ </head>
7
+ <body>
8
+
9
+ <h1>New post</h1>
10
+
11
+ <form accept-charset="UTF-8" action="/posts" class="new_post" data-sync-validations="true" id="new_post" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
12
+
13
+ <div class="field">
14
+ <label for="post_title">Title</label><br>
15
+ <input id="post_title" name="post[title]" type="text" class="valid">
16
+ </div>
17
+ <div class="field">
18
+ <label for="post_content">Content</label><br>
19
+ <textarea id="post_content" name="post[content]" class="valid"></textarea>
20
+ </div>
21
+ <div class="field">
22
+ <label for="post_view_count">View count</label><br>
23
+ <input id="post_view_count" name="post[view_count]" type="text" class="valid">
24
+ </div>
25
+ <div class="field">
26
+ <label for="post_order">Order</label><br>
27
+ <input id="post_order" name="post[order]" type="text" class="valid">
28
+ </div>
29
+ <div class="field">
30
+ <label for="post_author_email">Author email</label><br>
31
+ <input id="post_author_email" name="post[author_email]" type="text" class="error"><label for="post_author_email" class="error"></label>
32
+ </div>
33
+ <div class="field">
34
+ <label for="post_user_id">User</label><br>
35
+ <input id="post_user_id" name="post[user_id]" type="text" class="valid">
36
+ </div>
37
+ <div class="actions">
38
+ <input name="commit" type="submit" value="Create Post">
39
+ </div>
40
+ </form>
41
+
42
+ <a href="/posts">Back</a>
43
+
44
+
45
+
46
+
47
+ </body></html>
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html><html><head>
2
+ <title>Dummy</title>
3
+ <link data-turbolinks-track="true" href="/assets/application.css" media="all" rel="stylesheet">
4
+ <script data-turbolinks-track="true" src="/assets/application.js"></script>
5
+
6
+ </head>
7
+ <body>
8
+
9
+ <h1>New user</h1>
10
+
11
+ <form accept-charset="UTF-8" action="/users" class="new_user" data-sync-validations="true" id="new_user" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
12
+
13
+ <div class="field">
14
+ <label for="user_email">Email</label><br>
15
+ <input id="user_email" name="user[email]" type="text" class="error"><label for="user_email" class="error">Please enter the same value again.</label>
16
+ </div>
17
+ <div class="field">
18
+ <label for="user_email_confirmation">Email confirmation</label><br>
19
+ <input id="user_email_confirmation" name="user[email_confirmation]" type="text" class="valid">
20
+ </div>
21
+ <div class="field">
22
+ <label for="user_password">Password</label><br>
23
+ <textarea id="user_password" name="user[password]" class="error"></textarea><label for="user_password" class="error">Please enter the same value again.</label>
24
+ </div>
25
+ <div class="field">
26
+ <label for="user_password_confirmation">Password confirmation</label><br>
27
+ <input id="user_password_confirmation" name="user[password_confirmation]" type="text" class="valid">
28
+ </div>
29
+ <div class="actions">
30
+ <input name="commit" type="submit" value="Create User">
31
+ </div>
32
+ </form>
33
+
34
+ <a href="/users">Back</a>
35
+
36
+
37
+
38
+
39
+ </body></html>
@@ -0,0 +1,27 @@
1
+ <!DOCTYPE html><html><head>
2
+ <title>Dummy</title>
3
+ <link data-turbolinks-track="true" href="/assets/application.css" media="all" rel="stylesheet">
4
+ <script data-turbolinks-track="true" src="/assets/application.js"></script>
5
+
6
+ </head>
7
+ <body>
8
+
9
+ <p id="notice">User was successfully created.</p>
10
+
11
+ <p>
12
+ <strong>Email:</strong>
13
+ email4@example.com
14
+ </p>
15
+
16
+ <p>
17
+ <strong>Password:</strong>
18
+ password!
19
+ </p>
20
+
21
+ <a href="/users/29/edit">Edit</a> |
22
+ <a href="/users">Back</a>
23
+
24
+
25
+
26
+
27
+ </body></html>
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html><html><head>
2
+ <title>Dummy</title>
3
+ <link data-turbolinks-track="true" href="/assets/application.css" media="all" rel="stylesheet">
4
+ <script data-turbolinks-track="true" src="/assets/application.js"></script>
5
+
6
+ </head>
7
+ <body>
8
+
9
+ <h1>New user</h1>
10
+
11
+ <form accept-charset="UTF-8" action="/users" class="new_user" data-sync-validations="true" id="new_user" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
12
+
13
+ <div class="field">
14
+ <label for="user_email">Email</label><br>
15
+ <input id="user_email" name="user[email]" type="text" class="error"><label for="user_email" class="error"></label>
16
+ </div>
17
+ <div class="field">
18
+ <label for="user_email_confirmation">Email confirmation</label><br>
19
+ <input id="user_email_confirmation" name="user[email_confirmation]" type="text" class="valid">
20
+ </div>
21
+ <div class="field">
22
+ <label for="user_password">Password</label><br>
23
+ <textarea id="user_password" name="user[password]" class="error"></textarea><label for="user_password" class="error">Confirm your password, bitch!</label>
24
+ </div>
25
+ <div class="field">
26
+ <label for="user_password_confirmation">Password confirmation</label><br>
27
+ <input id="user_password_confirmation" name="user[password_confirmation]" type="text" class="valid">
28
+ </div>
29
+ <div class="actions">
30
+ <input name="commit" type="submit" value="Create User">
31
+ </div>
32
+ </form>
33
+
34
+ <a href="/users">Back</a>
35
+
36
+
37
+
38
+
39
+ </body></html>
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html><html><head>
2
+ <title>Dummy</title>
3
+ <link data-turbolinks-track="true" href="/assets/application.css" media="all" rel="stylesheet">
4
+ <script data-turbolinks-track="true" src="/assets/application.js"></script>
5
+
6
+ </head>
7
+ <body>
8
+
9
+ <h1>New user</h1>
10
+
11
+ <form accept-charset="UTF-8" action="/users" class="new_user" data-sync-validations="true" id="new_user" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
12
+
13
+ <div class="field">
14
+ <label for="user_email">Email</label><br>
15
+ <input id="user_email" name="user[email]" type="text" class="valid"><label for="user_email" class="error" style="display: none; ">Please enter the same value again.</label>
16
+ </div>
17
+ <div class="field">
18
+ <label for="user_email_confirmation">Email confirmation</label><br>
19
+ <input id="user_email_confirmation" name="user[email_confirmation]" type="text" class="valid">
20
+ </div>
21
+ <div class="field">
22
+ <label for="user_password">Password</label><br>
23
+ <input id="user_password" name="user[password]" type="text" class="error"><label for="user_password" class="error">Please enter the same value again.</label>
24
+ </div>
25
+ <div class="field">
26
+ <label for="user_password_confirmation">Password confirmation</label><br>
27
+ <input id="user_password_confirmation" name="user[password_confirmation]" type="text" class="valid">
28
+ </div>
29
+ <div class="actions">
30
+ <input name="commit" type="submit" value="Create User">
31
+ </div>
32
+ </form>
33
+
34
+ <a href="/users">Back</a>
35
+
36
+
37
+
38
+
39
+ </body></html>
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html><html><head>
2
+ <title>Dummy</title>
3
+ <link data-turbolinks-track="true" href="/assets/application.css" media="all" rel="stylesheet">
4
+ <script data-turbolinks-track="true" src="/assets/application.js"></script>
5
+
6
+ </head>
7
+ <body>
8
+
9
+ <h1>New user</h1>
10
+
11
+ <form accept-charset="UTF-8" action="/users" class="new_user" data-sync-validations="true" id="new_user" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
12
+
13
+ <div class="field">
14
+ <label for="user_email">Email</label><br>
15
+ <input id="user_email" name="user[email]" type="text" class="valid"><label for="user_email" class="error" style="display: none; ">Please enter the same value again.</label>
16
+ </div>
17
+ <div class="field">
18
+ <label for="user_email_confirmation">Email confirmation</label><br>
19
+ <input id="user_email_confirmation" name="user[email_confirmation]" type="text" class="valid">
20
+ </div>
21
+ <div class="field">
22
+ <label for="user_password">Password</label><br>
23
+ <input id="user_password" name="user[password]" type="text" class="error"><label for="user_password" class="error">Please enter the same value again.</label>
24
+ </div>
25
+ <div class="field">
26
+ <label for="user_password_confirmation">Password confirmation</label><br>
27
+ <input id="user_password_confirmation" name="user[password_confirmation]" type="text" class="valid">
28
+ </div>
29
+ <div class="actions">
30
+ <input name="commit" type="submit" value="Create User">
31
+ </div>
32
+ </form>
33
+
34
+ <a href="/users">Back</a>
35
+
36
+
37
+
38
+
39
+ </body></html>
@@ -0,0 +1 @@
1
+ 13129
@@ -0,0 +1,153 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Interacting with forms", :js => true do
4
+
5
+
6
+ describe "posts" do
7
+
8
+ # Helper to quickly complete a valid form
9
+ def complete_form
10
+ @post = attributes_for(:post)
11
+ fill_in "post[title]", :with => @post[:title]
12
+ fill_in "post[content]", :with => @post[:content]
13
+ fill_in "post[view_count]", :with => @post[:view_count]
14
+ fill_in "post[order]", :with => @post[:order]
15
+ fill_in "post[user_id]", :with => @post[:user_id]
16
+ end
17
+
18
+ before :each do
19
+ visit new_post_path
20
+ end
21
+
22
+
23
+ it "creates a valid record" do
24
+ complete_form
25
+ click_button "Create Post"
26
+ expect(page).to have_content @post[:title]
27
+ new_post = Post.last
28
+ expect(current_path).to eq post_path(new_post)
29
+ end
30
+
31
+
32
+
33
+ describe "validates_presence_of" do
34
+
35
+ it "shows the custom message, when defined" do
36
+ complete_form
37
+ fill_in "post[title]", :with => ""
38
+ click_button "Create Post"
39
+ # we should not have changed pages
40
+ expect(current_path).to eq new_post_path
41
+ # We validate the presence of Post.title with the message "You need a title, bro."
42
+ expect(page).to have_content "You need a title, bro."
43
+ end
44
+
45
+ it "shows the default message when no custom message is defined" do
46
+ complete_form
47
+ fill_in "post[content]", :with => ""
48
+ click_button "Create Post"
49
+ # we should not have changed pages
50
+ expect(current_path).to eq new_post_path
51
+ # We validate the presence of Post.content with the default error message
52
+ expect(page).to have_content I18n.t('errors.messages.blank')
53
+ end
54
+
55
+ end # validates_presence_of
56
+
57
+
58
+
59
+ describe "validates_numericality_of" do
60
+
61
+ it "shows the custom message, when defined" do
62
+ complete_form
63
+ fill_in "post[order]", :with => "letters"
64
+ click_button "Create Post"
65
+ # we should not have changed pages
66
+ expect(current_path).to eq new_post_path
67
+ # We validate the numericality of Post.order with the message "Make that shit a number!"
68
+ expect(page).to have_content "Make that shit a number!"
69
+ end
70
+
71
+ it "shows the default message when no custom message is defined" do
72
+ complete_form
73
+ fill_in "post[view_count]", :with => "letters"
74
+ click_button "Create Post"
75
+ # we should not have changed pages
76
+ expect(current_path).to eq new_post_path
77
+ # We validate the numericality of Post.view_count with the default error message
78
+ expect(page).to have_content I18n.t('errors.messages.not_a_number')
79
+ end
80
+
81
+ it "Adds a 'required' validator if :allow_nil => false" do
82
+ complete_form
83
+ fill_in "post[user_id]", :with => ""
84
+ click_button "Create Post"
85
+ # we should not have changed pages
86
+ expect(current_path).to eq new_post_path
87
+ # We validate the numericality (allow_nil = false) of Post.user_id with the message "User ID Must be a number."
88
+ expect(page).to have_content "User ID Must be a number."
89
+ end
90
+
91
+ end # validates_numericality_of
92
+
93
+ end # posts
94
+
95
+
96
+
97
+
98
+ describe "users" do
99
+
100
+ # Helper to quickly complete a valid form
101
+ def complete_form
102
+ @user = attributes_for(:user)
103
+ fill_in "user[email]", :with => @user[:email]
104
+ fill_in "user[email_confirmation]", :with => @user[:email]
105
+ fill_in "user[password]", :with => @user[:password]
106
+ fill_in "user[password_confirmation]", :with => @user[:password]
107
+ end
108
+
109
+ before :each do
110
+ visit new_user_path
111
+ end
112
+
113
+
114
+ it "creates a valid record" do
115
+ complete_form
116
+ click_button "Create User"
117
+ expect(page).to have_content @user[:title]
118
+ new_user = User.last
119
+ expect(current_path).to eq user_path(new_user)
120
+ end
121
+
122
+
123
+
124
+ describe "validates_confirmation_of" do
125
+
126
+ it "shows the custom message, when defined" do
127
+ complete_form
128
+ fill_in "user[password_confirmation]", :with => "differentPassword"
129
+ click_button "Create User"
130
+ # we should not have changed pages
131
+ expect(current_path).to eq new_user_path
132
+ # We validate the confirmation of of User.password with the message "Confirm your password, bitch!"
133
+ expect(page).to have_content "Confirm your password, bitch!"
134
+ end
135
+
136
+ it "shows the default message when no custom message is defined" do
137
+ complete_form
138
+ fill_in "user[email_confirmation]", :with => ""
139
+ click_button "Create User"
140
+ # we should not have changed pages
141
+ expect(current_path).to eq new_user_path
142
+ # We validate the confirmation of of User.email with the default error message
143
+ expect(page).to have_content I18n.t('errors.messages.confirmation', attribute: "Email")
144
+ end
145
+
146
+ end # validates_confirmation_of
147
+
148
+ end # users
149
+
150
+
151
+
152
+ end # Interacting with forms
153
+
@@ -0,0 +1,26 @@
1
+ # require 'spec_helper'
2
+
3
+ # describe "Generating Validation JS" do
4
+
5
+ # before :each do
6
+ # visit "/assets/generate_validations.js"
7
+ # end
8
+
9
+
10
+
11
+ # describe "creating a method for each model" do
12
+
13
+ # it "wraps the page in a function" do
14
+ # expect(page).to have_content "ValidationSync"
15
+ # end
16
+
17
+ # it "creates an init method for each ActiveRecord model" do
18
+ # expect(page).to have_content "validatePost"
19
+ # expect(page).to have_content "validateUser"
20
+ # end
21
+
22
+ # end # creating a method for each model
23
+
24
+
25
+
26
+ # end # Generating Validation JS
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe ValidationSyncFormHelper do
4
+
5
+ describe "Overriding the Form Builder" do
6
+
7
+ it "adds the 'data-sync-validations' attribute to all forms" do
8
+ form = form_for(Post.new) {|p| }
9
+ expect(form).to include "data-sync-validations="
10
+ end
11
+
12
+ it "defaults to data-sync-validations = false" do
13
+ form = form_for(Post.new) {|p| }
14
+ expect(form).to include 'data-sync-validations="false"'
15
+ end
16
+
17
+ it "allows you to set data-sync-validations = true" do
18
+ form = form_for(Post.new, :validate => true) {|p| }
19
+ expect(form).to include 'data-sync-validations="true"'
20
+ end
21
+
22
+ end # Overriding the Form Builder
23
+
24
+ end
@@ -0,0 +1,173 @@
1
+ require 'spec_helper'
2
+
3
+ describe ValidationBuilder do
4
+
5
+ before :each do
6
+ @builder = ValidationBuilder.new
7
+ end
8
+
9
+
10
+ describe "setting default arguments" do
11
+
12
+ it "gives you access to 'object_name' attribute" do
13
+ expect(ValidationBuilder.method_defined?(:object_name)).to be_true
14
+ end
15
+
16
+ it "gives you access to 'method' attribute" do
17
+ expect(ValidationBuilder.method_defined?(:method)).to be_true
18
+ end
19
+
20
+ end
21
+
22
+
23
+ describe "the find_all_models method" do
24
+
25
+ it "returns an array" do
26
+ expect(@builder.find_all_models).to be_a(Array)
27
+ end
28
+
29
+ it "lists all of the app's models by name" do
30
+ post_model = {
31
+ name: "post",
32
+ attributes: ["id","title","content","view_count","author_email","created_at","updated_at","order","user_id"]
33
+ }
34
+
35
+ user_model = {
36
+ name: "user",
37
+ attributes: ["id","email","password","created_at","updated_at"]
38
+ }
39
+
40
+ expect(@builder.find_all_models).to include post_model
41
+ expect(@builder.find_all_models).to include user_model
42
+ end
43
+
44
+ end # the find_all_models method
45
+
46
+
47
+
48
+
49
+ describe "get_model_validation" do
50
+
51
+ it "returns a validation object if a model uses the given validation" do
52
+ # our dummy app validates the presence of Post.title
53
+ check = @builder.get_model_validation("post", :title, ActiveRecord::Validations::PresenceValidator)
54
+ expect(check.class).to eq ActiveRecord::Validations::PresenceValidator
55
+ end
56
+
57
+ it "makes use of the builder's default arguments" do
58
+ @builder.object_name = "post"
59
+ @builder.method = :title
60
+ # our dummy app validates the presence of Post.title
61
+ check = @builder.get_model_validation(ActiveRecord::Validations::PresenceValidator)
62
+ expect(check.class).to eq ActiveRecord::Validations::PresenceValidator
63
+ end
64
+
65
+ it "returns nil if a model doesn't use a given validation" do
66
+ # our dummy app does not validate the Numericality of Post.content
67
+ check = @builder.get_model_validation("post", :content, ActiveModel::Validations::NumericalityValidator)
68
+ expect(check).to eq nil
69
+ end
70
+
71
+ end # check_model_validation
72
+
73
+
74
+
75
+
76
+ describe "check_model_validation" do
77
+
78
+ it "returns true if a model uses a given validation" do
79
+ # our dummy app validates the presence of Post.title
80
+ check = @builder.check_model_validation("post", :title, ActiveRecord::Validations::PresenceValidator)
81
+ expect(check).to eq true
82
+ end
83
+
84
+ it "makes use of the builder's default arguments" do
85
+ @builder.object_name = "post"
86
+ @builder.method = :title
87
+ # our dummy app validates the presence of Post.title
88
+ check = @builder.check_model_validation(ActiveRecord::Validations::PresenceValidator)
89
+ expect(check).to eq true
90
+ end
91
+
92
+ it "returns false if a model doesn't use a given validation" do
93
+ # our dummy app does not validate the Numericality of Post.content
94
+ check = @builder.check_model_validation("post", :content, ActiveModel::Validations::NumericalityValidator)
95
+ expect(check).to eq false
96
+ end
97
+
98
+ end # check_model_validation
99
+
100
+
101
+
102
+
103
+ describe "get_validation_attr" do
104
+
105
+ it "returns an validation option's value if that option is present" do
106
+ # our dummy app validates the length of Post.title, :minimum => 5
107
+ check = @builder.get_validation_attr("post", :title, ActiveModel::Validations::LengthValidator, :minimum)
108
+ expect(check).to eq 5
109
+ end
110
+
111
+ it "makes use of the builder's default arguments" do
112
+ @builder.object_name = "post"
113
+ @builder.method = :title
114
+ # our dummy app validates the length of Post.title, :minimum => 5
115
+ check = @builder.get_validation_attr(ActiveModel::Validations::LengthValidator, :minimum)
116
+ expect(check).to eq 5
117
+ end
118
+
119
+ it "returns nil if that option is not present" do
120
+ # our dummy app validates the length of Post.title, but not :maximum
121
+ check = @builder.get_validation_attr("post", :title, ActiveModel::Validations::LengthValidator, :maximum)
122
+ expect(check).to eq nil
123
+ end
124
+
125
+ it "returns nil if that validation is not used at all" do
126
+ # our dummy app does not validate the length of Post.author_email
127
+ check = @builder.get_validation_attr("post", :author_email, ActiveModel::Validations::LengthValidator, :maximum)
128
+ expect(check).to eq nil
129
+ end
130
+
131
+ end # get_validation_attr
132
+
133
+
134
+
135
+
136
+ describe "get_validation_message" do
137
+
138
+ it "returns a custom validation message, if one exists" do
139
+ # our dummy app validates the presence of Post.title with the message "You need a title, bro."
140
+ message = @builder.get_validation_message("post", :title, ActiveRecord::Validations::PresenceValidator)
141
+ expect(message).to eq "You need a title, bro."
142
+ end
143
+
144
+ it "makes use of the builder's default arguments" do
145
+ @builder.object_name = "post"
146
+ @builder.method = :title
147
+ # our dummy app validates the presence of Post.title with the message "You need a title, bro."
148
+ message = @builder.get_validation_message(ActiveRecord::Validations::PresenceValidator)
149
+ expect(message).to eq "You need a title, bro."
150
+ end
151
+
152
+ it "returns nil if that validation is not used at all" do
153
+ # our dummy app doesn't validate the presence of Post.author_email
154
+ message = @builder.get_validation_message("post", :author_email, ActiveRecord::Validations::PresenceValidator)
155
+ expect(message).to eq nil
156
+ end
157
+
158
+ it "returns a default validation message, if a custom message is not defined" do
159
+ # our dummy app validates the presence of Post.content, but provides no custom message
160
+ message = @builder.get_validation_message("post", :content, ActiveRecord::Validations::PresenceValidator)
161
+ expect(message).to eq I18n.t('errors.messages.blank')
162
+ end
163
+
164
+ it "returns the default validation message for validates_confirmation_of attributes" do
165
+ # our dummy app validates the confirmation of User.email, but provides no custom message
166
+ message = @builder.get_validation_message("user", :email, ActiveModel::Validations::ConfirmationValidator)
167
+ expect(message).to eq I18n.t('errors.messages.confirmation', attribute: "Email")
168
+ end
169
+
170
+ end # get_validation_message
171
+
172
+
173
+ end # ValidationBuilder