shoulda_matchmakers 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +21 -0
- data/lib/controller/action_controller/action_controller_controller_sm_model.rb +53 -0
- data/lib/controller/action_controller/action_controller_controller_sm_model_helper.rb +73 -0
- data/lib/controller/action_controller/matchmakers/callbacks.rb +56 -0
- data/lib/controller/action_controller/matchmakers/filter_param.rb +69 -0
- data/lib/controller/action_controller/matchmakers/permit.rb +510 -0
- data/lib/controller/action_controller/matchmakers/redirect_to.rb +126 -0
- data/lib/controller/action_controller/matchmakers/render_template.rb +198 -0
- data/lib/controller/action_controller/matchmakers/render_with_layout.rb +72 -0
- data/lib/controller/action_controller/matchmakers/rescue_from.rb +96 -0
- data/lib/controller/action_controller/matchmakers/respond_with.rb +71 -0
- data/lib/controller/action_controller/matchmakers/route.rb +586 -0
- data/lib/controller/action_controller/matchmakers/set_flash.rb +136 -0
- data/lib/controller/action_controller/matchmakers/set_session.rb +115 -0
- data/lib/controller/action_controller/permitted_params_definition.rb +60 -0
- data/lib/generators/shoulda_matchmakers/controller_matcher_generator.rb +87 -0
- data/lib/generators/shoulda_matchmakers/controller_matcher_generator_helper.rb +92 -0
- data/lib/generators/shoulda_matchmakers/factory_generator.rb +86 -0
- data/lib/generators/shoulda_matchmakers/install_generator.rb +10 -0
- data/lib/generators/shoulda_matchmakers/model_matcher_generator.rb +87 -0
- data/lib/generators/shoulda_matchmakers/model_matcher_generator_helper.rb +107 -0
- data/lib/model/active_record/active_record_model_sm_model.rb +50 -0
- data/lib/model/active_record/active_record_model_sm_model_helper.rb +206 -0
- data/lib/model/active_record/factory_sm_model.rb +28 -0
- data/lib/model/active_record/factory_sm_model_helper.rb +124 -0
- data/lib/model/active_record/matchmakers/accept_nested_attributes_for.rb +66 -0
- data/lib/model/active_record/matchmakers/allow_value.rb +137 -0
- data/lib/model/active_record/matchmakers/associations.rb +52 -0
- data/lib/model/active_record/matchmakers/define_enum_for.rb +53 -0
- data/lib/model/active_record/matchmakers/delegate_method.rb +101 -0
- data/lib/model/active_record/matchmakers/have_db_column.rb +33 -0
- data/lib/model/active_record/matchmakers/have_db_index.rb +39 -0
- data/lib/model/active_record/matchmakers/have_readonly_attribute.rb +32 -0
- data/lib/model/active_record/matchmakers/have_secure_password.rb +32 -0
- data/lib/model/active_record/matchmakers/serialize.rb +67 -0
- data/lib/model/active_record/matchmakers/validations.rb +169 -0
- data/lib/model/active_record/options_definition.rb +160 -0
- data/lib/shoulda_matchmakers.rb +48 -0
- data/lib/shoulda_matchmakers/version.rb +3 -0
- data/lib/support/command_line_interface.rb +100 -0
- data/lib/support/controller_generator.rb +198 -0
- data/lib/support/indefinite_article.rb +70 -0
- data/lib/support/to_discard/belong_to.rb +94 -0
- data/lib/support/to_discard/have_and_belong_to_many.rb +83 -0
- data/lib/support/to_discard/have_many.rb +96 -0
- data/lib/support/to_discard/have_one.rb +98 -0
- data/lib/support/to_discard/permit_refactor.rb +270 -0
- data/lib/support/to_discard/render_template_new.rb +204 -0
- data/lib/support/to_discard/render_template_reconstruction.rb +188 -0
- data/lib/support/to_discard/use_around_action.rb +20 -0
- data/lib/support/to_discard/use_before_action.rb +20 -0
- data/lib/support/to_discard/validate_absence_of.rb +16 -0
- data/lib/support/to_discard/validate_acceptance_of.rb +16 -0
- data/lib/support/to_discard/validate_confirmation_of.rb +16 -0
- data/lib/support/to_discard/validate_exclusion_of.rb +145 -0
- data/lib/support/to_discard/validate_inclusion_of.rb +94 -0
- data/lib/support/to_discard/validate_length_of.rb +16 -0
- data/lib/support/to_discard/validate_numericality_of.rb +16 -0
- data/lib/support/to_discard/validate_presence_of.rb +16 -0
- data/lib/support/to_discard/validate_uniqueness_of.rb +16 -0
- data/lib/support/to_discard/validation_old.rb +37 -0
- data/lib/support/to_discard/validations.rb +41 -0
- data/lib/support/to_discard/validations_conditional.rb +146 -0
- data/lib/support/trace_debug_lines.txt +319 -0
- data/lib/support/util.rb +15 -0
- data/lib/templates/controller/action_controller/controller_spec_template.haml +146 -0
- data/lib/templates/factory/active_record/factory_template.haml +13 -0
- data/lib/templates/model/active_record/model_spec_template.haml +233 -0
- data/lib/templates/shoulda_matchmakers.rb +112 -0
- metadata +263 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module ActiveModelMatcher
|
5
|
+
module ValidateAcceptanceOf
|
6
|
+
|
7
|
+
def validate_acceptance_of_matcher_tests
|
8
|
+
acceptance_validators = extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::AcceptanceValidator).flatten
|
9
|
+
generate_validator_matcher_tests(acceptance_validators)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module ActiveModelMatcher
|
5
|
+
module ValidateConfirmationOf
|
6
|
+
|
7
|
+
def validate_confirmation_of_matcher_tests
|
8
|
+
confirmation_validators = extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::ConfirmationValidator).flatten
|
9
|
+
generate_validator_matcher_tests(confirmation_validators)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module Matchmaker
|
5
|
+
module ValidateExclusionOf
|
6
|
+
|
7
|
+
|
8
|
+
def validate_exclusion_of_matcher_tests
|
9
|
+
exclusion_validators = extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::ExclusionValidator).flatten
|
10
|
+
if exclusion_validators.present?
|
11
|
+
generate_exclusion_validator_matcher_tests(exclusion_validators)
|
12
|
+
else
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def generate_exclusion_validator_matcher_tests(exclusion_validators)
|
21
|
+
exclusion_tests = []
|
22
|
+
exclusion_validators.map do |exclusion_validator|
|
23
|
+
if conditional_options_exist(exclusion_validator.options)
|
24
|
+
exclusion_tests = exclusion_tests + generate_exclusion_conditional_tests(exclusion_validator)
|
25
|
+
else
|
26
|
+
exclusion_tests << generate_exclusion_test(exclusion_validator, exclusion_validator.options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
exclusion_tests = properly_line_space_tests(exclusion_tests)
|
30
|
+
exclusion_tests.flatten.compact.uniq.join("\n")
|
31
|
+
end
|
32
|
+
|
33
|
+
def generate_exclusion_test(exclusion_validator, exclusion_options)
|
34
|
+
exclusion_test = get_exclusion_test_core(exclusion_options, exclusion_validator.attributes[0])
|
35
|
+
exclusion_options_string = get_options_string(exclusion_options)
|
36
|
+
exclusion_options_string = exclusion_options_string.gsub(".", ".\n ")
|
37
|
+
exclusion_test.concat(exclusion_options_string + "\n end")
|
38
|
+
exclusion_test
|
39
|
+
end
|
40
|
+
|
41
|
+
def generate_exclusion_conditional_tests(exclusion_validator)
|
42
|
+
exclusion_conditional_tests = []
|
43
|
+
exclusion_options = parse_validator_options(exclusion_validator.options.dup)
|
44
|
+
if all_option_values_are_symbols(exclusion_options[:if_option_values]) &&
|
45
|
+
all_option_values_are_symbols(exclusion_options[:unless_option_values])
|
46
|
+
exclusion_conditional_tests << generate_exclusion_validating_test(exclusion_validator, exclusion_options[:non_conditional_options])
|
47
|
+
exclusion_conditional_tests = exclusion_conditional_tests + generate_exclusion_non_validating_tests(exclusion_validator, exclusion_options[:non_conditional_options])
|
48
|
+
# else
|
49
|
+
# Skip tests due to non-symbol conditions (see below)
|
50
|
+
end
|
51
|
+
exclusion_conditional_tests
|
52
|
+
end
|
53
|
+
|
54
|
+
def generate_exclusion_validating_test(exclusion_validator, exclusion_options)
|
55
|
+
exclusion_validating_test = compose_conditional_validating_context_string(exclusion_options)
|
56
|
+
validating_permutation = get_validating_true_false_permutation(exclusion_options)
|
57
|
+
exclusion_validating_test.concat(compose_conditional_before_strings(exclusion_options, validating_permutation))
|
58
|
+
validating_test = generate_exclusion_test(exclusion_validator, exclusion_options[:non_conditional_options])
|
59
|
+
validating_test = adjust_conditional_test_indentation(validating_test)
|
60
|
+
exclusion_validating_test.concat(validating_test + "\n end")
|
61
|
+
end
|
62
|
+
|
63
|
+
def generate_exclusion_non_validating_tests(exclusion_validator, exclusion_options)
|
64
|
+
exclusion_non_validating_tests = []
|
65
|
+
possible_conditional_permutations = get_possible_true_false_permutations(exclusion_options)
|
66
|
+
validating_permutation = get_validating_true_false_permutation(exclusion_options)
|
67
|
+
non_validating_permutations = possible_conditional_permutations - [validating_permutation]
|
68
|
+
non_validating_permutations.each do |non_validating_permutation|
|
69
|
+
exclusion_non_validating_test = generate_exclusion_non_validating_test(exclusion_validator, exclusion_options, non_validating_permutation)
|
70
|
+
exclusion_non_validating_tests << exclusion_non_validating_test
|
71
|
+
end
|
72
|
+
exclusion_non_validating_tests[0] = exclusion_non_validating_tests[0].prepend("#\n# For more natural readability of 'is_expected.not_to' context lines, 'unless' is represented by 'if not'\n# and 'unless not' is represented by 'if'.\n#\n")
|
73
|
+
exclusion_non_validating_tests
|
74
|
+
end
|
75
|
+
|
76
|
+
def generate_exclusion_non_validating_test(exclusion_validator, exclusion_options, non_validating_permutation)
|
77
|
+
exclusion_non_validating_test = compose_conditional_non_validating_context_string(exclusion_options, non_validating_permutation)
|
78
|
+
exclusion_non_validating_test.concat(compose_conditional_before_strings(exclusion_options, non_validating_permutation))
|
79
|
+
non_validating_test = generate_exclusion_test(exclusion_validator, exclusion_options[:non_conditional_options])
|
80
|
+
non_validating_test.sub!("is_expected.to","is_expected.not_to")
|
81
|
+
non_validating_test = adjust_conditional_test_indentation(non_validating_test)
|
82
|
+
exclusion_non_validating_test.concat(non_validating_test)
|
83
|
+
exclusion_non_validating_test.concat("\n end")
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_exclusion_test_core(validator_options, validator_attribute)
|
87
|
+
exclusion_enumerable = validator_options[:in] || validator_options[:within]
|
88
|
+
if exclusion_enumerable.is_a?(Array)
|
89
|
+
" it do\n is_expected.to validate_exclusion_of(:#{ validator_attribute }).\n in_array(#{ exclusion_enumerable })"
|
90
|
+
elsif exclusion_enumerable.is_a?(Range)
|
91
|
+
" it do\n is_expected.to validate_exclusion_of(:#{ validator_attribute }).\n in_range(#{ exclusion_enumerable })"
|
92
|
+
elsif exclusion_enumerable.lambda?
|
93
|
+
" #\n # Note: Your 'in:/within:' configuration option value is a 'Lambda'\n" +
|
94
|
+
" # You will need to implement a customized test.\n" +
|
95
|
+
" it do\n skip(\"Remove this skip line once test customization has been implemented.\")\n is_expected.to validate_exclusion_of(:#{ validator_attribute })"
|
96
|
+
# CONFIRMATION TODO: Confirm whether or not exclusion_enumerable could be a 'Proc' that isn't a 'lambda'
|
97
|
+
elsif exclusion_enumerable.respond_to?(:call)
|
98
|
+
" #\n # Note: Your 'in:/within:' configuration option value is a 'Proc'\n" +
|
99
|
+
" # You will need to implement a customized test.\n" +
|
100
|
+
" it do\n skip(\"Remove this skip line once test customization has been implemented.\")\n is_expected.to validate_exclusion_of(:#{ validator_attribute })"
|
101
|
+
else
|
102
|
+
" #\n # Alert: Invalid 'in:/within:' enumerable object type: '#{ exclusion_enumerable.class.to_s }'\n" +
|
103
|
+
" # Valid exclusion 'in:/within:' enumerable object types: 'Array', 'Range'\n" +
|
104
|
+
" # (or a proc, lambda or symbol which returns an enumerable)\n" +
|
105
|
+
" it do\n skip(\"Remove this skip line once valid enumerable object type is provided.\")\n is_expected.to validate_exclusion_of(:#{ validator_attribute })"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# def get_exclusion_test_options(options)
|
111
|
+
# exclusion_test_options = ""
|
112
|
+
# options.map do |option, option_value|
|
113
|
+
# exclusion_test_option = get_exclusion_test_option(option, option_value)
|
114
|
+
# exclusion_test_options.concat(".\n " + exclusion_test_option) if exclusion_test_option.present?
|
115
|
+
# end
|
116
|
+
# exclusion_test_options
|
117
|
+
# end
|
118
|
+
#
|
119
|
+
# def get_exclusion_test_option(option, option_value)
|
120
|
+
# case option
|
121
|
+
# # IMPLEMENTATION TODO: Determine if 'allow_blank' is a valid option
|
122
|
+
# # when :allow_blank
|
123
|
+
# # "allow_blank"
|
124
|
+
# # IMPLEMENTATION TODO: Determine if 'allow_nil' is a valid option
|
125
|
+
# # when :allow_nil
|
126
|
+
# # "allow_nil"
|
127
|
+
# when :message
|
128
|
+
# if option_value.include? '"'
|
129
|
+
# "with_message('#{ option_value }')"
|
130
|
+
# else
|
131
|
+
# "with_message(\"#{ option_value }\")"
|
132
|
+
# end
|
133
|
+
# when :on
|
134
|
+
# "on(:#{ option_value })"
|
135
|
+
# else
|
136
|
+
# # IMPLEMENTATION TODO: Possibly handle as an error or modify evaluation of option
|
137
|
+
# ""
|
138
|
+
# end
|
139
|
+
# end
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module Matchmaker
|
5
|
+
module ValidateInclusionOf
|
6
|
+
|
7
|
+
|
8
|
+
def validate_inclusion_of_matcher_tests
|
9
|
+
inclusion_tests = []
|
10
|
+
extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::InclusionValidator).flatten.map do |validator|
|
11
|
+
validator_options = validator.options.dup
|
12
|
+
validator_if_option = validator_options.delete(:if)
|
13
|
+
validator_unless_option = validator_options.delete(:unless)
|
14
|
+
validator.attributes.map do |attribute|
|
15
|
+
inclusion_tests << generate_inclusion_test_multiple_lines(validator_options, attribute)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
inclusion_tests.flatten.compact.uniq.join("\n\n")
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def generate_inclusion_test_multiple_lines(validator_options, attribute)
|
25
|
+
inclusion_test = get_inclusion_test_core(validator_options, attribute)
|
26
|
+
inclusion_test_options = get_inclusion_test_options(validator_options)
|
27
|
+
inclusion_test.concat(inclusion_test_options) if inclusion_test_options.present?
|
28
|
+
inclusion_test.concat("\n end")
|
29
|
+
[inclusion_test]
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def get_inclusion_test_core(validator_options, attribute)
|
34
|
+
inclusion_enumerable = validator_options[:in] || validator_options[:within]
|
35
|
+
if inclusion_enumerable.is_a?(Array)
|
36
|
+
" it do\n is_expected.to validate_inclusion_of(:#{ attribute }).\n in_array(#{ inclusion_enumerable })"
|
37
|
+
elsif inclusion_enumerable.is_a?(Range)
|
38
|
+
" it do\n is_expected.to validate_inclusion_of(:#{ attribute }).\n in_range(#{ inclusion_enumerable })"
|
39
|
+
elsif inclusion_enumerable.lambda?
|
40
|
+
" #\n # Note: Your 'in:/within:' configuration option value is a 'Lambda'\n" +
|
41
|
+
" # You will need to implement a customized test.\n" +
|
42
|
+
" it do\n skip(\"Remove this skip line once test customization has been implemented.\")\n is_expected.to validate_inclusion_of(:#{ attribute })"
|
43
|
+
# CONFIRMATION TODO: Confirm whether or not inclusion_enumerable could be a 'Proc' that isn't a 'lambda'
|
44
|
+
elsif inclusion_enumerable.respond_to?(:call)
|
45
|
+
" #\n # Note: Your 'in:/within:' configuration option value is a 'Proc'\n" +
|
46
|
+
" # You will need to implement a customized test.\n" +
|
47
|
+
" it do\n skip(\"Remove this skip line once test customization has been implemented.\")\n is_expected.to validate_inclusion_of(:#{ attribute })"
|
48
|
+
else
|
49
|
+
" #\n # Alert: Invalid 'in:/within:' enumerable object type: '#{ inclusion_enumerable.class.to_s }'\n" +
|
50
|
+
" # Valid inclusion 'in:/within:' enumerable object types: 'Array', 'Range'\n" +
|
51
|
+
" # (or a proc, lambda or symbol which returns an enumerable)\n" +
|
52
|
+
" it do\n skip(\"Remove this skip line once valid enumerable object type is provided.\")\n is_expected.to validate_inclusion_of(:#{ attribute })"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def get_inclusion_test_options(options)
|
58
|
+
inclusion_test_options = ""
|
59
|
+
options.map do |option, option_value|
|
60
|
+
inclusion_test_option = get_inclusion_test_option(option, option_value)
|
61
|
+
inclusion_test_options.concat(".\n " + inclusion_test_option) if inclusion_test_option.present?
|
62
|
+
end
|
63
|
+
inclusion_test_options
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def get_inclusion_test_option(option, option_value)
|
68
|
+
# IMPLEMENTATION TODO: Determine if it is possible to implement 'with_low_message' and 'with_high_message'
|
69
|
+
case option
|
70
|
+
# IMPLEMENTATION TODO: Determine if 'allow_blank' is a valid option
|
71
|
+
# when :allow_blank
|
72
|
+
# "allow_blank"
|
73
|
+
# IMPLEMENTATION TODO: Determine if 'allow_nil' is a valid option
|
74
|
+
# when :allow_nil
|
75
|
+
# "allow_nil"
|
76
|
+
when :message
|
77
|
+
if option_value.include? '"'
|
78
|
+
"with_message('#{ option_value }')"
|
79
|
+
else
|
80
|
+
"with_message(\"#{ option_value }\")"
|
81
|
+
end
|
82
|
+
when :on
|
83
|
+
"on(:#{ option_value })"
|
84
|
+
else
|
85
|
+
# IMPLEMENTATION TODO: Possibly handle as an error or modify evaluation of option
|
86
|
+
""
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module ActiveModelMatcher
|
5
|
+
module ValidateLengthOf
|
6
|
+
|
7
|
+
def validate_length_of_matcher_tests
|
8
|
+
length_validators = extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::LengthValidator).flatten
|
9
|
+
generate_validator_matcher_tests(length_validators)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module ActiveModelMatcher
|
5
|
+
module ValidateNumericalityOf
|
6
|
+
|
7
|
+
def validate_numericality_of_matcher_tests
|
8
|
+
numericality_validators = extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::NumericalityValidator).flatten
|
9
|
+
generate_validator_matcher_tests(numericality_validators)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module ActiveModelMatcher
|
5
|
+
module ValidatePresenceOf
|
6
|
+
|
7
|
+
def validate_presence_of_matcher_tests
|
8
|
+
presence_validators = extract_validators(@active_record_model_sm_model, ::ActiveRecord::Validations::PresenceValidator).flatten
|
9
|
+
generate_validator_matcher_tests(presence_validators)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module ActiveRecordMatcher
|
5
|
+
module ValidateUniquenessOf
|
6
|
+
|
7
|
+
def validate_uniqueness_of_matcher_tests
|
8
|
+
uniqueness_validators = extract_validators(@active_record_model_sm_model, ::ActiveRecord::Validations::UniquenessValidator).flatten
|
9
|
+
generate_validator_matcher_tests(uniqueness_validators)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module Validation
|
5
|
+
|
6
|
+
def wrap_conditional_validations validator, specs
|
7
|
+
# if_mock = if_condition_mock validator
|
8
|
+
# unless_mock = unless_condition_mock validator
|
9
|
+
# padding = if_mock.blank? && unless_mock.blank? ? '' : ' '
|
10
|
+
specs = specs.map do |spec|
|
11
|
+
"#{spec}"
|
12
|
+
# "#{padding}#{spec}"
|
13
|
+
end.uniq.join("\n")
|
14
|
+
# end.uniq.join("\n ")
|
15
|
+
# if if_mock.blank? && unless_mock.blank?
|
16
|
+
# specs
|
17
|
+
# else
|
18
|
+
# "context \"with conditions\" do\n before do\n#{if_mock}#{unless_mock} end\n\n#{specs}\n end\n"
|
19
|
+
# end
|
20
|
+
end
|
21
|
+
|
22
|
+
def if_condition_mock validator
|
23
|
+
if_condition = validator.options[:if]
|
24
|
+
return '' unless if_condition && if_condition.is_a?(Symbol)
|
25
|
+
" allow(subject).to receive(:#{if_condition.to_s}).and_return(true)\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def unless_condition_mock validator
|
29
|
+
unless_condition = validator.options[:unless]
|
30
|
+
return '' unless unless_condition && unless_condition.is_a?(Symbol)
|
31
|
+
" allow(subject).to receive(:#{unless_condition.to_s}).and_return(false)\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module ActiveModelMatcher
|
5
|
+
module Validations
|
6
|
+
|
7
|
+
def validate_absence_of_matcher_tests
|
8
|
+
absence_validators = extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::AbsenceValidator).flatten
|
9
|
+
generate_validator_matcher_tests(absence_validators)
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate_acceptance_of_matcher_tests
|
13
|
+
acceptance_validators = extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::AcceptanceValidator).flatten
|
14
|
+
generate_validator_matcher_tests(acceptance_validators)
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_confirmation_of_matcher_tests
|
18
|
+
confirmation_validators = extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::ConfirmationValidator).flatten
|
19
|
+
generate_validator_matcher_tests(confirmation_validators)
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate_length_of_matcher_tests
|
23
|
+
length_validators = extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::LengthValidator).flatten
|
24
|
+
generate_validator_matcher_tests(length_validators)
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate_numericality_of_matcher_tests
|
28
|
+
numericality_validators = extract_validators(@active_record_model_sm_model, ::ActiveModel::Validations::NumericalityValidator).flatten
|
29
|
+
generate_validator_matcher_tests(numericality_validators)
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate_presence_of_matcher_tests
|
33
|
+
presence_validators = extract_validators(@active_record_model_sm_model, ::ActiveRecord::Validations::PresenceValidator).flatten
|
34
|
+
generate_validator_matcher_tests(presence_validators)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module ShouldaMatchmakers
|
2
|
+
module Model
|
3
|
+
module ActiveRecord
|
4
|
+
module ConditionalValidations
|
5
|
+
|
6
|
+
# def generate_validation_tests(validator)
|
7
|
+
#
|
8
|
+
# end
|
9
|
+
|
10
|
+
def generate_conditional_validation_tests(validator)
|
11
|
+
validator_conditional_tests = []
|
12
|
+
if_option_values_are_symbols = true
|
13
|
+
unless_option_values_are_symbols = true
|
14
|
+
validator_options = validator.options.dup
|
15
|
+
if_option_values = validator_options.delete(:if)
|
16
|
+
unless_option_values = validator_options.delete(:unless)
|
17
|
+
|
18
|
+
if if_option_values.present?
|
19
|
+
if !if_option_values.is_a?(Array)
|
20
|
+
if_option_values = [if_option_values]
|
21
|
+
end
|
22
|
+
if_option_values_are_symbols = all_option_values_are_symbols(if_option_values)
|
23
|
+
else
|
24
|
+
if_option_values = []
|
25
|
+
end
|
26
|
+
|
27
|
+
if unless_option_values.present?
|
28
|
+
if !unless_option_values.is_a?(Array)
|
29
|
+
unless_option_values = [unless_option_values]
|
30
|
+
end
|
31
|
+
unless_option_values_are_symbols = all_option_values_are_symbols(unless_option_values)
|
32
|
+
else
|
33
|
+
unless_option_values = []
|
34
|
+
end
|
35
|
+
|
36
|
+
if if_option_values_are_symbols && unless_option_values_are_symbols
|
37
|
+
|
38
|
+
if_and_unless_option_values = if_option_values + unless_option_values
|
39
|
+
validator_conditional_test = " context \""
|
40
|
+
|
41
|
+
if_and_unless_option_values.each_with_index do |option_value, index|
|
42
|
+
|
43
|
+
if index < if_option_values.size
|
44
|
+
validator_conditional_test.concat("if #{ option_value.to_s.chomp('?')} and ")
|
45
|
+
else
|
46
|
+
validator_conditional_test.concat("unless #{ option_value.to_s.chomp('?')} and ")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
validator_conditional_test.chomp!(" and ").concat("\" do\n")
|
51
|
+
|
52
|
+
if_and_unless_option_values.each_with_index do |option_value, index|
|
53
|
+
if index < if_option_values.size
|
54
|
+
validator_conditional_test.concat(" before { allow(subject).to receive(:#{ option_value }).and_return(true) }\n")
|
55
|
+
else
|
56
|
+
validator_conditional_test.concat(" before { allow(subject).to receive(:#{ option_value }).and_return(false) }\n")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
validator_conditional_test.concat("\n it { is_expected.to validate_#{ validator.kind.to_s }_of(:#{ validator.attributes.first }) }\n end")
|
61
|
+
validator_conditional_tests << [validator_conditional_test]
|
62
|
+
|
63
|
+
possible_conditional_permutations = get_possible_permutations(if_option_values.size + unless_option_values.size)
|
64
|
+
validating_permutation = get_validating_permutation(if_option_values.size, unless_option_values.size)
|
65
|
+
non_validating_permutations = possible_conditional_permutations - [validating_permutation]
|
66
|
+
|
67
|
+
non_validating_permutations.each do |non_validating_permutation|
|
68
|
+
validator_conditional_test = " context \""
|
69
|
+
|
70
|
+
if_and_unless_option_values.each_with_index do |option_value, index|
|
71
|
+
|
72
|
+
if index < if_option_values.size
|
73
|
+
if non_validating_permutation[index]
|
74
|
+
# TRACE.debug " *** TRUE CLASS WORKED!!!"
|
75
|
+
end
|
76
|
+
if non_validating_permutation[index]
|
77
|
+
validator_conditional_test.concat("if #{ option_value.to_s.chomp('?')} and ")
|
78
|
+
else
|
79
|
+
validator_conditional_test.concat("if not #{ option_value.to_s.chomp('?')} and ")
|
80
|
+
end
|
81
|
+
else
|
82
|
+
if non_validating_permutation[index]
|
83
|
+
validator_conditional_test.concat("if #{ option_value.to_s.chomp('?')} and ")
|
84
|
+
else
|
85
|
+
validator_conditional_test.concat("if not #{ option_value.to_s.chomp('?')} and ")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
validator_conditional_test.chomp!(" and ").concat("\" do\n")
|
90
|
+
if_and_unless_option_values.each_with_index do |option_value, index|
|
91
|
+
validator_conditional_test.concat(" before { allow(subject).to receive(:#{ option_value }).and_return(#{ non_validating_permutation[index] }) }\n")
|
92
|
+
end
|
93
|
+
validator_conditional_test.concat("\n it { is_expected.not_to validate_#{ validator.kind.to_s }_of(:#{ validator.attributes.first }) }\n end")
|
94
|
+
validator_conditional_tests << [validator_conditional_test]
|
95
|
+
end
|
96
|
+
# else
|
97
|
+
# Skip tests due to non-symbol conditions
|
98
|
+
# validator.attributes.map do |attribute|
|
99
|
+
# skip = true
|
100
|
+
# presence_test = generate_presence_test_single_line(validator_options, attribute, skip)
|
101
|
+
# if presence_test[0].length > 80 || validator_options.count > 1
|
102
|
+
# presence_test = generate_presence_test_multiple_lines(validator_options, attribute, skip)
|
103
|
+
# end
|
104
|
+
# presence_test_comment = " # This test is currently skipped due to if: and/or unless: conditions that aren't symbols.\n"
|
105
|
+
# presence_test_comment.concat(" # Provide ")
|
106
|
+
# presence_test.prepend(presence_test_comment)
|
107
|
+
# presence_tests << presence_test
|
108
|
+
# end
|
109
|
+
end
|
110
|
+
validator_conditional_tests
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def all_option_values_are_symbols(option_values)
|
117
|
+
option_values_are_symbols = true
|
118
|
+
option_values.each do |option_value|
|
119
|
+
if !option_value.is_a?(Symbol)
|
120
|
+
option_values_are_symbols = false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
option_values_are_symbols
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def get_possible_permutations(number_of_option_values)
|
128
|
+
[true, false].repeated_permutation(number_of_option_values).to_a
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
def get_validating_permutation(if_option_values_size, unless_options_values_size)
|
133
|
+
validating_permutation = []
|
134
|
+
if_option_values_size.times do |n|
|
135
|
+
validating_permutation << true
|
136
|
+
end
|
137
|
+
unless_options_values_size.times do |n|
|
138
|
+
validating_permutation << false
|
139
|
+
end
|
140
|
+
validating_permutation
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|