quick_shoulda 0.0.2
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.
- data/.gitignore +18 -0
- data/.rdebugrc +3 -0
- data/.rspec +4 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +8 -0
- data/data/stored_strings.yml +44 -0
- data/lib/generators/quick_shoulda/generate/generate_generator.rb +11 -0
- data/lib/quick_shoulda/errors.rb +33 -0
- data/lib/quick_shoulda/file_writer.rb +58 -0
- data/lib/quick_shoulda/generator/association.rb +46 -0
- data/lib/quick_shoulda/generator/spec_content.rb +31 -0
- data/lib/quick_shoulda/generator/validation.rb +144 -0
- data/lib/quick_shoulda/generator.rb +11 -0
- data/lib/quick_shoulda/helpers/string_helpers.rb +18 -0
- data/lib/quick_shoulda/main.rb +39 -0
- data/lib/quick_shoulda/path_resolver.rb +31 -0
- data/lib/quick_shoulda/random_string.rb +51 -0
- data/lib/quick_shoulda/version.rb +3 -0
- data/lib/quick_shoulda.rb +26 -0
- data/quick_shoulda.gemspec +23 -0
- data/spec/file_writer_spec.rb +109 -0
- data/spec/fixtures/user_spec.rb +11 -0
- data/spec/fixtures/write_spec.rb +3 -0
- data/spec/generator/association_spec.rb +51 -0
- data/spec/generator/spec_content_spec.rb +65 -0
- data/spec/generator/validation_spec.rb +407 -0
- data/spec/main_spec.rb +154 -0
- data/spec/models/not_a_ruby_file.txt +0 -0
- data/spec/path_resolver_spec.rb +88 -0
- data/spec/quick_shoulda_spec.rb +64 -0
- data/spec/random_string_spec.rb +93 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/string_helpers_spec.rb +34 -0
- metadata +127 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'quick_shoulda/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "quick_shoulda"
|
|
8
|
+
spec.version = QuickShoulda::VERSION
|
|
9
|
+
spec.authors = ["Tien Nguyen"]
|
|
10
|
+
spec.email = ["nqtien310@gmail.com"]
|
|
11
|
+
spec.description = %q{Generate Shoulda testcases through rails generators}
|
|
12
|
+
spec.summary = %q{Generate Shoulda testcases}
|
|
13
|
+
spec.homepage = ""
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_development_dependency "debugger", "~> 1.3"
|
|
22
|
+
spec.add_development_dependency "rspec"
|
|
23
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
|
|
4
|
+
describe 'QuickShoulda::FileWriter' do
|
|
5
|
+
include QuickShoulda::Main
|
|
6
|
+
include QuickShoulda::Generator
|
|
7
|
+
include QuickShoulda::PathResolver
|
|
8
|
+
include QuickShoulda::FileWriter
|
|
9
|
+
|
|
10
|
+
context '#create_file_and_write_init_content' do
|
|
11
|
+
let(:spec_init_content) {
|
|
12
|
+
'spec init content'
|
|
13
|
+
}
|
|
14
|
+
let(:spec_file_path) {
|
|
15
|
+
File.expand_path('../test_written_folder/test_written_file.rb', __FILE__)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
after do
|
|
19
|
+
File.delete spec_file_path
|
|
20
|
+
FileUtils.rm_r File.dirname(spec_file_path)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should create folders which are in file path' do
|
|
24
|
+
File.should_not be_directory File.dirname(spec_file_path)
|
|
25
|
+
create_file_and_write_init_content
|
|
26
|
+
File.should be_directory File.dirname(spec_file_path)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'should create file' do
|
|
30
|
+
File.should_not be_file spec_file_path
|
|
31
|
+
create_file_and_write_init_content
|
|
32
|
+
File.should be_file spec_file_path
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'should write spec_init_content to file' do
|
|
36
|
+
File.should_not be_file spec_file_path
|
|
37
|
+
create_file_and_write_init_content
|
|
38
|
+
File.read(spec_file_path).should eq spec_init_content
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context '#clear_all_blocks' do
|
|
43
|
+
let(:association_block_header) { "describe '#Associations' do"}
|
|
44
|
+
let(:validation_block_header) { "describe '#Validations' do"}
|
|
45
|
+
|
|
46
|
+
it 'should invoke clear_block for validation block' do
|
|
47
|
+
should_receive(:block_describe_header).with(:validation).once.and_return(validation_block_header)
|
|
48
|
+
should_receive(:block_describe_header).with(:association).once.and_return(association_block_header)
|
|
49
|
+
should_receive(:clear_block).with(validation_block_header).once
|
|
50
|
+
should_receive(:clear_block).with(association_block_header).once
|
|
51
|
+
clear_all_blocks
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context '#clear_block' do
|
|
56
|
+
before do
|
|
57
|
+
@test_file_content = IO.read(file_path)
|
|
58
|
+
@spec_file_path = file_path
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
after do
|
|
62
|
+
File.open(file_path, 'w') do |file|
|
|
63
|
+
file.write(@test_file_content)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
let(:file_path) { 'spec/fixtures/user_spec.rb' }
|
|
68
|
+
|
|
69
|
+
[:association, :validation].each do |block_name|
|
|
70
|
+
it "should clear the whole #{block_name} block" do
|
|
71
|
+
block = block_describe_header(block_name)
|
|
72
|
+
( IO.read(file_path) =~ /#{block}\n.+\n.+\n\tend/ ).should_not be_nil
|
|
73
|
+
clear_block(block)
|
|
74
|
+
( IO.read(file_path) =~ /#{block}\n.+\n.+\n\tend/ ).should be_nil
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context '#write_block' do
|
|
80
|
+
before do
|
|
81
|
+
@test_file_content = IO.read(file_path)
|
|
82
|
+
@spec_file_path = file_path
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
after do
|
|
86
|
+
File.open(file_path, 'w') do |file|
|
|
87
|
+
file.write(@test_file_content)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
let(:shoulda_lines) { ['it { should be_written }', 'it { should be_written_again }'] }
|
|
92
|
+
|
|
93
|
+
let(:file_path) { 'spec/fixtures/write_spec.rb' }
|
|
94
|
+
|
|
95
|
+
[:association, :validation].each do |block|
|
|
96
|
+
context "#{block}" do
|
|
97
|
+
let(:expected) do
|
|
98
|
+
/\n\t#{block_describe_header(block)}\n\t\tit { should be_written }\n\t\tit { should be_written_again }\n\tend/
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "should write the whole #{block} block" do
|
|
102
|
+
( IO.read(file_path) =~ expected ).should be_nil
|
|
103
|
+
write_block(shoulda_content(block, shoulda_lines))
|
|
104
|
+
( IO.read(file_path) =~ expected ).should_not be_nil
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
describe 'User', :test => true do
|
|
2
|
+
describe '#Associations' do
|
|
3
|
+
it { should have_many(:attr1) }
|
|
4
|
+
it { should have_many(:attr2) }
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
describe '#Validations' do
|
|
8
|
+
it { should validate_presence_of(:user) }
|
|
9
|
+
it { should validate_presence_of(:password) }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'QuickShoulda::Generator::Association' do
|
|
4
|
+
include QuickShoulda::StringHelpers
|
|
5
|
+
include QuickShoulda::Generator::Association
|
|
6
|
+
|
|
7
|
+
describe '#generate_for_association' do
|
|
8
|
+
let(:association) do
|
|
9
|
+
mock(:association, :macro => :belongs_to,
|
|
10
|
+
:name => :friendly_user,
|
|
11
|
+
:options => options )
|
|
12
|
+
end
|
|
13
|
+
let(:options) {
|
|
14
|
+
{
|
|
15
|
+
:dependent => :destroy,
|
|
16
|
+
:class_name => 'User',
|
|
17
|
+
:order => 'users.email DESC',
|
|
18
|
+
:foreign_key => 'friendly_user_id'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let(:expected) do
|
|
23
|
+
"it { should belong_to(:friendly_user).dependent(:destroy).class_name('User').order('users.email DESC').with_foreign_key('friendly_user_id') }"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'should return valid shoulda test case' do
|
|
27
|
+
send(:generate_for_association, association).should eq expected
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe '#shoulda_option_method_with_value' do
|
|
32
|
+
context 'option exists in predefined OptionMethods' do
|
|
33
|
+
let(:option) { 'dependent' }
|
|
34
|
+
let(:value) { 'destroy' }
|
|
35
|
+
let(:expected) { ".dependent('destroy')" }
|
|
36
|
+
|
|
37
|
+
it 'should return valid shoulda option method with value as symbol' do
|
|
38
|
+
send(:shoulda_option_method_with_value, option, value).should eq expected
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'option does not exist in predefined OptionMethods' do
|
|
44
|
+
let(:option) { 'dependent1' }
|
|
45
|
+
|
|
46
|
+
it 'should return nil' do
|
|
47
|
+
send(:shoulda_option_method_with_value, option, '').should be_nil
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'QuickShoulda::Generator::SpecContent' do
|
|
4
|
+
include QuickShoulda::Generator::SpecContent
|
|
5
|
+
|
|
6
|
+
describe '#shoulda_content' do
|
|
7
|
+
let(:block_name) { :validation }
|
|
8
|
+
|
|
9
|
+
context 'with shoulda test cases' do
|
|
10
|
+
let(:shoulda_lines) do
|
|
11
|
+
['it { should validate_presence_of(:username) }',
|
|
12
|
+
'it { should validate_presence_of(:password) }']
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
let(:expected) do
|
|
16
|
+
exp = "\tdescribe '#Validations' do\n"
|
|
17
|
+
exp << "\t\t#{shoulda_lines[0]}\n"
|
|
18
|
+
exp << "\t\t#{shoulda_lines[1]}\n"
|
|
19
|
+
exp << "\tend\n"
|
|
20
|
+
exp
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should return whole shoulda content' do
|
|
24
|
+
shoulda_content(block_name, shoulda_lines.dup).should eq expected
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'with shoulda test cases' do
|
|
29
|
+
let(:shoulda_lines) { [] }
|
|
30
|
+
|
|
31
|
+
it 'should return whole shoulda content' do
|
|
32
|
+
shoulda_content(block_name, shoulda_lines.dup).should eq ''
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '#spec_init_content' do
|
|
38
|
+
before { should_receive(:model_full_namespace).and_return('User::Friend')}
|
|
39
|
+
|
|
40
|
+
let(:expected) do
|
|
41
|
+
exp = "require 'spec_helper'\n\n"
|
|
42
|
+
exp << "describe 'User::Friend' do\n"
|
|
43
|
+
exp << "end"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'should return valid describe block' do
|
|
47
|
+
spec_init_content.should eq expected
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '#block_describe_header' do
|
|
52
|
+
let(:block_name) { 'validation' }
|
|
53
|
+
let(:expected) { "describe '#Validations' do" }
|
|
54
|
+
|
|
55
|
+
it 'should invoke to_sym for block_name' do
|
|
56
|
+
block_name.should_receive(:to_sym).once
|
|
57
|
+
block_describe_header(block_name)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'should return the describe header for block' do
|
|
61
|
+
block_describe_header(block_name).should eq expected
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'QuickShoulda::Generator::Validation' do
|
|
4
|
+
include QuickShoulda::StringHelpers
|
|
5
|
+
include QuickShoulda::Generator::Validation
|
|
6
|
+
|
|
7
|
+
describe '#generate' do
|
|
8
|
+
let(:attribute) { :student }
|
|
9
|
+
|
|
10
|
+
let(:presence_options) { {} }
|
|
11
|
+
let(:uniqueness_options) { { scope: [:class, :college]} }
|
|
12
|
+
let(:format_options) { { with: /abc/} }
|
|
13
|
+
let(:length_options) { { minimum: 1, maximum: 20}}
|
|
14
|
+
let(:inclusion_options) { { within: (1..20), :allow_nil => true, :allow_blank => true} }
|
|
15
|
+
let(:exclusion_options) { { in: ['a', 'b', 'c']} }
|
|
16
|
+
let(:numericality_options) { { only_integer: true, message: 'must be an integer' } }
|
|
17
|
+
|
|
18
|
+
let(:random_strings) do
|
|
19
|
+
{
|
|
20
|
+
matched_strings: ['abc'],
|
|
21
|
+
unmatched_strings: ['nqtien310@gmail.com', 'nqtien310@hotdev.com']
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
['presence', 'format', 'uniqueness', 'length', 'inclusion', 'exclusion', 'numericality'].each do | type |
|
|
26
|
+
let("#{type}_validator_class") { mock("#{type}_validator_class".to_sym, to_s: "ActiveModel::Validations::#{type.upcase}Validator") }
|
|
27
|
+
let("#{type}_validator".to_sym) do
|
|
28
|
+
mock("#{type}_validator".to_sym, :class => eval("#{type}_validator_class"),
|
|
29
|
+
attributes: [attribute], options: eval("#{type}_options") )
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
let(:validators) { [presence_validator, uniqueness_validator, format_validator, length_validator,
|
|
34
|
+
inclusion_validator, exclusion_validator, numericality_validator] }
|
|
35
|
+
let(:model) { mock(:model, validators: validators) }
|
|
36
|
+
|
|
37
|
+
before { QuickShoulda::RandomString.should_receive(:generate).with(/abc/).and_return(random_strings) }
|
|
38
|
+
|
|
39
|
+
let(:expected) {
|
|
40
|
+
[
|
|
41
|
+
'it { should validate_presence_of(:student) }',
|
|
42
|
+
'it { should validate_uniqueness_of(:student).scoped_to(:class).scoped_to(:college) }',
|
|
43
|
+
"it { should allow_value('abc').for(:student) }",
|
|
44
|
+
"it { should_not allow_value('nqtien310@gmail.com').for(:student) }",
|
|
45
|
+
"it { should_not allow_value('nqtien310@hotdev.com').for(:student) }",
|
|
46
|
+
"it { should ensure_length_of(:student).is_at_least(1).is_at_most(20) }",
|
|
47
|
+
"it { should ensure_inclusion_of(:student).in_range(1..20).allow_nil(true).allow_blank(true) }",
|
|
48
|
+
'it { should ensure_exclusion_of(:student).in_array(["a", "b", "c"]) }',
|
|
49
|
+
"it { should validate_numericality_of(:student).only_integer.with_message('must be an integer') }"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
it 'should return exact array of strings' do
|
|
54
|
+
generate_validations(model).should eq expected
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe '#generate_for_validator' do
|
|
59
|
+
before { should_receive(:_validation_type).and_return(type) }
|
|
60
|
+
let(:attributes) { [:username, :email] }
|
|
61
|
+
let(:options) { {:minimum => 100, :maximum => 200} }
|
|
62
|
+
let(:validator) { mock(:validator, :attributes => attributes, :options => options) }
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
context '_validation_type returns nil' do
|
|
66
|
+
let(:type) { nil }
|
|
67
|
+
|
|
68
|
+
it 'should return nil' do
|
|
69
|
+
send(:generate_for_validator, validator).should be_nil
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context '_validation_type returns not nil' do
|
|
74
|
+
let(:type) { 'length' }
|
|
75
|
+
|
|
76
|
+
context 'attrs_filter returns an empty array' do
|
|
77
|
+
before { should_receive(:attrs_filter).and_return([]) }
|
|
78
|
+
|
|
79
|
+
it 'should return nil' do
|
|
80
|
+
send(:generate_for_validator, validator).should be_nil
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context 'attrs_filter does not return an empty array' do
|
|
85
|
+
before { should_receive(:attrs_filter).and_return(attributes) }
|
|
86
|
+
|
|
87
|
+
it 'should invoke generate_shouldas valid parameters' do
|
|
88
|
+
should_receive(:generate_shouldas).with(attributes, options)
|
|
89
|
+
send(:generate_for_validator, validator)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'should assign value to validation_type attr_accessor' do
|
|
93
|
+
validation_type.should be_nil
|
|
94
|
+
send(:generate_for_validator, validator)
|
|
95
|
+
validation_type.should eq type
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe '#attrs_filter' do
|
|
102
|
+
let(:attrs) { [:friendly_id, :username]}
|
|
103
|
+
|
|
104
|
+
it 'should remove all attr which can not pass filters' do
|
|
105
|
+
attrs_filter(attrs).should eq [:username]
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe '#_validation_type' do
|
|
110
|
+
let(:validator_class) { mock(:validator_class, :to_s => validator_class_name) }
|
|
111
|
+
let(:validator) { mock(:validator, :class => validator_class) }
|
|
112
|
+
let(:expected_type) { 'length' }
|
|
113
|
+
|
|
114
|
+
context 'valid validator' do
|
|
115
|
+
let(:validator_class_name) { 'ActiveModel::Validations::LengthValidator' }
|
|
116
|
+
|
|
117
|
+
it 'should return expected_type' do
|
|
118
|
+
send(:_validation_type, validator).should eq expected_type
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context 'invalid validator' do
|
|
123
|
+
let(:validator_class_name) { 'ActiveModel::Validations::LengthValidatoErrorr' }
|
|
124
|
+
|
|
125
|
+
it 'should return nil' do
|
|
126
|
+
send(:_validation_type, validator).should be_nil
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context 'custom validator' do
|
|
131
|
+
let(:validator_class_name) { 'ActiveModel::Validations::EmailValidator' }
|
|
132
|
+
|
|
133
|
+
it 'should return nil' do
|
|
134
|
+
send(:_validation_type, validator).should be_nil
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe '#shoulda_matcher_method' do
|
|
140
|
+
context 'ensure type' do
|
|
141
|
+
['exclusion', 'inclusion', 'length'].each do |type|
|
|
142
|
+
context "validate #{type}" do
|
|
143
|
+
let(:expected) { "ensure_#{type}_of" }
|
|
144
|
+
it "should return ensure_#{type}_of" do
|
|
145
|
+
should_receive(:validation_type).at_least(1).and_return(type)
|
|
146
|
+
send(:shoulda_matcher_method).should == expected
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
context 'validate type' do
|
|
153
|
+
['presence', 'uniquness'].each do |type|
|
|
154
|
+
context "validate #{type}" do
|
|
155
|
+
let(:expected) { "validate_#{type}_of" }
|
|
156
|
+
it "should return validate_#{type}_of" do
|
|
157
|
+
should_receive(:validation_type).at_least(1).and_return(type)
|
|
158
|
+
send(:shoulda_matcher_method).should == expected
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
describe '#shoulda_option_method' do
|
|
166
|
+
context 'cannot look up for option method' do
|
|
167
|
+
before { should_receive(:shoulda_option_method_name).and_return(nil) }
|
|
168
|
+
it 'should return nil' do
|
|
169
|
+
send(:shoulda_option_method, nil, nil).should be_nil
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
context 'can look up for option method' do
|
|
174
|
+
let(:value) { 'value' }
|
|
175
|
+
|
|
176
|
+
context 'scope_to option method' do
|
|
177
|
+
before { should_receive(:shoulda_option_method_name).and_return('scoped_to') }
|
|
178
|
+
|
|
179
|
+
it 'should invoke #scope_to' do
|
|
180
|
+
should_receive(:shoulda_scope_to_method).with(value).once
|
|
181
|
+
send(:shoulda_option_method, nil, value)
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
context 'no value methods' do
|
|
186
|
+
['case_insensitive', 'only_integer'].each do |method|
|
|
187
|
+
it "should invoke #shoulda_method_without_value with #{method}" do
|
|
188
|
+
should_receive(:shoulda_option_method_name).and_return(method)
|
|
189
|
+
should_receive(:shoulda_method_without_value).with(method).once
|
|
190
|
+
send(:shoulda_option_method, nil, value)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
context 'other option method' do
|
|
196
|
+
let(:method) { 'is_at_least' }
|
|
197
|
+
|
|
198
|
+
before { should_receive(:shoulda_option_method_name).and_return(method) }
|
|
199
|
+
it 'should invoke #shoulda_normal_option_method' do
|
|
200
|
+
should_receive(:shoulda_normal_option_method).with(method, value)
|
|
201
|
+
send(:shoulda_option_method, nil, value)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
describe '#shoulda_normal_option_method' do
|
|
208
|
+
let(:method) { 'is_at_least'}
|
|
209
|
+
let(:value) { 50 }
|
|
210
|
+
let(:expected) { '.is_at_least(50)' }
|
|
211
|
+
before { should_receive(:value_transform).with(value).and_return('(50)') }
|
|
212
|
+
|
|
213
|
+
it 'should return a text contain both method and value' do
|
|
214
|
+
send(:shoulda_normal_option_method, method, value).should eq expected
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
describe '#shoulda_option_methods_chain' do
|
|
219
|
+
context 'no options given' do
|
|
220
|
+
it 'should return ""' do
|
|
221
|
+
send(:shoulda_option_methods_chain,{}).should be_empty
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
context 'options given' do
|
|
226
|
+
context 'matched options' do
|
|
227
|
+
context 'contain invalid option' do
|
|
228
|
+
let(:options) { {:minimum=>1, :maximum11=>20} }
|
|
229
|
+
let(:expected) { ".is_at_least(1)" }
|
|
230
|
+
it 'should return shoulda option methods corresponded with given options exclude the invalid option' do
|
|
231
|
+
send(:shoulda_option_methods_chain, options).should eq expected
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
context 'do not contain invalid option' do
|
|
236
|
+
let(:options) { {:minimum=>1, :maximum=>20} }
|
|
237
|
+
let(:expected) { ".is_at_least(1).is_at_most(20)" }
|
|
238
|
+
it 'should return shoulda option methods corresponded with given options' do
|
|
239
|
+
send(:shoulda_option_methods_chain, options).should eq expected
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
describe '#generate_shoulda' do
|
|
247
|
+
let(:attribute) { :username }
|
|
248
|
+
|
|
249
|
+
context 'format type' do
|
|
250
|
+
let(:type) { 'format' }
|
|
251
|
+
let(:options) { {:format => /abc/i} }
|
|
252
|
+
let(:expected) { ["it { should allow_value('abc').for(:username) }"] }
|
|
253
|
+
|
|
254
|
+
before do
|
|
255
|
+
should_receive(:validation_type).at_least(1).and_return(type)
|
|
256
|
+
should_receive(:generate_shouldas_for_format_validation).and_return(expected)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it 'should return shouldas for format validation' do
|
|
260
|
+
send(:generate_shoulda, attribute, options).should eq expected
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
context 'other types' do
|
|
265
|
+
let(:type) { 'length' }
|
|
266
|
+
let(:options) { {:minimum=>1, :maximum=>20} }
|
|
267
|
+
let(:expected) { ['it { should ensure_length_of(:username).is_at_least(1).is_at_most(20) }'] }
|
|
268
|
+
|
|
269
|
+
it 'should return 1 complete shoulda test case' do
|
|
270
|
+
should_receive(:validation_type).at_least(1).and_return(type)
|
|
271
|
+
send(:generate_shoulda, attribute, options).should eq expected
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
describe "#shoulda_option_method_name" do
|
|
277
|
+
context 'pass filters' do
|
|
278
|
+
before { should_receive(:pass_filter?).and_return(true) }
|
|
279
|
+
|
|
280
|
+
context 'rails validate option is mapped to a shoulda method' do
|
|
281
|
+
let(:option) { :minimum }
|
|
282
|
+
let(:expected) { 'is_at_least' }
|
|
283
|
+
let(:value) { '' }
|
|
284
|
+
|
|
285
|
+
it 'should return the mapped shoulda method' do
|
|
286
|
+
send(:shoulda_option_method_name, option, value).should eq expected
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
context 'rails validate option is mapped to a hash' do
|
|
291
|
+
context 'value type mapped to a shoulda method' do
|
|
292
|
+
let(:option) { :in }
|
|
293
|
+
let(:value) { 1..2 }
|
|
294
|
+
let(:expected) { 'in_range' }
|
|
295
|
+
|
|
296
|
+
it 'should return the mapped shoulda method' do
|
|
297
|
+
send(:shoulda_option_method_name, option, value).should eq expected
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
context 'value type is not mapped to a shoulda method' do
|
|
302
|
+
let(:option) { :in }
|
|
303
|
+
let(:value) { 'abcdef' }
|
|
304
|
+
|
|
305
|
+
it 'should return nil' do
|
|
306
|
+
send(:shoulda_option_method_name, option, value).should be_nil
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
context 'not pass filters' do
|
|
313
|
+
before { should_receive(:pass_filter?).and_return(false)}
|
|
314
|
+
|
|
315
|
+
it 'should return nil' do
|
|
316
|
+
send(:shoulda_option_method_name, '', '').should be_nil
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
describe '#shoulda_scope_to_method' do
|
|
322
|
+
context 'single attr' do
|
|
323
|
+
let(:value) { :username }
|
|
324
|
+
let(:expected) { ".scoped_to(:username)" }
|
|
325
|
+
it 'should encapsulate attr inside scope_to()' do
|
|
326
|
+
send(:shoulda_scope_to_method, value).should eq expected
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
context 'array attr' do
|
|
331
|
+
let(:value) { [:account, :date]}
|
|
332
|
+
let(:expected) { ".scoped_to(:account).scoped_to(:date)"}
|
|
333
|
+
|
|
334
|
+
it 'should encapsulate each attr inside scope_to()' do
|
|
335
|
+
send(:shoulda_scope_to_method, value).should eq expected
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
describe '#generate_allow_shouldas' do
|
|
341
|
+
context 'allow' do
|
|
342
|
+
let(:type) { 'matched_strings' }
|
|
343
|
+
let(:strings) do
|
|
344
|
+
['nqtien310@gmail.com', 'nqtien310@hotdev.com']
|
|
345
|
+
end
|
|
346
|
+
let(:attr) { :email }
|
|
347
|
+
let(:expected) do
|
|
348
|
+
["it { should allow_value('nqtien310@gmail.com').for(:#{attr}) }",
|
|
349
|
+
"it { should allow_value('nqtien310@hotdev.com').for(:#{attr}) }",
|
|
350
|
+
]
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
it 'should return full shoulda allow test cases' do
|
|
354
|
+
send(:generate_allow_shouldas, type, strings, attr).should eq expected
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
describe '#generate_shouldas_for_format_validation' do
|
|
360
|
+
let(:attr) { 'email' }
|
|
361
|
+
let(:matched_strings) { ['123','456'] }
|
|
362
|
+
let(:unmatched_strings) { ['abc'] }
|
|
363
|
+
let(:options) { {with: /123|456/ } }
|
|
364
|
+
|
|
365
|
+
let(:random_strings) {
|
|
366
|
+
{
|
|
367
|
+
matched_strings: matched_strings,
|
|
368
|
+
unmatched_strings: unmatched_strings
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
before { QuickShoulda::RandomString.should_receive(:generate).with(options[:with]).and_return(random_strings) }
|
|
373
|
+
after { send(:generate_shouldas_for_format_validation, attr, options) }
|
|
374
|
+
|
|
375
|
+
it 'should invoke generate_allow_shouldas for matched_strings and unmatched strings' do
|
|
376
|
+
should_receive(:generate_allow_shouldas).with(:matched_strings, matched_strings, attr)
|
|
377
|
+
should_receive(:generate_allow_shouldas).with(:unmatched_strings, unmatched_strings, attr)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
describe '#pass_filter?' do
|
|
382
|
+
context 'option method does not appear in filter list' do
|
|
383
|
+
let(:option) { 'message' }
|
|
384
|
+
it 'should return true' do
|
|
385
|
+
send(:pass_filter?, option).should be_true
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
context 'option method appears in filter list' do
|
|
390
|
+
let(:option) { 'allow_blank' }
|
|
391
|
+
|
|
392
|
+
context 'option method matches validation_type' do
|
|
393
|
+
before { should_receive(:validation_type).and_return('inclusion') }
|
|
394
|
+
it 'should return true' do
|
|
395
|
+
send(:pass_filter?, option).should be_true
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
context 'option method does not match validation_type' do
|
|
400
|
+
before { should_receive(:validation_type).and_return('presence') }
|
|
401
|
+
it 'should return true' do
|
|
402
|
+
send(:pass_filter?, option).should be_false
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
end
|