incline 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +186 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +208 -0
- data/Rakefile +37 -0
- data/app/assets/fonts/incline/.keep +0 -0
- data/app/assets/images/incline/.keep +0 -0
- data/app/assets/images/incline/barcode-B.svg +181 -0
- data/app/assets/javascripts/incline/activate_classed_items.js +11 -0
- data/app/assets/javascripts/incline/application.js +30 -0
- data/app/assets/javascripts/incline/bootstrap-datepicker.js +1800 -0
- data/app/assets/javascripts/incline/datatables.js +22193 -0
- data/app/assets/javascripts/incline/escapeHtml.js +10 -0
- data/app/assets/javascripts/incline/inline_actions.js +479 -0
- data/app/assets/javascripts/incline/jquery.doubleScroll.js +112 -0
- data/app/assets/javascripts/incline/jquery.number.js +764 -0
- data/app/assets/javascripts/incline/regexMask.js +27 -0
- data/app/assets/javascripts/incline/select2/i18n/en.js +3 -0
- data/app/assets/javascripts/incline/select2/select2.full.js +6436 -0
- data/app/assets/stylesheets/incline/application.css +18 -0
- data/app/assets/stylesheets/incline/bootstrap-theme.min.css +5 -0
- data/app/assets/stylesheets/incline/custom.scss +279 -0
- data/app/assets/stylesheets/incline/datatables.css +494 -0
- data/app/assets/stylesheets/incline/datepicker3.css +790 -0
- data/app/assets/stylesheets/incline/select2.css +484 -0
- data/app/controllers/incline/access_groups_controller.rb +127 -0
- data/app/controllers/incline/access_test_controller.rb +30 -0
- data/app/controllers/incline/account_activations_controller.rb +28 -0
- data/app/controllers/incline/application_controller.rb +11 -0
- data/app/controllers/incline/contact_controller.rb +34 -0
- data/app/controllers/incline/password_resets_controller.rb +113 -0
- data/app/controllers/incline/security_controller.rb +100 -0
- data/app/controllers/incline/sessions_controller.rb +50 -0
- data/app/controllers/incline/users_controller.rb +304 -0
- data/app/controllers/incline/welcome_controller.rb +19 -0
- data/app/helpers/incline/.keep +0 -0
- data/app/mailers/incline/application_mailer_base.rb +11 -0
- data/app/mailers/incline/contact_form.rb +19 -0
- data/app/mailers/incline/user_mailer.rb +45 -0
- data/app/models/incline/access_group.rb +121 -0
- data/app/models/incline/access_group_group_member.rb +12 -0
- data/app/models/incline/access_group_user_member.rb +10 -0
- data/app/models/incline/action_group.rb +12 -0
- data/app/models/incline/action_security.rb +222 -0
- data/app/models/incline/contact_message.rb +37 -0
- data/app/models/incline/disable_info.rb +20 -0
- data/app/models/incline/password_reset.rb +14 -0
- data/app/models/incline/password_reset_request.rb +14 -0
- data/app/models/incline/user.rb +437 -0
- data/app/models/incline/user_login_history.rb +30 -0
- data/app/views/incline/access_groups/_details.json.jbuilder +10 -0
- data/app/views/incline/access_groups/_form.html.erb +19 -0
- data/app/views/incline/access_groups/_list.html.erb +60 -0
- data/app/views/incline/access_groups/_messages.json.jbuilder +6 -0
- data/app/views/incline/access_groups/edit.html.erb +2 -0
- data/app/views/incline/access_groups/index.html.erb +6 -0
- data/app/views/incline/access_groups/index.json.jbuilder +16 -0
- data/app/views/incline/access_groups/new.html.erb +2 -0
- data/app/views/incline/access_groups/show.html.erb +9 -0
- data/app/views/incline/access_groups/show.json.jbuilder +11 -0
- data/app/views/incline/contact/new.html.erb +22 -0
- data/app/views/incline/contact_form/contact.html.erb +16 -0
- data/app/views/incline/contact_form/contact.text.erb +13 -0
- data/app/views/incline/password_resets/edit.html.erb +16 -0
- data/app/views/incline/password_resets/new.html.erb +12 -0
- data/app/views/incline/security/_details.json.jbuilder +7 -0
- data/app/views/incline/security/_form.html.erb +20 -0
- data/app/views/incline/security/_list.html.erb +89 -0
- data/app/views/incline/security/_messages.json.jbuilder +6 -0
- data/app/views/incline/security/edit.html.erb +2 -0
- data/app/views/incline/security/index.html.erb +6 -0
- data/app/views/incline/security/index.json.jbuilder +16 -0
- data/app/views/incline/security/show.html.erb +31 -0
- data/app/views/incline/security/show.json.jbuilder +11 -0
- data/app/views/incline/sessions/new.html.erb +26 -0
- data/app/views/incline/user_mailer/account_activation.html.erb +7 -0
- data/app/views/incline/user_mailer/account_activation.text.erb +6 -0
- data/app/views/incline/user_mailer/invalid_password_reset.html.erb +3 -0
- data/app/views/incline/user_mailer/invalid_password_reset.text.erb +5 -0
- data/app/views/incline/user_mailer/password_reset.html.erb +8 -0
- data/app/views/incline/user_mailer/password_reset.text.erb +7 -0
- data/app/views/incline/users/_details.json.jbuilder +32 -0
- data/app/views/incline/users/_form.html.erb +21 -0
- data/app/views/incline/users/_list.html.erb +102 -0
- data/app/views/incline/users/_messages.json.jbuilder +6 -0
- data/app/views/incline/users/disable_confirm.html.erb +19 -0
- data/app/views/incline/users/edit.html.erb +5 -0
- data/app/views/incline/users/index.html.erb +6 -0
- data/app/views/incline/users/index.json.jbuilder +16 -0
- data/app/views/incline/users/new.html.erb +5 -0
- data/app/views/incline/users/show.html.erb +12 -0
- data/app/views/incline/users/show.json.jbuilder +11 -0
- data/app/views/incline/welcome/home.html.erb +5 -0
- data/app/views/layouts/application.html.erb +1 -0
- data/app/views/layouts/incline/_account_menu.html.erb +18 -0
- data/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
- data/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
- data/app/views/layouts/incline/_footer.html.erb +13 -0
- data/app/views/layouts/incline/_header.html.erb +21 -0
- data/app/views/layouts/incline/_html_mailer.html.erb +5 -0
- data/app/views/layouts/incline/_incline_app.html.erb +25 -0
- data/app/views/layouts/incline/_messages.html.erb +3 -0
- data/app/views/layouts/incline/_shim.html.erb +3 -0
- data/app/views/layouts/incline/_text_mailer.text.erb +1 -0
- data/app/views/layouts/incline/application.html.erb +1 -0
- data/app/views/layouts/mailer.html.erb +2 -0
- data/app/views/layouts/mailer.text.erb +2 -0
- data/bin/rails +12 -0
- data/bin/test_scaffold.sh +10 -0
- data/config/routes.rb +61 -0
- data/db/migrate/20170511230126_create_incline_users.rb +26 -0
- data/db/migrate/20170515003052_create_incline_access_groups.rb +10 -0
- data/db/migrate/20170515003221_create_incline_user_login_histories.rb +12 -0
- data/db/migrate/20170515150908_create_incline_access_group_user_members.rb +11 -0
- data/db/migrate/20170515151058_create_incline_access_group_group_members.rb +11 -0
- data/db/migrate/20170517193432_add_comments_to_incline_user.rb +5 -0
- data/db/migrate/20170622132700_create_incline_action_securities.rb +16 -0
- data/db/migrate/20170622172712_create_incline_action_groups.rb +11 -0
- data/db/migrate/20170622195742_add_non_standard_to_action_security.rb +5 -0
- data/db/migrate/20170622230422_add_visible_to_action_security.rb +5 -0
- data/db/seeds.rb +81 -0
- data/exe/new_incline_app +42 -0
- data/lib/generators/incline/install_generator.rb +259 -0
- data/lib/generators/incline/templates/_app_menu_anon.html.erb +1 -0
- data/lib/generators/incline/templates/_app_menu_authenticated.html.erb +1 -0
- data/lib/generators/incline/templates/incline_application.css +17 -0
- data/lib/generators/incline/templates/incline_application.html.erb +1 -0
- data/lib/generators/incline/templates/incline_application.js +12 -0
- data/lib/generators/incline/templates/incline_database.yml +25 -0
- data/lib/generators/incline/templates/incline_email.yml +20 -0
- data/lib/generators/incline/templates/incline_mailer.html.erb +2 -0
- data/lib/generators/incline/templates/incline_mailer.text.erb +2 -0
- data/lib/generators/incline/templates/incline_users.yml +64 -0
- data/lib/generators/incline/templates/incline_version.rb +3 -0
- data/lib/incline/auth_engine_base.rb +52 -0
- data/lib/incline/data_tables_request.rb +336 -0
- data/lib/incline/date_time_formats.rb +6 -0
- data/lib/incline/engine.rb +212 -0
- data/lib/incline/errors.rb +15 -0
- data/lib/incline/extensions/action_controller_base.rb +526 -0
- data/lib/incline/extensions/action_mailer_base.rb +66 -0
- data/lib/incline/extensions/action_view_base.rb +489 -0
- data/lib/incline/extensions/active_record_base.rb +308 -0
- data/lib/incline/extensions/application.rb +137 -0
- data/lib/incline/extensions/application_configuration.rb +50 -0
- data/lib/incline/extensions/connection_adapter.rb +55 -0
- data/lib/incline/extensions/date_time_value.rb +123 -0
- data/lib/incline/extensions/date_value.rb +77 -0
- data/lib/incline/extensions/decimal_value.rb +55 -0
- data/lib/incline/extensions/erb_scaffold_generator.rb +31 -0
- data/lib/incline/extensions/float_value.rb +59 -0
- data/lib/incline/extensions/form_builder.rb +617 -0
- data/lib/incline/extensions/integer_value.rb +54 -0
- data/lib/incline/extensions/jbuilder_generator.rb +38 -0
- data/lib/incline/extensions/jbuilder_template.rb +39 -0
- data/lib/incline/extensions/main_app.rb +40 -0
- data/lib/incline/extensions/numeric.rb +63 -0
- data/lib/incline/extensions/object.rb +31 -0
- data/lib/incline/extensions/resource_route_generator.rb +53 -0
- data/lib/incline/extensions/session.rb +113 -0
- data/lib/incline/extensions/string.rb +50 -0
- data/lib/incline/extensions/test_case.rb +764 -0
- data/lib/incline/extensions/time_zone_converter.rb +40 -0
- data/lib/incline/global_status.rb +236 -0
- data/lib/incline/helpers/route_hash_formatter.rb +46 -0
- data/lib/incline/json_log_formatter.rb +96 -0
- data/lib/incline/json_logger.rb +17 -0
- data/lib/incline/log.rb +153 -0
- data/lib/incline/number_formats.rb +17 -0
- data/lib/incline/recaptcha.rb +346 -0
- data/lib/incline/user_manager.rb +212 -0
- data/lib/incline/validators/email_validator.rb +45 -0
- data/lib/incline/validators/ip_address_validator.rb +32 -0
- data/lib/incline/validators/recaptcha_validator.rb +37 -0
- data/lib/incline/validators/safe_name_validator.rb +31 -0
- data/lib/incline/version.rb +3 -0
- data/lib/incline/work_path.rb +75 -0
- data/lib/incline.rb +197 -0
- data/lib/tasks/incline_tasks.rake +4 -0
- data/lib/templates/erb/scaffold/_form.html.erb +43 -0
- data/lib/templates/erb/scaffold/_list.html.erb +81 -0
- data/lib/templates/erb/scaffold/edit.html.erb +1 -0
- data/lib/templates/erb/scaffold/index.html.erb +6 -0
- data/lib/templates/erb/scaffold/new.html.erb +1 -0
- data/lib/templates/erb/scaffold/show.html.erb +34 -0
- data/lib/templates/jbuilder/scaffold/_details.json.jbuilder +20 -0
- data/lib/templates/jbuilder/scaffold/index.json.jbuilder +16 -0
- data/lib/templates/jbuilder/scaffold/show.json.jbuilder +16 -0
- data/lib/templates/rails/scaffold_controller/controller.rb +128 -0
- data/test/controllers/incline/access_groups_controller_test.rb +65 -0
- data/test/controllers/incline/access_test_controller_test.rb +53 -0
- data/test/controllers/incline/contact_controller_test.rb +32 -0
- data/test/controllers/incline/security_controller_test.rb +39 -0
- data/test/controllers/incline/welcome_controller_test.rb +16 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +12 -0
- data/test/dummy/app/assets/stylesheets/application.css +17 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.keep +0 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +1 -0
- data/test/dummy/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
- data/test/dummy/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +2 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +2 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config/application.rb +38 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +34 -0
- data/test/dummy/config/email.yml +24 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +45 -0
- data/test/dummy/config/environments/production.rb +85 -0
- data/test/dummy/config/environments/test.rb +44 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +6 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/schema.rb +108 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/extensions/action_controller_base_extensions_test.rb +21 -0
- data/test/extensions/action_mailer_base_extensions_test.rb +20 -0
- data/test/extensions/action_view_base_extensions_test.rb +267 -0
- data/test/extensions/active_record_extensions_test.rb +173 -0
- data/test/extensions/application_configuration_extensions_test.rb +46 -0
- data/test/extensions/application_extensions_test.rb +23 -0
- data/test/extensions/connection_adapter_extensions_test.rb +54 -0
- data/test/extensions/date_time_value_extensions_test.rb +104 -0
- data/test/extensions/date_value_extensions_test.rb +102 -0
- data/test/extensions/decimal_value_extensions_test.rb +85 -0
- data/test/extensions/erb_scaffold_generator_extensions_test.rb +17 -0
- data/test/extensions/float_value_extensions_test.rb +78 -0
- data/test/extensions/form_builder_extensions_test.rb +28 -0
- data/test/extensions/integer_value_extensions_test.rb +78 -0
- data/test/extensions/jbuilder_generator_extensions_test.rb +21 -0
- data/test/extensions/jbuilder_template_extensions_test.rb +47 -0
- data/test/extensions/main_app_extensions_test.rb +55 -0
- data/test/extensions/numeric_extensions_test.rb +76 -0
- data/test/extensions/object_extensions_test.rb +104 -0
- data/test/extensions/session_extensions_test.rb +69 -0
- data/test/extensions/string_extensions_test.rb +32 -0
- data/test/extensions/test_case_extensions_test.rb +538 -0
- data/test/extensions/time_zone_converter_extensions_test.rb +10 -0
- data/test/fixtures/incline/access_group_group_members.yml +1 -0
- data/test/fixtures/incline/access_group_user_members.yml +1 -0
- data/test/fixtures/incline/access_groups.yml +13 -0
- data/test/fixtures/incline/action_groups.yml +6 -0
- data/test/fixtures/incline/action_securities.yml +18 -0
- data/test/fixtures/incline/user_login_histories.yml +1 -0
- data/test/fixtures/incline/users.yml +64 -0
- data/test/incline_test.rb +63 -0
- data/test/integration/incline/users_edit_test.rb +180 -0
- data/test/integration/incline/users_login_test.rb +105 -0
- data/test/integration/incline/users_signup_test.rb +147 -0
- data/test/integration/navigation_test.rb +11 -0
- data/test/lib/data_tables_request_test.rb +245 -0
- data/test/lib/date_time_formats_test.rb +111 -0
- data/test/lib/global_status_test.rb +89 -0
- data/test/lib/json_log_formatter_test.rb +43 -0
- data/test/lib/log_test.rb +36 -0
- data/test/lib/recaptcha_test.rb +75 -0
- data/test/lib/user_manager_test.rb +47 -0
- data/test/lib/work_path_test.rb +18 -0
- data/test/models/incline/access_group_group_member_test.rb +30 -0
- data/test/models/incline/access_group_test.rb +60 -0
- data/test/models/incline/access_group_user_member_test.rb +29 -0
- data/test/models/incline/action_group_test.rb +27 -0
- data/test/models/incline/action_security_test.rb +176 -0
- data/test/models/incline/contact_message_test.rb +66 -0
- data/test/models/incline/disable_info_test.rb +29 -0
- data/test/models/incline/password_reset_request_test.rb +35 -0
- data/test/models/incline/password_reset_test.rb +51 -0
- data/test/models/incline/user_login_history_test.rb +31 -0
- data/test/models/incline/user_test.rb +91 -0
- data/test/test_helper.rb +42 -0
- data/test/validators/email_validator_test.rb +102 -0
- data/test/validators/ip_address_validator_test.rb +107 -0
- data/test/validators/recaptcha_validator_test.rb +57 -0
- data/test/validators/safe_name_validator_test.rb +101 -0
- metadata +584 -0
@@ -0,0 +1,764 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module Incline::Extensions
|
4
|
+
##
|
5
|
+
# Adds some extra assertions and methods for use in tests.
|
6
|
+
module TestCase
|
7
|
+
##
|
8
|
+
# Adds the #access_tests_for method.
|
9
|
+
module ClassMethods
|
10
|
+
##
|
11
|
+
# This method will generate multiple generic access tests for your controller.
|
12
|
+
#
|
13
|
+
# The +action+ argument can be one or more actions to test. These can be specified as arguments or an array.
|
14
|
+
# access_tests_for :new, :edit, :show
|
15
|
+
# access_tests_for [ :new, :edit, :show ]
|
16
|
+
#
|
17
|
+
# Options are provided after the last action to test. All options will be applied to all actions.
|
18
|
+
# The {action}_params option being the only one that is explicitly for a specific action.
|
19
|
+
#
|
20
|
+
# Valid options:
|
21
|
+
# controller::
|
22
|
+
# The name of the controller. If not supplied, the controller is inferred from the class name.
|
23
|
+
# url_helper::
|
24
|
+
# The code used to generate the URL. If not supplied, the helper is inferred from the controller and action name.
|
25
|
+
# fixture_helper::
|
26
|
+
# A string defining the fixture helper to use. If not supplied the pluralized controller name will be used.
|
27
|
+
# fixture_key::
|
28
|
+
# The key to use to load a fixture. The default is :one.
|
29
|
+
# allow_anon::
|
30
|
+
# Determines if anonymous users should be able to access the action. The default is false.
|
31
|
+
# allow_any_user::
|
32
|
+
# Determines if any authenticated user should be able to access the action. The default is false.
|
33
|
+
# allow_groups::
|
34
|
+
# Specifies a list of groups that should be able to access the action. The default is nil.
|
35
|
+
# deny_groups::
|
36
|
+
# Specifies a list of groups that should not be able to access the action. The default is nil.
|
37
|
+
# allow_admin::
|
38
|
+
# Specifies if a system admin should be able to access the action. The default is true.
|
39
|
+
# method::
|
40
|
+
# Specifies the method to process the action with. The default is 'get'.
|
41
|
+
# success::
|
42
|
+
# Determines the result on success. Defauls to :success for 'get' requests, otherwise the pluralized controller helper path.
|
43
|
+
# failure::
|
44
|
+
# Determines the result on failure for non-anon tests. Defaults to 'main_app.root_path'.
|
45
|
+
# anon_failure::
|
46
|
+
# Determines the result on failure for anon tests. Defaults to 'incline.login_path'.
|
47
|
+
# {action}_params::
|
48
|
+
# You can pass params to the action by specifying a hash containing them in this fashion.
|
49
|
+
# e.g. - :new_params => { } # params for :new action
|
50
|
+
# return_code::
|
51
|
+
# If this is set to a true value, the test code is generated, but not executed. The test code will then
|
52
|
+
# be returned as a string.
|
53
|
+
# If this is not to a true value, the test code will be executed as generated and nil will be returned.
|
54
|
+
#
|
55
|
+
# access_tests_for :new, controller: 'users', allow_anon: true, allow_any_user: false, allow_admin: false
|
56
|
+
#
|
57
|
+
def access_tests_for(*actions)
|
58
|
+
|
59
|
+
options = actions.delete(actions.last) if actions.last.is_a?(::Hash)
|
60
|
+
options ||= { }
|
61
|
+
|
62
|
+
if actions.count == 1 && actions.first.is_a?(::Array)
|
63
|
+
actions = actions.first
|
64
|
+
end
|
65
|
+
|
66
|
+
if actions.count > 1
|
67
|
+
data = actions.map{|act| access_tests_for(act, options.dup)}
|
68
|
+
if options[:return_code]
|
69
|
+
return data.join
|
70
|
+
else
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
action = actions.first
|
76
|
+
|
77
|
+
options = {
|
78
|
+
allow_anon: false,
|
79
|
+
allow_any_user: false,
|
80
|
+
allow_groups: nil,
|
81
|
+
deny_groups: nil,
|
82
|
+
allow_admin: true,
|
83
|
+
fixture_key: :one,
|
84
|
+
failure: 'main_app.root_path',
|
85
|
+
anon_failure: 'incline.login_path'
|
86
|
+
}.merge((options || {}).symbolize_keys)
|
87
|
+
|
88
|
+
action = action.to_sym
|
89
|
+
params = options[:"#{action}_params"]
|
90
|
+
params = params.inspect if params.is_a?(::Hash)
|
91
|
+
params = nil unless params.is_a?(::String)
|
92
|
+
|
93
|
+
# guess at the method to use.
|
94
|
+
if options[:method].blank?
|
95
|
+
options[:method] =
|
96
|
+
if action == :destroy
|
97
|
+
'delete'
|
98
|
+
elsif action == :update
|
99
|
+
'patch'
|
100
|
+
elsif action == :create
|
101
|
+
'post'
|
102
|
+
else
|
103
|
+
'get'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
options[:method] = options[:method].to_sym
|
107
|
+
|
108
|
+
if options[:controller].blank?
|
109
|
+
# only works with controller tests (eg - UsersControllerTest => users_controller_test => users_controller)
|
110
|
+
options[:controller] = self.name.underscore.rpartition('_')[0]
|
111
|
+
else
|
112
|
+
options[:controller] = options[:controller].to_s.underscore
|
113
|
+
end
|
114
|
+
|
115
|
+
if options[:controller] =~ /_controller$/
|
116
|
+
options[:controller] = options[:controller].rpartition('_')[0]
|
117
|
+
end
|
118
|
+
|
119
|
+
if options[:fixture_helper].blank?
|
120
|
+
options[:fixture_helper] = options[:controller].pluralize
|
121
|
+
end
|
122
|
+
|
123
|
+
if options[:url_helper].blank?
|
124
|
+
fix_val = "#{options[:fixture_helper]}(#{options[:fixture_key].inspect})"
|
125
|
+
options[:url_helper] =
|
126
|
+
case action
|
127
|
+
when :show, :update, :destroy then "#{options[:controller].singularize}_path(#{fix_val})"
|
128
|
+
when :edit then "edit_#{options[:controller].singularize}_path(#{fix_val})"
|
129
|
+
when :new then "new_#{options[:controller].singularize}_path"
|
130
|
+
else "#{options[:controller].pluralize}_path"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if options[:success].blank?
|
135
|
+
if options[:method] == :get
|
136
|
+
options[:success] = :success
|
137
|
+
else
|
138
|
+
options[:success] = "#{options[:controller].pluralize}_path"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
method = options[:method]
|
144
|
+
url_helper = options[:url_helper]
|
145
|
+
|
146
|
+
tests = [
|
147
|
+
# label result user group success_override failure_override
|
148
|
+
[ 'anonymous', options[:allow_anon], nil, nil, nil, options[:anon_failure] ],
|
149
|
+
[ 'any user', options[:allow_any_user], :basic ],
|
150
|
+
[ 'admin user', options[:allow_admin], :admin ]
|
151
|
+
]
|
152
|
+
|
153
|
+
unless options[:allow_groups].blank?
|
154
|
+
if options[:allow_groups].is_a?(::String)
|
155
|
+
options[:allow_groups] = options[:allow_groups].gsub(',', ';').split(';').map{|v| v.strip}
|
156
|
+
end
|
157
|
+
options[:allow_groups].each do |group|
|
158
|
+
tests << [ "#{group} member", true, :basic, group ]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
unless options[:deny_groups].blank?
|
163
|
+
if options[:deny_groups].is_a?(::String)
|
164
|
+
options[:deny_groups] = options[:deny_groups].gsub(',', ';').split(';').map{|v| v.strip}
|
165
|
+
end
|
166
|
+
options[:deny_groups].each do |group|
|
167
|
+
tests << [ "#{group} member", false, :basic, group ]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
all_code = ''
|
172
|
+
|
173
|
+
tests.each do |(label, result, user, group, success_override, failure_override)|
|
174
|
+
expected_result = result ? (success_override || options[:success]) : (failure_override || options[:failure])
|
175
|
+
|
176
|
+
# build the code block
|
177
|
+
test_code = "test \"should #{result ? '' : 'not '}allow access to #{action} for #{label}\" do\n"
|
178
|
+
|
179
|
+
if user
|
180
|
+
test_code += " user = incline_users(#{user.inspect})\n"
|
181
|
+
if group
|
182
|
+
test_code += " group = Incline::AccessGroup.find_or_create_by(name: #{group.inspect})\n"
|
183
|
+
test_code += " user.groups << group\n"
|
184
|
+
end
|
185
|
+
test_code += " log_in_as user\n"
|
186
|
+
end
|
187
|
+
|
188
|
+
test_code += " path = #{url_helper}\n"
|
189
|
+
|
190
|
+
if params.blank?
|
191
|
+
test_code += " #{method}(path)\n"
|
192
|
+
else
|
193
|
+
test_code += " #{method}(path, #{params})\n"
|
194
|
+
end
|
195
|
+
|
196
|
+
if expected_result.is_a?(::Symbol)
|
197
|
+
test_code += " assert_response #{expected_result.inspect}\n"
|
198
|
+
else
|
199
|
+
test_code += " assert_redirected_to #{expected_result}\n"
|
200
|
+
end
|
201
|
+
|
202
|
+
test_code += "end\n"
|
203
|
+
|
204
|
+
all_code += test_code
|
205
|
+
|
206
|
+
unless options[:return_code]
|
207
|
+
Incline::Log::debug test_code
|
208
|
+
eval test_code
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
options[:return_code] ? all_code : nil
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
##
|
219
|
+
# Make sure main_app is available and working correctly.
|
220
|
+
def main_app
|
221
|
+
Rails.application.class.routes.url_helpers
|
222
|
+
end
|
223
|
+
|
224
|
+
##
|
225
|
+
# Determines if a user is logged into the test session
|
226
|
+
def is_logged_in?
|
227
|
+
!session[:user_id].nil?
|
228
|
+
end
|
229
|
+
|
230
|
+
##
|
231
|
+
# Logs in a test user
|
232
|
+
def log_in_as(user, options = {})
|
233
|
+
password = options[:password] || 'Password123'
|
234
|
+
remember_me = options[:remember_me] || '1'
|
235
|
+
if integration_test?
|
236
|
+
post incline.login_path, session: { email: user.email, password: password, remember_me: remember_me }
|
237
|
+
else
|
238
|
+
session[:user_id] = user.id
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
|
243
|
+
##
|
244
|
+
# Tests a specific field for presence validation.
|
245
|
+
#
|
246
|
+
# model::
|
247
|
+
# This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
|
248
|
+
#
|
249
|
+
# attribute::
|
250
|
+
# This must provide the name of a valid attribute in the model.
|
251
|
+
#
|
252
|
+
# message::
|
253
|
+
# This is optional, but if provided it will be postfixed with the failure reason.
|
254
|
+
#
|
255
|
+
# regex::
|
256
|
+
# This is the regex to match against the error message to ensure that the failure is for the correct reason.
|
257
|
+
#
|
258
|
+
def assert_required(model, attribute, message = nil, regex = /can't be blank/i)
|
259
|
+
original_value = model.send(attribute)
|
260
|
+
assert model.valid?, 'Model should be valid to start.'
|
261
|
+
is_string = original_value.is_a?(::String)
|
262
|
+
setter = :"#{attribute}="
|
263
|
+
model.send setter, nil
|
264
|
+
assert_not model.valid?, message ? (message + ': (nil)') : "Should not allow #{attribute} to be set to nil."
|
265
|
+
assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
266
|
+
if is_string
|
267
|
+
model.send setter, ''
|
268
|
+
assert_not model.valid?, message ? (message + ": ('')") : "Should not allow #{attribute} to be set to empty string."
|
269
|
+
assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
270
|
+
model.send setter, ' '
|
271
|
+
assert_not model.valid?, message ? (message + ": (' ')") : "Should not allow #{attribute} to be set to blank string."
|
272
|
+
assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
273
|
+
end
|
274
|
+
model.send setter, original_value
|
275
|
+
assert model.valid?, message ? (message + ": !(#{original_value.inspect})") : "Should allow #{attribute} to be set back to '#{original_value.inspect}'."
|
276
|
+
end
|
277
|
+
|
278
|
+
##
|
279
|
+
# Tests a specific field for maximum length restriction.
|
280
|
+
#
|
281
|
+
# model::
|
282
|
+
# This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
|
283
|
+
#
|
284
|
+
# attribute::
|
285
|
+
# This must provide the name of a valid attribute in the model.
|
286
|
+
#
|
287
|
+
# max_length::
|
288
|
+
# This is the maximum valid length for the field.
|
289
|
+
#
|
290
|
+
# message::
|
291
|
+
# This is optional, but if provided it will be postfixed with the failure reason.
|
292
|
+
#
|
293
|
+
# regex::
|
294
|
+
# This is the regex to match against the error message to ensure that the failure is for the correct reason.
|
295
|
+
#
|
296
|
+
# options::
|
297
|
+
# This is a list of options for the validation.
|
298
|
+
# Currently :start_with and :end_with are recognized.
|
299
|
+
# Use :start_with to specify a prefix for the tested string.
|
300
|
+
# Use :end_with to specify a postfix for the tested string.
|
301
|
+
# This would be most useful when you value has to follow a format (eg - email address :end_with => '@example.com')
|
302
|
+
#
|
303
|
+
def assert_max_length(model, attribute, max_length, message = nil, regex = /is too long/i, options = {})
|
304
|
+
original_value = model.send(attribute)
|
305
|
+
assert model.valid?, 'Model should be valid to start.'
|
306
|
+
setter = :"#{attribute}="
|
307
|
+
|
308
|
+
if message.is_a?(::Hash)
|
309
|
+
options = message.merge(options || {})
|
310
|
+
message = nil
|
311
|
+
end
|
312
|
+
|
313
|
+
if regex.is_a?(::Hash)
|
314
|
+
options = regex.merge(options || {})
|
315
|
+
regex = /is too long/i
|
316
|
+
end
|
317
|
+
|
318
|
+
pre = options[:start_with].to_s
|
319
|
+
post = options[:end_with].to_s
|
320
|
+
len = max_length - pre.length - post.length
|
321
|
+
|
322
|
+
# try with maximum valid length.
|
323
|
+
value = pre + ('a' * len) + post
|
324
|
+
model.send setter, value
|
325
|
+
assert model.valid?, message ? (message + ": !(#{value.length})") : "Should allow a string of #{value.length} characters."
|
326
|
+
|
327
|
+
# try with one extra character.
|
328
|
+
value = pre + ('a' * (len + 1)) + post
|
329
|
+
model.send setter, value
|
330
|
+
assert_not model.valid?, message ? (message + ": (#{value.length})") : "Should not allow a string of #{value.length} characters."
|
331
|
+
assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
332
|
+
|
333
|
+
model.send setter, original_value
|
334
|
+
assert model.valid?, message ? (message + ": !(#{original_value.inspect})") : "Should allow #{attribute} to be set back to '#{original_value.inspect}'."
|
335
|
+
end
|
336
|
+
|
337
|
+
##
|
338
|
+
# Tests a specific field for maximum length restriction.
|
339
|
+
#
|
340
|
+
# model::
|
341
|
+
# This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
|
342
|
+
#
|
343
|
+
# attribute::
|
344
|
+
# This must provide the name of a valid attribute in the model.
|
345
|
+
#
|
346
|
+
# min_length::
|
347
|
+
# This is the minimum valid length for the field.
|
348
|
+
#
|
349
|
+
# message::
|
350
|
+
# This is optional, but if provided it will be postfixed with the failure reason.
|
351
|
+
#
|
352
|
+
# regex::
|
353
|
+
# This is the regex to match against the error message to ensure that the failure is for the correct reason.
|
354
|
+
#
|
355
|
+
# options::
|
356
|
+
# This is a list of options for the validation.
|
357
|
+
# Currently :start_with and :end_with are recognized.
|
358
|
+
# Use :start_with to specify a prefix for the tested string.
|
359
|
+
# Use :end_with to specify a postfix for the tested string.
|
360
|
+
# This would be most useful when you value has to follow a format (eg - email address :end_with => '@example.com')
|
361
|
+
#
|
362
|
+
def assert_min_length(model, attribute, min_length, message = nil, regex = /is too short/i, options = {})
|
363
|
+
original_value = model.send(attribute)
|
364
|
+
assert model.valid?, 'Model should be valid to start.'
|
365
|
+
setter = :"#{attribute}="
|
366
|
+
|
367
|
+
if message.is_a?(::Hash)
|
368
|
+
options = message.merge(options || {})
|
369
|
+
message = nil
|
370
|
+
end
|
371
|
+
|
372
|
+
if regex.is_a?(::Hash)
|
373
|
+
options = regex.merge(options || {})
|
374
|
+
regex = /is too short/i
|
375
|
+
end
|
376
|
+
|
377
|
+
pre = options[:start_with].to_s
|
378
|
+
post = options[:end_with].to_s
|
379
|
+
len = min_length - pre.length - post.length
|
380
|
+
|
381
|
+
# try with minimum valid length.
|
382
|
+
value = pre + ('a' * len) + post
|
383
|
+
model.send setter, value
|
384
|
+
assert model.valid?, message ? (message + ": !(#{value.length})") : "Should allow a string of #{value.length} characters."
|
385
|
+
|
386
|
+
# try with one extra character.
|
387
|
+
value = pre + ('a' * (len - 1)) + post
|
388
|
+
model.send setter, value
|
389
|
+
assert_not model.valid?, message ? (message + ": (#{value.length})") : "Should not allow a string of #{value.length} characters."
|
390
|
+
assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
391
|
+
|
392
|
+
model.send setter, original_value
|
393
|
+
assert model.valid?, message ? (message + ": !(#{original_value.inspect})") : "Should allow #{attribute} to be set back to '#{original_value.inspect}'."
|
394
|
+
end
|
395
|
+
|
396
|
+
##
|
397
|
+
# Tests a specific field for uniqueness.
|
398
|
+
#
|
399
|
+
# model::
|
400
|
+
# This must respond to _attribute_ and _attribute=_ as well as _valid?_, _errors_, and _save!_.
|
401
|
+
# The model will be saved to perform uniqueness testing.
|
402
|
+
#
|
403
|
+
# attribute::
|
404
|
+
# This must provide the name of a valid attribute in the model.
|
405
|
+
#
|
406
|
+
# case_sensitive::
|
407
|
+
# This determines if changing case should change validation.
|
408
|
+
#
|
409
|
+
# message::
|
410
|
+
# This is optional, but if provided it will be postfixed with the failure reason.
|
411
|
+
#
|
412
|
+
# regex::
|
413
|
+
# This is the regex to match against the error message to ensure that the failure is for the correct reason.
|
414
|
+
#
|
415
|
+
#
|
416
|
+
# alternate_scopes::
|
417
|
+
# This is also optional. If provided the keys of the hash will be used to
|
418
|
+
# set additional attributes on the model. When these attributes are changed to the alternate
|
419
|
+
# values, the model should once again be valid.
|
420
|
+
# The alternative scopes are processed one at a time and the original values are restored
|
421
|
+
# before moving onto the next scope.
|
422
|
+
#
|
423
|
+
def assert_uniqueness(model, attribute, case_sensitive = false, message = nil, regex = /has already been taken/i, alternate_scopes = {})
|
424
|
+
setter = :"#{attribute}="
|
425
|
+
original_value = model.send(attribute)
|
426
|
+
|
427
|
+
assert model.valid?, 'Model should be valid to start.'
|
428
|
+
|
429
|
+
if case_sensitive.is_a?(::Hash)
|
430
|
+
alternate_scopes = case_sensitive.merge(alternate_scopes || {})
|
431
|
+
case_sensitive = false
|
432
|
+
end
|
433
|
+
if message.is_a?(::Hash)
|
434
|
+
alternate_scopes = message.merge(alternate_scopes || {})
|
435
|
+
message = nil
|
436
|
+
end
|
437
|
+
if regex.is_a?(::Hash)
|
438
|
+
alternate_scopes = regex.merge(alternate_scopes || {})
|
439
|
+
regex = /has already been taken/i
|
440
|
+
end
|
441
|
+
|
442
|
+
model.save!
|
443
|
+
copy = model.dup
|
444
|
+
|
445
|
+
assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid."
|
446
|
+
assert copy.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : "Did not fail for expected reason"
|
447
|
+
if original_value.is_a?(::String)
|
448
|
+
unless case_sensitive
|
449
|
+
copy.send(setter, original_value.upcase)
|
450
|
+
assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid."
|
451
|
+
assert copy.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : "Did not fail for expected reason"
|
452
|
+
copy.send(setter, original_value.downcase)
|
453
|
+
assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid."
|
454
|
+
assert copy.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : "Did not fail for expected reason"
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
unless alternate_scopes.blank?
|
459
|
+
copy.send(setter, original_value)
|
460
|
+
assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid."
|
461
|
+
assert copy.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : "Did not fail for expected reason"
|
462
|
+
alternate_scopes.each do |k,v|
|
463
|
+
kset = :"#{k}="
|
464
|
+
vorig = copy.send(k)
|
465
|
+
copy.send(kset, v)
|
466
|
+
assert copy.valid?, message ? (message + ": !#{k}(#{v})") : "Duplicate model with #{k}=#{v.inspect} should be valid with #{attribute}=#{copy.send(attribute).inspect}."
|
467
|
+
copy.send(kset, vorig)
|
468
|
+
assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid."
|
469
|
+
assert copy.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : "Did not fail for expected reason"
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
##
|
475
|
+
# Tests a specific field for reCAPTCHA validation.
|
476
|
+
#
|
477
|
+
# During testing reCAPTCHA is disabled, but there is a special response that is expected.
|
478
|
+
#
|
479
|
+
# model::
|
480
|
+
# This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
|
481
|
+
#
|
482
|
+
# attribute::
|
483
|
+
# This must provide the name of a valid attribute in the model.
|
484
|
+
#
|
485
|
+
# message::
|
486
|
+
# This is optional, but if provided it will be postfixed with the failure reason.
|
487
|
+
#
|
488
|
+
# regex::
|
489
|
+
# This is the regex to match against the error message to ensure that the failure is for the correct reason.
|
490
|
+
# The default value of nil uses two regular expressions to match the two failure cases.
|
491
|
+
#
|
492
|
+
def assert_recaptcha_validation(model, attribute, message = nil, regex = nil)
|
493
|
+
assert model.valid?, 'Model should be valid to start.'
|
494
|
+
setter = :"#{attribute}="
|
495
|
+
|
496
|
+
# no response, just an ip address.
|
497
|
+
model.send setter, '127.0.0.1'
|
498
|
+
assert_not model.valid?, message ? (message + ': (accepted without response)') : 'Should not have accepted without response.'
|
499
|
+
r = regex || /requires recaptcha challenge to be completed/i
|
500
|
+
assert model.errors[:base].to_s =~ r, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
501
|
+
|
502
|
+
@item.recaptcha = '127.0.0.1|invalid'
|
503
|
+
assert_not @item.valid?, message ? (message + ': (accepted invalid response)') : 'Should not have accepted invalid response.'
|
504
|
+
r = regex || /invalid response from recaptcha challenge/i
|
505
|
+
assert model.errors[:base].to_s =~ r, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
506
|
+
|
507
|
+
# since recaptcha is disabled for testing, the following string should validate.
|
508
|
+
@item.recaptcha = '127.0.0.1|disabled'
|
509
|
+
assert @item.valid?, message ? (message + ': (rejected valid response)') : 'Should have accepted valid response.'
|
510
|
+
end
|
511
|
+
|
512
|
+
##
|
513
|
+
# Tests a specific field for email verification.
|
514
|
+
#
|
515
|
+
# model::
|
516
|
+
# This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
|
517
|
+
#
|
518
|
+
# attribute::
|
519
|
+
# This must provide the name of a valid attribute in the model.
|
520
|
+
#
|
521
|
+
# message::
|
522
|
+
# This is optional, but if provided it will be postfixed with the failure reason.
|
523
|
+
#
|
524
|
+
# regex::
|
525
|
+
# This is the regex to match against the error message to ensure that the failure is for the correct reason.
|
526
|
+
#
|
527
|
+
def assert_email_validation(model, attribute, message = nil, regex = /is not a valid email address/i)
|
528
|
+
assert model.valid?, 'Model should be valid to start.'
|
529
|
+
setter = :"#{attribute}="
|
530
|
+
orig = model.send attribute
|
531
|
+
|
532
|
+
valid = %w(
|
533
|
+
user@example.com
|
534
|
+
USER@foo.COM
|
535
|
+
A_US-ER@foo.bar.org
|
536
|
+
first.last@foo.jp
|
537
|
+
alice+bob@bax.cn
|
538
|
+
)
|
539
|
+
|
540
|
+
invalid = %w(
|
541
|
+
user@example,com
|
542
|
+
user_at_foo.org
|
543
|
+
user@example.
|
544
|
+
user@example.com.
|
545
|
+
foo@bar_baz.com
|
546
|
+
foo@bar+baz.com
|
547
|
+
@example.com
|
548
|
+
user@
|
549
|
+
user
|
550
|
+
user@..com
|
551
|
+
user@example..com
|
552
|
+
user@.example.com
|
553
|
+
user@@example.com
|
554
|
+
user@www@example.com
|
555
|
+
)
|
556
|
+
|
557
|
+
valid.each do |addr|
|
558
|
+
model.send setter, addr
|
559
|
+
assert model.valid?, message ? (message + ': (rejected valid address)') : "Should have accepted #{addr.inspect}."
|
560
|
+
end
|
561
|
+
|
562
|
+
invalid.each do |addr|
|
563
|
+
model.send setter, addr
|
564
|
+
assert_not model.valid?, message ? (message + ': (accepted invalid address)') : "Should have rejected #{addr.inspect}."
|
565
|
+
assert model.errors[attribute].to_s =~ regex, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
566
|
+
end
|
567
|
+
|
568
|
+
model.send setter, orig
|
569
|
+
assert model.valid?, message ? (message + ': (rejected original value)') : "Should have accepted original value of #{orig.inspect}."
|
570
|
+
|
571
|
+
end
|
572
|
+
|
573
|
+
|
574
|
+
##
|
575
|
+
# Tests a specific field for IP address verification.
|
576
|
+
#
|
577
|
+
# model::
|
578
|
+
# This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
|
579
|
+
#
|
580
|
+
# attribute::
|
581
|
+
# This must provide the name of a valid attribute in the model.
|
582
|
+
#
|
583
|
+
# mask::
|
584
|
+
# This can be one of :allow_mask, :require_mask, or :deny_mask. The default is :allow_mask.
|
585
|
+
#
|
586
|
+
# message::
|
587
|
+
# This is optional, but if provided it will be postfixed with the failure reason.
|
588
|
+
#
|
589
|
+
# regex::
|
590
|
+
# This is the regex to match against the error message to ensure that the failure is for the correct reason.
|
591
|
+
# The default value is nil to test for the various default messages.
|
592
|
+
#
|
593
|
+
def assert_ip_validation(model, attribute, mask = :allow_mask, message = nil, regex = nil)
|
594
|
+
assert model.valid?, 'Model should be valid to start.'
|
595
|
+
setter = :"#{attribute}="
|
596
|
+
orig = model.send attribute
|
597
|
+
|
598
|
+
valid = %w(
|
599
|
+
0.0.0.0
|
600
|
+
1.2.3.4
|
601
|
+
10.20.30.40
|
602
|
+
255.255.255.255
|
603
|
+
10:20::30:40
|
604
|
+
::1
|
605
|
+
1:2:3:4:5:6:7:8
|
606
|
+
A:B:C:D:E:F::
|
607
|
+
)
|
608
|
+
|
609
|
+
invalid = %w(
|
610
|
+
localhost
|
611
|
+
100.200.300.400
|
612
|
+
12345::abcde
|
613
|
+
1.2.3.4.5
|
614
|
+
1.2.3
|
615
|
+
0
|
616
|
+
1:2:3:4:5:6:7:8:9:0
|
617
|
+
a:b:c:d:e:f:g:h
|
618
|
+
)
|
619
|
+
|
620
|
+
valid.each do |addr|
|
621
|
+
if mask == :require_mask
|
622
|
+
if addr.index(':')
|
623
|
+
addr += '/128'
|
624
|
+
else
|
625
|
+
addr += '/32'
|
626
|
+
end
|
627
|
+
end
|
628
|
+
model.send setter, addr
|
629
|
+
assert model.valid?, message ? (message + ': (rejected valid address)') : "Should have accepted #{addr.inspect}."
|
630
|
+
end
|
631
|
+
|
632
|
+
r = regex ? regex : /is not a valid ip address/i
|
633
|
+
invalid.each do |addr|
|
634
|
+
if mask == :require_mask
|
635
|
+
if addr.index(':')
|
636
|
+
addr += '/128'
|
637
|
+
else
|
638
|
+
addr += '/32'
|
639
|
+
end
|
640
|
+
end
|
641
|
+
model.send setter, addr
|
642
|
+
assert_not model.valid?, message ? (message + ': (accepted invalid address)') : "Should have rejected #{addr.inspect}."
|
643
|
+
assert model.errors[attribute].to_s =~ r, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
644
|
+
end
|
645
|
+
|
646
|
+
if mask == :allow_mask || mask == :require_mask
|
647
|
+
address = '127.0.0.0/8'
|
648
|
+
model.send setter, address
|
649
|
+
assert model.valid?, message ? (message + ': (rejected masked address)') : "Should have accepted #{address.inspect}."
|
650
|
+
end
|
651
|
+
|
652
|
+
if mask == :allow_mask || mask == :deny_mask
|
653
|
+
address = '127.0.0.1'
|
654
|
+
model.send setter, address
|
655
|
+
assert model.valid?, message ? (message + ': (rejected unmasked address)') : "Should have accepted #{address.inspect}."
|
656
|
+
end
|
657
|
+
|
658
|
+
if mask == :require_mask
|
659
|
+
r = regex ? regex : /must contain a mask/i
|
660
|
+
address = '127.0.0.1'
|
661
|
+
model.send setter, address
|
662
|
+
assert_not model.valid?, message ? (message + ': (accepted unmasked address)') : "Should have rejected #{address.inspect} for no mask."
|
663
|
+
assert model.errors[attribute].to_s =~ r, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
664
|
+
end
|
665
|
+
|
666
|
+
if mask == :deny_mask
|
667
|
+
r = regex ? regex : /must not contain a mask/i
|
668
|
+
address = '127.0.0.0/8'
|
669
|
+
model.send setter, address
|
670
|
+
assert_not model.valid? message ? (message + ': (accepted masked address)') : "Should have rejected #{address.inspect} for mask."
|
671
|
+
assert model.errors[attribute].to_s =~ r, message ? (message + ': (error message)') : 'Did not fail for expected reason.'
|
672
|
+
end
|
673
|
+
|
674
|
+
model.send setter, orig
|
675
|
+
assert model.valid?, message ? (message + ': (rejected original value)') : "Should have accepted original value of #{orig.inspect}."
|
676
|
+
end
|
677
|
+
|
678
|
+
##
|
679
|
+
# Tests a specific field for safe name verification.
|
680
|
+
#
|
681
|
+
# model::
|
682
|
+
# This must respond to _attribute_ and _attribute=_ as well as _valid?_ and _errors_.
|
683
|
+
#
|
684
|
+
# attribute::
|
685
|
+
# This must provide the name of a valid attribute in the model.
|
686
|
+
#
|
687
|
+
# length::
|
688
|
+
# The length of the string to test. Must be greater than 2. Default is 6.
|
689
|
+
#
|
690
|
+
# message::
|
691
|
+
# This is optional, but if provided it will be postfixed with the failure reason.
|
692
|
+
#
|
693
|
+
# regex::
|
694
|
+
# This is the regex to match against the error message to ensure that the failure is for the correct reason.
|
695
|
+
# The default value is nil to test for the various default messages.
|
696
|
+
#
|
697
|
+
def assert_safe_name_validation(model, attribute, length = 6, message = nil, regex = nil)
|
698
|
+
assert model.valid?, 'Model should be valid to start.'
|
699
|
+
setter = :"#{attribute}="
|
700
|
+
orig = model.send attribute
|
701
|
+
|
702
|
+
assert length > 2, message ? (message + ': (field is too short to test)') : 'Requires a field length greater than 2 to perform tests.'
|
703
|
+
|
704
|
+
# valid tests.
|
705
|
+
mid_length = length - 2
|
706
|
+
mid = '' # _z_z_z_z_z_
|
707
|
+
while mid.length < mid_length
|
708
|
+
if mid.length + 1 < mid_length
|
709
|
+
mid += '_z'
|
710
|
+
else
|
711
|
+
mid += '_'
|
712
|
+
end
|
713
|
+
end
|
714
|
+
|
715
|
+
[
|
716
|
+
'a' * length,
|
717
|
+
'a' + ('1' * (length - 1)),
|
718
|
+
'a' + mid + 'a',
|
719
|
+
'a' + mid + '1'
|
720
|
+
].each do |val|
|
721
|
+
model.send setter, val
|
722
|
+
assert model.valid?, message ? (message + ': (rejected valid string)') : "Should have accepted #{val.inspect}."
|
723
|
+
val.upcase!
|
724
|
+
model.send setter, val
|
725
|
+
assert model.valid?, message ? (message + ': (rejected valid string)') : "Should have accepted #{val.inspect}."
|
726
|
+
end
|
727
|
+
|
728
|
+
# invalid tests.
|
729
|
+
{
|
730
|
+
'_' + ('a' * (length - 1)) => /must start with a letter/i,
|
731
|
+
'1' + ('a' * (length - 1)) => /must start with a letter/i,
|
732
|
+
('a' * (length - 1)) + '_' => /must not end with an underscore/i,
|
733
|
+
('a' * (length - 2)) + '-' + 'a' => /must contain only letters, numbers, and underscore/i,
|
734
|
+
('a' * (length - 2)) + '#' + 'a' => /must contain only letters, numbers, and underscore/i,
|
735
|
+
('a' * (length - 2)) + ' ' + 'a' => /must contain only letters, numbers, and underscore/i
|
736
|
+
}.each do |val, reg|
|
737
|
+
r = regex ? regex : reg
|
738
|
+
model.send setter, val
|
739
|
+
assert_not model.valid?, message ? (message + ': (accepted invalid string)') : "Should have rejected #{val.inspect}."
|
740
|
+
assert model.errors[attribute].to_s =~ r, message ? (message + ': (error message)') : "Did not fail for expected reason on #{val.inspect}."
|
741
|
+
end
|
742
|
+
|
743
|
+
model.send setter, orig
|
744
|
+
assert model.valid?, message ? (message + ': (rejected original value)') : "Should have accepted original value of #{orig.inspect}."
|
745
|
+
end
|
746
|
+
|
747
|
+
##
|
748
|
+
# Includes the class methods into the including object.
|
749
|
+
def self.included(base)
|
750
|
+
base.extend ClassMethods
|
751
|
+
end
|
752
|
+
|
753
|
+
private
|
754
|
+
|
755
|
+
# returns true inside an integration test
|
756
|
+
def integration_test?
|
757
|
+
defined?(post_via_redirect)
|
758
|
+
end
|
759
|
+
|
760
|
+
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
ActiveSupport::TestCase.include Incline::Extensions::TestCase
|