validation_sync 0.0.4 → 0.0.5

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 (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