pretentious 0.0.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.
@@ -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