active_mocker 0.1.1
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/.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
|