pretentious 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,292 @@
1
+ class Pretentious::Deconstructor
2
+
3
+ class Reference
4
+ attr_accessor :tree
5
+
6
+ def initialize(tree)
7
+ @tree = tree
8
+ end
9
+ end
10
+
11
+ def dfs_array(arr, refs)
12
+ value = []
13
+ arr.each { |v|
14
+ if Pretentious::Deconstructor.is_primitive?(v)
15
+ value << v
16
+ elsif v.is_a? Hash
17
+ value << dfs_hash(v, refs)
18
+ elsif v.is_a? Array
19
+ value << dfs_array(v, refs)
20
+ elsif v.is_a? Reference
21
+ refs << v.tree[:id]
22
+ value << Reference.new(dfs(v.tree))
23
+ elsif value << v
24
+ end
25
+ }
26
+ value
27
+ end
28
+
29
+ def dfs_hash(hash, refs)
30
+ value = {}
31
+ hash.each { |k, v|
32
+ if Pretentious::Deconstructor.is_primitive?(v)
33
+ value[k] = v
34
+ elsif v.is_a? Hash
35
+ value[k] = dfs_hash(v, refs)
36
+ elsif v.is_a? Array
37
+ value[k] = dfs_array(v, refs)
38
+ elsif v.is_a? Reference
39
+ refs << v.tree[:id]
40
+ value[k] = Reference.new(dfs(v.tree))
41
+ else
42
+ value[k] = v
43
+ end
44
+ }
45
+ value
46
+ end
47
+
48
+ def dfs(tree)
49
+ if !tree.is_a? Hash
50
+ value = tree
51
+ definition = {id: value.object_id, class: tree.class, value: value}
52
+ unless (@dependencies.include? value.object_id)
53
+ @dependencies[value.object_id] = definition
54
+ @declaration_order << definition
55
+ end
56
+ value.object_id
57
+ else
58
+ ref = []
59
+
60
+ definition = {id: tree[:id], class: tree[:class]}
61
+
62
+ if tree[:class] == Hash
63
+ definition[:value] = dfs_hash(tree[:composition], ref)
64
+ elsif tree[:class] == Array
65
+ definition[:value] = dfs_array(tree[:composition], ref)
66
+ elsif tree[:composition].is_a? Array
67
+ tree[:composition].each { |t|
68
+ ref << dfs(t)
69
+ }
70
+ else
71
+ ref << dfs(tree[:composition])
72
+ end
73
+
74
+ definition[:ref] = ref
75
+
76
+ unless (@dependencies.include? tree[:id])
77
+ @declaration_order << definition
78
+ @dependencies[tree[:id]] = definition
79
+ end
80
+ tree[:id]
81
+ end
82
+ end
83
+
84
+ def deconstruct(*target_objects)
85
+
86
+ @declaration_order = []
87
+ @dependencies = {}
88
+
89
+ target_objects.each { |target_object|
90
+ tree = build_tree target_object
91
+ dfs(tree)
92
+ }
93
+
94
+ {declaration: @declaration_order, dependency: @dependencies}
95
+ end
96
+
97
+ def deconstruct_to_ruby(indentation_level = 0, variable_map = {}, declared_names = {}, *target_objects)
98
+ output_buffer = ""
99
+ indentation = ""
100
+
101
+ indentation_level.times {
102
+ indentation << ' '
103
+ }
104
+
105
+ target_objects.each { |target_object|
106
+ variable_map.merge!(target_object._variable_map) if target_object.methods.include?(:_variable_map) && !target_object._variable_map.nil?
107
+ }
108
+
109
+ declarations, dependencies = deconstruct *target_objects
110
+ declarations[:declaration].each do |d|
111
+
112
+ var_name = Pretentious::Deconstructor.pick_name(variable_map, d[:id], declared_names)
113
+ output_buffer << "#{indentation}#{var_name} = #{construct(d, variable_map, declared_names)}\n"
114
+
115
+ end
116
+
117
+ output_buffer
118
+ end
119
+
120
+ def self.is_primitive?(value)
121
+ value.is_a?(String) || value.is_a?(Fixnum) || value.is_a?(TrueClass) || value.is_a?(FalseClass) ||
122
+ value.is_a?(NilClass) || value.is_a?(Symbol)
123
+ end
124
+
125
+ def deconstruct_array(array)
126
+ composition = []
127
+ array.each { |v|
128
+ if (Pretentious::Deconstructor.is_primitive?(v))
129
+ composition << v
130
+ elsif v.is_a? Hash
131
+ composition << deconstruct_hash(v)
132
+ elsif v.is_a? Array
133
+ composition << deconstruct_array(v)
134
+ else
135
+ composition << Reference.new(build_tree(v))
136
+ end
137
+ }
138
+ composition
139
+ end
140
+
141
+ def deconstruct_hash(hash)
142
+ composition = {}
143
+ hash.each { |k, v|
144
+ if (Pretentious::Deconstructor.is_primitive?(v))
145
+ composition[k] = v
146
+ elsif v.is_a? Hash
147
+ composition[k] = deconstruct_hash(v)
148
+ elsif v.is_a? Array
149
+ composition[k] = deconstruct_array(v)
150
+ else
151
+ composition[k] = Reference.new(build_tree(v))
152
+ end
153
+ }
154
+ composition
155
+ end
156
+
157
+ def get_test_class(target_object)
158
+ target_object.respond_to?(:test_class) ? target_object.test_class : target_object.class
159
+ end
160
+
161
+ #creates a tree on how the object was created
162
+ def build_tree(target_object)
163
+
164
+ tree = {class: get_test_class(target_object), id: target_object.object_id, composition: []}
165
+ if (target_object.is_a? Array)
166
+ tree[:composition] = deconstruct_array(target_object)
167
+ elsif target_object.is_a? Hash
168
+ tree[:composition] = deconstruct_hash(target_object)
169
+ elsif target_object.methods.include? :_get_init_arguments
170
+
171
+ args = target_object._get_init_arguments
172
+ unless args.nil?
173
+ args[:params].each { |p|
174
+ tree[:composition] << build_tree(p)
175
+ }
176
+
177
+ else
178
+ tree[:composition] = target_object
179
+ end
180
+ else
181
+ tree[:composition] = target_object
182
+ end
183
+ tree
184
+ end
185
+
186
+ def self.pick_name(variable_map, object_id, declared_names = {})
187
+ var_name = "var_#{object_id}"
188
+
189
+ object_id_to_declared_names = {}
190
+
191
+ declared_names.each { |k,v|
192
+ object_id_to_declared_names[v[:object_id]] = k
193
+ } if declared_names
194
+
195
+ #return immediately if already mapped
196
+ return object_id_to_declared_names[object_id] if (object_id_to_declared_names.include? object_id)
197
+
198
+ if (!variable_map.nil? && variable_map.include?(object_id))
199
+
200
+ candidate_name = variable_map[object_id].to_s
201
+
202
+ if !declared_names.include?(candidate_name)
203
+ var_name = candidate_name
204
+ declared_names[candidate_name] = {count: 1, object_id: object_id}
205
+ else
206
+
207
+ if (declared_names[candidate_name][:object_id] == object_id)
208
+ var_name = candidate_name
209
+ else
210
+ new_name = "#{candidate_name}_#{declared_names[candidate_name][:count]}"
211
+ var_name = "#{new_name}"
212
+
213
+ declared_names[candidate_name][:count]+=1
214
+ declared_names[new_name] = {count: 1, object_id: object_id}
215
+ end
216
+
217
+ end
218
+ end
219
+
220
+ var_name
221
+ end
222
+
223
+ private
224
+
225
+
226
+ def output_array(arr, variable_map, declared_names)
227
+ output_buffer = '['
228
+ array_elements = []
229
+ arr.each { |v|
230
+ value = Pretentious::value_ize(v, variable_map, declared_names)
231
+ if (v.is_a? Hash)
232
+ value = output_hash(v, variable_map, declared_names)
233
+ elsif (v.is_a? Array)
234
+ value = output_array(v, variable_map, declared_names)
235
+ elsif (v.is_a? Reference)
236
+ value = Pretentious::Deconstructor.pick_name(variable_map, v.tree, declared_names)
237
+ end
238
+ array_elements << value
239
+ }
240
+ output_buffer << array_elements.join(', ')
241
+ output_buffer << ']'
242
+ output_buffer
243
+ end
244
+
245
+ def output_hash(hash, variable_map, declared_names)
246
+ output_buffer = '{'
247
+ hash_elements = []
248
+ hash.each { |k, v|
249
+ value = Pretentious::value_ize(v, variable_map, declared_names)
250
+ if (v.is_a? Hash)
251
+ value = output_hash(v, variable_map, declared_names)
252
+ elsif (v.is_a? Array)
253
+ value = output_array(v, variable_map, declared_names)
254
+ elsif (v.is_a? Reference)
255
+ value = Pretentious::Deconstructor.pick_name(variable_map, v.tree, declared_names)
256
+ end
257
+
258
+ if (k.is_a? Symbol)
259
+ hash_elements << "#{k}: #{value}"
260
+ else
261
+ hash_elements << "#{Pretentious::value_ize(k, variable_map, declared_names)} => #{value}"
262
+ end
263
+ }
264
+ output_buffer << hash_elements.join(', ')
265
+ output_buffer << '}'
266
+ output_buffer
267
+ end
268
+
269
+ def construct(definition, variable_map, declared_names)
270
+ if (definition[:value])
271
+ if (definition[:value].is_a? Hash)
272
+ output_hash(definition[:value], variable_map, declared_names)
273
+ elsif (definition[:value].is_a? Array)
274
+ output_array(definition[:value], variable_map, declared_names)
275
+ else
276
+ Pretentious::value_ize(definition[:value], variable_map, declared_names)
277
+ end
278
+ else
279
+ params = []
280
+ if (definition[:ref].size > 0)
281
+ definition[:ref].each do |v|
282
+ params << Pretentious::Deconstructor.pick_name(variable_map,v, declared_names)
283
+ end
284
+ "#{definition[:class]}.new(#{params.join(', ')})"
285
+ else
286
+ "#{definition[:class]}.new"
287
+ end
288
+
289
+ end
290
+ end
291
+
292
+ end
@@ -0,0 +1,215 @@
1
+ class Pretentious::RspecGenerator
2
+
3
+ def initialize(options = {})
4
+ @deconstructor = Pretentious::Deconstructor.new
5
+ indentation_count = options[:indentation] || 2
6
+ @output_buffer = ""
7
+ @_indentation = ""
8
+ indentation_count.times do
9
+ @_indentation << " "
10
+ end
11
+ end
12
+
13
+ def indentation(level)
14
+ buffer = ""
15
+ level.times do
16
+ buffer << @_indentation
17
+ end
18
+ buffer
19
+ end
20
+
21
+ def buffer(line, level = 0)
22
+ @output_buffer << "#{indentation(level)}#{line}\n"
23
+ end
24
+
25
+ def whitespace(level = 0)
26
+ @output_buffer << "#{indentation(level)}\n"
27
+ end
28
+
29
+ def begin_spec(test_class)
30
+ buffer("require 'spec_helper'")
31
+ whitespace
32
+ buffer("RSpec.describe #{test_class.name} do")
33
+ whitespace
34
+ end
35
+
36
+ def end_spec
37
+ buffer("end")
38
+ end
39
+
40
+ def output
41
+ @output_buffer
42
+ end
43
+
44
+ def generate(test_instance, instance_count)
45
+ if (test_instance.is_a? Class)
46
+ #class methods
47
+ class_method_calls = test_instance.method_calls_by_method
48
+ generate_specs("#{test_instance.test_class.name}::",test_instance.test_class.name, class_method_calls, test_instance.let_variables)
49
+ else
50
+ buffer("context 'Scenario #{instance_count}' do",1)
51
+
52
+ buffer("before do",2)
53
+ whitespace
54
+ args = test_instance._init_arguments[:params]
55
+ declarations = {}
56
+ buffer(declare_dependencies(args, test_instance.init_let_variables, 3 * @_indentation.length, declarations))
57
+ if (args.size > 0)
58
+ buffer("@fixture = #{test_instance.test_class.name}.new(#{params_generator(args, test_instance.init_let_variables, declarations)})",3)
59
+ else
60
+ buffer("@fixture = #{test_instance.test_class.name}.new",3)
61
+ end
62
+ whitespace
63
+ buffer("end",2)
64
+ whitespace
65
+
66
+ method_calls = test_instance.method_calls_by_method
67
+
68
+ generate_specs("#{test_instance.test_class.name}#","@fixture",method_calls, test_instance.let_variables)
69
+
70
+ buffer('end',1)
71
+ whitespace
72
+ end
73
+
74
+ end
75
+
76
+ private
77
+
78
+ def generate_expectation(fixture, method, let_variables, declarations, params, result)
79
+ statement = if params.size > 0
80
+ "#{fixture}.#{method.to_s}(#{params_generator(params, let_variables, declarations)})"
81
+ else
82
+ "#{fixture}.#{method.to_s}"
83
+ end
84
+
85
+ if (result.kind_of? Exception)
86
+ buffer("expect { #{statement} }.to #{pick_matcher(result)}",3)
87
+ else
88
+ buffer("expect( #{statement} ).to #{pick_matcher(result)}",3)
89
+ end
90
+ end
91
+
92
+ def generate_specs(context_prefix, fixture, method_calls, let_variables)
93
+ buffer("it 'should pass current expectations' do",2)
94
+ whitespace
95
+ declaration = {}
96
+ #collect all params
97
+ params_collection = []
98
+
99
+ method_calls.each_key do |k|
100
+ info_blocks_arr = method_calls[k]
101
+ info_blocks_arr.each do |block|
102
+ params_collection = params_collection | block[:params]
103
+ if (!Pretentious::Deconstructor.is_primitive?(block[:result]) && !block[:result].kind_of?(Exception))
104
+ params_collection << block[:result]
105
+ end
106
+ end
107
+ end
108
+
109
+ buffer(declare_dependencies(params_collection, let_variables, 3 * @_indentation.length, declaration))
110
+
111
+ method_calls.each_key do |k|
112
+ info_blocks_arr = method_calls[k]
113
+
114
+ info_blocks_arr.each do |block|
115
+
116
+ buffer("# #{context_prefix}#{k} when passed #{desc_params(block)} should return #{block[:result]}", 3)
117
+ generate_expectation(fixture, k, let_variables, declaration, block[:params], block[:result])
118
+
119
+ whitespace
120
+ end
121
+
122
+
123
+ end
124
+ buffer("end",2)
125
+ end
126
+
127
+ #def generate_specs(context_prefix, fixture, method_calls, let_variables)
128
+ # method_calls.each_key do |k|
129
+ # info_blocks_arr = method_calls[k]
130
+ #
131
+ # buffer("context \"#{context_prefix}#{k}\" do", 1)
132
+ #
133
+ # whitespace
134
+ # info_blocks_arr.each do |block|
135
+ # buffer("it '#{desc_params(block)} returns #{block[:result]}' do",2)
136
+ # whitespace
137
+ # if block[:params].size > 0
138
+ # buffer(declare_dependencies(block[:params], let_variables, 3))
139
+ # buffer("expect(#{fixture}.#{k.to_s}(#{params_generator(block[:params], let_variables)})).to #{pick_matcher(block[:result])}",3)
140
+ # else
141
+ # buffer("expect(#{fixture}.#{k.to_s}).to #{pick_matcher(block[:result])}",3)
142
+ # end
143
+ # whitespace
144
+ # buffer("end",2)
145
+ # whitespace
146
+ # end
147
+ #
148
+ # buffer("end", 1)
149
+ # whitespace
150
+ # end
151
+ #end
152
+
153
+ def pick_matcher(result)
154
+ if result.is_a? TrueClass
155
+ 'be true'
156
+ elsif result.is_a? FalseClass
157
+ 'be false'
158
+ elsif result.nil?
159
+ 'be_nil'
160
+ elsif result.kind_of? Exception
161
+ 'raise_error'
162
+ else
163
+ "eq(#{Pretentious::value_ize(result, nil, nil)})"
164
+ end
165
+ end
166
+
167
+
168
+
169
+ def desc_params(block)
170
+ params = []
171
+ args = block[:params]
172
+ names = block[:names]
173
+ n = 0
174
+ #puts args.inspect
175
+ return "" if args.nil?
176
+
177
+ args.each do |arg|
178
+ param_name = names[n][1].to_s
179
+ arg_value = (arg.is_a? String) ? "#{arg.dump}" : "#{arg.to_s}"
180
+ if (param_name.empty?)
181
+ params << "#{arg_value}"
182
+ else
183
+ params << "#{param_name} = #{arg_value}"
184
+ end
185
+
186
+ n+=1
187
+ end
188
+ params.join(" ,")
189
+ end
190
+
191
+ def declare_dependencies(args, variable_map, level, declarations)
192
+ deconstructor = Pretentious::Deconstructor.new
193
+
194
+ args = remove_primitives(args, variable_map)
195
+ deconstructor.deconstruct_to_ruby(level, variable_map, declarations, *args)
196
+ end
197
+
198
+ def remove_primitives(args, let_lookup)
199
+ args.select { |a| let_lookup.include?(a.object_id) || !Pretentious::Deconstructor.is_primitive?(a) }
200
+ end
201
+
202
+ def params_generator(args, let_variables, declared_names)
203
+ params = []
204
+ args.each do |arg|
205
+ if (!let_variables.nil? && let_variables[arg.object_id])
206
+ params << Pretentious::Deconstructor.pick_name(let_variables, arg.object_id, declared_names)
207
+ else
208
+ params << Pretentious::value_ize(arg, let_variables, declared_names)
209
+ end
210
+
211
+ end
212
+ params.join(", ")
213
+ end
214
+
215
+ end