active_mocker 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +7 -0
- data/active_mocker.gemspec +30 -0
- data/lib/active_mocker.rb +5 -0
- data/lib/active_mocker/active_record.rb +12 -0
- data/lib/active_mocker/active_record/relationships.rb +34 -0
- data/lib/active_mocker/active_record/schema.rb +81 -0
- data/lib/active_mocker/active_record/scope.rb +12 -0
- data/lib/active_mocker/base.rb +170 -0
- data/lib/active_mocker/field.rb +28 -0
- data/lib/active_mocker/model_reader.rb +63 -0
- data/lib/active_mocker/reparameterize.rb +21 -0
- data/lib/active_mocker/schema_reader.rb +46 -0
- data/lib/active_mocker/table.rb +22 -0
- data/lib/active_mocker/version.rb +3 -0
- data/lib/file_reader.rb +7 -0
- data/lib/string_reader.rb +9 -0
- data/spec/lib/active_mocker/active_record/schema_spec.rb +2721 -0
- data/spec/lib/active_mocker/base_spec.rb +220 -0
- data/spec/lib/active_mocker/model_reader_spec.rb +126 -0
- data/spec/lib/active_mocker/schema_reader_spec.rb +124 -0
- data/spec/lib/model.rb +28 -0
- data/spec/lib/person.rb +9 -0
- data/spec/lib/schema.rb +40 -0
- metadata +152 -0
@@ -0,0 +1,220 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
$:.unshift File.expand_path('../../', __FILE__)
|
3
|
+
require 'string_reader'
|
4
|
+
require 'active_mocker/table'
|
5
|
+
require 'active_mocker/reparameterize'
|
6
|
+
require 'active_mocker/field'
|
7
|
+
require 'active_mocker/active_record'
|
8
|
+
require 'active_mocker/model_reader'
|
9
|
+
require 'active_mocker/schema_reader'
|
10
|
+
require 'active_mocker/active_record/schema'
|
11
|
+
require 'active_mocker/base'
|
12
|
+
require 'active_support/all'
|
13
|
+
|
14
|
+
describe ActiveMocker::Base do
|
15
|
+
|
16
|
+
let(:base_options){{}}
|
17
|
+
let(:sub_options){{schema: {path: File.expand_path('../../', __FILE__), file_reader: schema_file},
|
18
|
+
model: {path: File.expand_path('../../', __FILE__), file_reader: model_file}}}
|
19
|
+
|
20
|
+
let(:subject){ described_class.new(base_options.merge(sub_options))}
|
21
|
+
|
22
|
+
let(:mock_class){subject.mock('Person')}
|
23
|
+
|
24
|
+
let(:model_file){
|
25
|
+
StringReader.new <<-eos
|
26
|
+
class Person < ActiveRecord::Base
|
27
|
+
end
|
28
|
+
eos
|
29
|
+
}
|
30
|
+
|
31
|
+
let(:schema_file){
|
32
|
+
StringReader.new <<-eos
|
33
|
+
ActiveRecord::Schema.define(version: 20140327205359) do
|
34
|
+
|
35
|
+
create_table "people", force: true do |t|
|
36
|
+
t.integer "company_id"
|
37
|
+
t.string "first_name", limit: 128
|
38
|
+
t.string "middle_name", limit: 128
|
39
|
+
t.string "last_name", limit: 128
|
40
|
+
t.string "address_1", limit: 200
|
41
|
+
t.string "address_2", limit: 100
|
42
|
+
t.string "city", limit: 100
|
43
|
+
t.integer "state_id"
|
44
|
+
t.integer "zip_code_id"
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
eos
|
49
|
+
}
|
50
|
+
|
51
|
+
describe '#mock_class' do
|
52
|
+
|
53
|
+
it 'create a mock object after the active record' do
|
54
|
+
expect(mock_class).to eq(PersonMock)
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'private methods' do
|
58
|
+
|
59
|
+
let(:model_file){
|
60
|
+
StringReader.new <<-eos
|
61
|
+
class Person < ActiveRecord::Base
|
62
|
+
private
|
63
|
+
|
64
|
+
def bar
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
eos
|
69
|
+
}
|
70
|
+
|
71
|
+
it 'will not have private methods' do
|
72
|
+
expect{mock_class.bar}.to raise_error(NoMethodError)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#mock_of' do
|
78
|
+
|
79
|
+
it 'return the name of the class that is being mocked' do
|
80
|
+
expect(mock_class.new.mock_of).to eq 'Person'
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe 'relationships' do
|
86
|
+
|
87
|
+
let(:model_file){
|
88
|
+
StringReader.new <<-eos
|
89
|
+
class Person < ActiveRecord::Base
|
90
|
+
belongs_to :account
|
91
|
+
end
|
92
|
+
eos
|
93
|
+
}
|
94
|
+
|
95
|
+
it 'add instance methods from model relationships' do
|
96
|
+
result = mock_class.new(account: 'Account')
|
97
|
+
expect(result.account).to eq 'Account'
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'instance methods' do
|
103
|
+
|
104
|
+
let(:model_file){
|
105
|
+
StringReader.new <<-eos
|
106
|
+
class Person < ActiveRecord::Base
|
107
|
+
def bar(name, type=nil)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
eos
|
111
|
+
}
|
112
|
+
|
113
|
+
it 'will raise exception for unimplemented methods' do
|
114
|
+
expect(mock_class.new.method(:bar).parameters).to eq [[:req, :name], [:opt, :type]]
|
115
|
+
expect{mock_class.new.bar}.to raise_error ArgumentError
|
116
|
+
expect{mock_class.new.bar('foo', 'type')}.to raise_error('#bar is not Implemented for Class: PersonMock')
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'can be implemented dynamically' do
|
120
|
+
|
121
|
+
mock_class.instance_variable_set(:@bar, ->(name, type=nil){ "Now implemented with #{name} and #{type}" })
|
122
|
+
result = mock_class.new
|
123
|
+
result = result.bar('foo', 'type')
|
124
|
+
expect(result).to eq "Now implemented with foo and type"
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'can be implemented dynamically' do
|
129
|
+
|
130
|
+
mock_class.mock_instance_method(:bar) do |name, type=nil|
|
131
|
+
"Now implemented with #{name} and #{type}"
|
132
|
+
end
|
133
|
+
|
134
|
+
result = mock_class.new
|
135
|
+
result = result.bar('foo', 'type')
|
136
|
+
expect(result).to eq "Now implemented with foo and type"
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'class methods' do
|
143
|
+
|
144
|
+
let(:model_file){
|
145
|
+
StringReader.new <<-eos
|
146
|
+
class Person < ActiveRecord::Base
|
147
|
+
scope :named, -> { }
|
148
|
+
|
149
|
+
def self.class_method
|
150
|
+
end
|
151
|
+
end
|
152
|
+
eos
|
153
|
+
}
|
154
|
+
|
155
|
+
it 'will raise exception for unimplemented methods' do
|
156
|
+
expect{mock_class.class_method}.to raise_error('::class_method is not Implemented for Class: PersonMock')
|
157
|
+
end
|
158
|
+
|
159
|
+
xit 'can be implemented as follows' do
|
160
|
+
|
161
|
+
|
162
|
+
expect(mock_class.named).to eq "Now implemented"
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'loads named scopes as class method' do
|
167
|
+
expect{mock_class.named}.to raise_error('::named is not Implemented for Class: PersonMock')
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
describe '::column_names' do
|
175
|
+
|
176
|
+
|
177
|
+
it 'returns an array of column names found from the schema.rb file' do
|
178
|
+
expect(mock_class.column_names).to eq(["company_id", "first_name", "middle_name", "last_name", "address_1", "address_2", "city", "state_id", "zip_code_id"])
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
describe 'have attributes from schema' do
|
185
|
+
|
186
|
+
xit 'uses ActiveHash'
|
187
|
+
|
188
|
+
xit 'makes plain ruby class' do
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
describe 'mass_assignment' do
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
it "can pass any or all attributes from schema in initializer" do
|
199
|
+
result = mock_class.new(first_name: "Sam", last_name: 'Walton')
|
200
|
+
expect(result.first_name).to eq 'Sam'
|
201
|
+
expect(result.last_name).to eq 'Walton'
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
context 'set to false' do
|
206
|
+
|
207
|
+
it 'will fail' do
|
208
|
+
mock = described_class.new(sub_options.merge({mass_assignment: false}))
|
209
|
+
person = mock.mock("Person")
|
210
|
+
expect{
|
211
|
+
person.new(first_name: "Sam", last_name: 'Walton')
|
212
|
+
}.to raise_error ArgumentError
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
$:.unshift File.expand_path('../../', __FILE__)
|
3
|
+
require 'string_reader'
|
4
|
+
require 'file_reader'
|
5
|
+
require 'active_mocker/active_record'
|
6
|
+
require 'active_mocker/model_reader'
|
7
|
+
require 'active_mocker/reparameterize'
|
8
|
+
|
9
|
+
describe ActiveMocker::ModelReader do
|
10
|
+
|
11
|
+
let(:subject){ described_class.new({path: File.expand_path('../../', __FILE__)}).parse('Model') }
|
12
|
+
|
13
|
+
describe '#parse' do
|
14
|
+
|
15
|
+
let(:subject){ described_class.new({path: File.expand_path('../../', __FILE__)}) }
|
16
|
+
|
17
|
+
it 'takes a model name to the active_record model class' do
|
18
|
+
subject.parse('Model')
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#class_methods' do
|
24
|
+
|
25
|
+
|
26
|
+
it 'returns all public class methods' do
|
27
|
+
expect(subject.class_methods).to eq([:duper, :named])
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#instance methods' do
|
33
|
+
|
34
|
+
it 'returns all public instance methods' do
|
35
|
+
expect(subject.instance_methods).to eq([:foo, :super])
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#instance_methods_with_arguments' do
|
41
|
+
|
42
|
+
it 'returns all public instance methods' do
|
43
|
+
expect(subject.instance_methods_with_arguments).to eq([{:foo=>[[:req, :foobar], [:req, :value]]}, {:super=>[]}])
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#class_methods_with_arguments' do
|
49
|
+
|
50
|
+
it 'returns all public instance methods' do
|
51
|
+
expect(subject.class_methods_with_arguments).to eq([{:duper=>[[:req, :value], [:rest, :args]]}, {:named=>[[:req, :name], [:opt, :value], [:opt, :options]]}])
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#relationships_types' do
|
57
|
+
|
58
|
+
it '#belongs_to' do
|
59
|
+
|
60
|
+
expect(subject.relationships_types.belongs_to).to eq([[:company]])
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
it '#has_many' do
|
65
|
+
|
66
|
+
expect(subject.relationships_types.has_many).to eq([[:users]])
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
it '#has_one' do
|
71
|
+
|
72
|
+
expect(subject.relationships_types.has_one).to eq([[:account]])
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
it '#has_and_belongs_to_many' do
|
77
|
+
|
78
|
+
expect(subject.relationships_types.has_and_belongs_to_many).to eq([[:disclosure]])
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#relationships' do
|
85
|
+
|
86
|
+
it 'returns an array of relations' do
|
87
|
+
|
88
|
+
expect(subject.relationships).to eq [:users, :account, :company, :disclosure]
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
context 'inject string_reader as file_reader' do
|
96
|
+
|
97
|
+
let(:example_model){
|
98
|
+
StringReader.new(
|
99
|
+
<<-eos
|
100
|
+
class Person < ActiveRecord::Base
|
101
|
+
|
102
|
+
belongs_to :zip_code
|
103
|
+
|
104
|
+
def full_name(first_name, last_name)
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
eos
|
110
|
+
)
|
111
|
+
}
|
112
|
+
|
113
|
+
let(:subject){described_class.new({path: File.expand_path('../../', __FILE__), file_reader: example_model})}
|
114
|
+
|
115
|
+
let(:search){subject.parse('Person')}
|
116
|
+
|
117
|
+
it 'let not read a file but return a string instead to be evaluated' do
|
118
|
+
expect(search.relationships_types.belongs_to).to eq [[:zip_code]]
|
119
|
+
expect(subject.instance_methods).to eq([:full_name])
|
120
|
+
expect(subject.instance_methods_with_arguments).to eq([{:full_name=>[[:req, :first_name], [:req, :last_name]]}])
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
$:.unshift File.expand_path('../../', __FILE__)
|
3
|
+
require 'string_reader'
|
4
|
+
require 'file_reader'
|
5
|
+
require 'active_mocker/table'
|
6
|
+
require 'active_mocker/field'
|
7
|
+
require 'active_mocker/active_record/schema'
|
8
|
+
require 'active_mocker/schema_reader'
|
9
|
+
require 'active_support/all'
|
10
|
+
|
11
|
+
describe ActiveMocker::SchemaReader do
|
12
|
+
|
13
|
+
let(:example_schema){
|
14
|
+
StringReader.new(
|
15
|
+
<<-eos
|
16
|
+
ActiveRecord::Schema.define(version: 20140327205359) do
|
17
|
+
|
18
|
+
create_table "people", force: true do |t|
|
19
|
+
t.integer "company_id"
|
20
|
+
t.string "first_name", limit: 128
|
21
|
+
t.string "middle_name", limit: 128
|
22
|
+
t.string "last_name", limit: 128
|
23
|
+
t.string "address_1", limit: 200
|
24
|
+
t.string "address_2", limit: 100
|
25
|
+
t.string "city", limit: 100
|
26
|
+
t.integer "state_id"
|
27
|
+
t.integer "zip_code_id"
|
28
|
+
t.string "title", limit: 150
|
29
|
+
t.string "department", limit: 150
|
30
|
+
t.string "person_email", limit: 150
|
31
|
+
t.string "work_phone", limit: 20
|
32
|
+
t.string "cell_phone", limit: 20
|
33
|
+
t.string "home_phone", limit: 20
|
34
|
+
t.string "fax", limit: 20
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
create_table "zip_codes", force: true do |t|
|
39
|
+
t.string "zip_code", limit: 9
|
40
|
+
t.integer "state_id"
|
41
|
+
t.integer "cola_by_fip_id"
|
42
|
+
t.string "city_name", limit: 100
|
43
|
+
t.string "County_name", limit: 100
|
44
|
+
t.decimal "City_Latitude", precision: 8, scale: 4
|
45
|
+
t.decimal "City_Longitude", precision: 8, scale: 4
|
46
|
+
end
|
47
|
+
|
48
|
+
add_index "zip_codes", ["zip_code"], name: "index_zip_codes_on_zip_code", unique: true, using: :btree
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
eos
|
53
|
+
)
|
54
|
+
}
|
55
|
+
|
56
|
+
context 'inject string_reader as file_reader' do
|
57
|
+
|
58
|
+
let(:subject){described_class.new({path: File.expand_path('../../', __FILE__), file_reader: example_schema})}
|
59
|
+
|
60
|
+
let(:search){subject.search('people')}
|
61
|
+
|
62
|
+
it 'let not read a file but return a string instead to be evaluated' do
|
63
|
+
people = subject.search('people')
|
64
|
+
expect(people.name).to eq 'people'
|
65
|
+
expect(people.fields[1].to_h).to eq({:name=>"first_name", :type=>:string, :options=>[{:limit=>128}]})
|
66
|
+
expect(subject.search('zip_codes').name).to eq 'zip_codes'
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'reads from file' do
|
72
|
+
|
73
|
+
let(:subject){described_class.new({path: File.expand_path('../../', __FILE__)})}
|
74
|
+
|
75
|
+
|
76
|
+
describe '#search' do
|
77
|
+
|
78
|
+
it 'takes a table name and will return its attributes' do
|
79
|
+
described_class.new({path: File.expand_path('../../', __FILE__)}).search("people")
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
let(:people_search){subject.search("people")}
|
85
|
+
|
86
|
+
describe '#column_names' do
|
87
|
+
|
88
|
+
it 'returns an array of columns from the schema.rb' do
|
89
|
+
expect(people_search.name).to eq 'people'
|
90
|
+
expect(people_search.column_names).to eq ["company_id", "first_name", "middle_name", "last_name", "address_1", "address_2", "city", "state_id", "zip_code_id", "title", "department", "person_email", "work_phone", "cell_phone", "home_phone", "fax", "user_id_assistant", "birth_date", "needs_review", "created_at", "updated_at"]
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '#fields' do
|
96
|
+
|
97
|
+
it 'returns all fields from schema' do
|
98
|
+
expect(people_search.fields.first.to_h).to eq({:name=>"company_id", :type=>:integer, :options=>[]})
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#name' do
|
104
|
+
|
105
|
+
it 'returns the name of the table' do
|
106
|
+
expect(people_search.name).to eq("people")
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'returns an exception if table not found in schema.rb' do
|
113
|
+
expect{
|
114
|
+
described_class.new(
|
115
|
+
{path: File.expand_path('../../', __FILE__)}
|
116
|
+
).search("disclosures")
|
117
|
+
}.to raise_error 'disclosures table not found.'
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
end
|