gauge-ruby 0.4.2 → 0.4.3

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.
@@ -18,7 +18,7 @@
18
18
  require_relative 'messages.pb'
19
19
  require_relative 'executor'
20
20
  require_relative 'table'
21
- Dir[File.join(File.dirname(__FILE__), 'processors/*.rb')].each {|file| require file }
21
+ Dir[File.join(File.dirname(__FILE__), 'processors/*.rb')].each {|file| require file}
22
22
 
23
23
  module Gauge
24
24
  # @api private
@@ -43,6 +43,10 @@ module Gauge
43
43
  @processors[Messages::Message::MessageType::ScenarioDataStoreInit] = method(:process_datastore_init)
44
44
  @processors[Messages::Message::MessageType::StepNameRequest] = method(:process_step_name_request)
45
45
  @processors[Messages::Message::MessageType::RefactorRequest] = method(:refactor_step)
46
+ @processors[Messages::Message::MessageType::CacheFileRequest] = method(:process_cache_file_request)
47
+ @processors[Messages::Message::MessageType::StepPositionsRequest] = method(:process_step_positions_request)
48
+ @processors[Messages::Message::MessageType::ImplementationFileListRequest] = method(:process_implementation_file_list_request)
49
+ @processors[Messages::Message::MessageType::StubImplementationCodeRequest] = method(:process_stub_implementation_code_request)
46
50
 
47
51
  def self.is_valid_message(message)
48
52
  return @processors.has_key? message.messageType
@@ -33,10 +33,19 @@ module Gauge
33
33
  class SuiteDataStoreInitRequest < ::ProtocolBuffers::Message; end
34
34
  class ParameterPosition < ::ProtocolBuffers::Message; end
35
35
  class RefactorRequest < ::ProtocolBuffers::Message; end
36
+ class FileChanges < ::ProtocolBuffers::Message; end
36
37
  class RefactorResponse < ::ProtocolBuffers::Message; end
37
38
  class StepNameRequest < ::ProtocolBuffers::Message; end
38
39
  class StepNameResponse < ::ProtocolBuffers::Message; end
39
40
  class UnsupportedMessageResponse < ::ProtocolBuffers::Message; end
41
+ class CacheFileRequest < ::ProtocolBuffers::Message; end
42
+ class StepPositionsRequest < ::ProtocolBuffers::Message; end
43
+ class StepPositionsResponse < ::ProtocolBuffers::Message; end
44
+ class ImplementationFileListRequest < ::ProtocolBuffers::Message; end
45
+ class ImplementationFileListResponse < ::ProtocolBuffers::Message; end
46
+ class StubImplementationCodeRequest < ::ProtocolBuffers::Message; end
47
+ class TextDiff < ::ProtocolBuffers::Message; end
48
+ class FileDiff < ::ProtocolBuffers::Message; end
40
49
  class Message < ::ProtocolBuffers::Message; end
41
50
 
42
51
  class KillProcessRequest < ::ProtocolBuffers::Message
@@ -129,6 +138,8 @@ module Gauge
129
138
 
130
139
  optional ::Gauge::Messages::ExecuteStepRequest, :step, 1
131
140
  optional :bool, :isFailed, 2
141
+ optional :string, :stackTrace, 3
142
+ optional :string, :errorMessage, 4
132
143
  end
133
144
 
134
145
  class ExecuteStepRequest < ::ProtocolBuffers::Message
@@ -145,6 +156,7 @@ module Gauge
145
156
 
146
157
  optional :string, :stepText, 1
147
158
  optional :int32, :numberOfParameters, 2
159
+ optional ::Gauge::Messages::ProtoStepValue, :stepValue, 3
148
160
  end
149
161
 
150
162
  class StepValidateResponse < ::ProtocolBuffers::Message
@@ -165,6 +177,7 @@ module Gauge
165
177
  optional :bool, :isValid, 1
166
178
  optional :string, :errorMessage, 2
167
179
  optional ::Gauge::Messages::StepValidateResponse::ErrorType, :errorType, 3
180
+ optional :string, :suggestion, 4
168
181
  end
169
182
 
170
183
  class SuiteExecutionResult < ::ProtocolBuffers::Message
@@ -212,6 +225,14 @@ module Gauge
212
225
  optional ::Gauge::Messages::ProtoStepValue, :oldStepValue, 1
213
226
  optional ::Gauge::Messages::ProtoStepValue, :newStepValue, 2
214
227
  repeated ::Gauge::Messages::ParameterPosition, :paramPositions, 3
228
+ optional :bool, :saveChanges, 4
229
+ end
230
+
231
+ class FileChanges < ::ProtocolBuffers::Message
232
+ set_fully_qualified_name "gauge.messages.FileChanges"
233
+
234
+ optional :string, :fileName, 1
235
+ optional :string, :fileContent, 2
215
236
  end
216
237
 
217
238
  class RefactorResponse < ::ProtocolBuffers::Message
@@ -220,6 +241,7 @@ module Gauge
220
241
  optional :bool, :success, 1
221
242
  optional :string, :error, 2
222
243
  repeated :string, :filesChanged, 3
244
+ repeated ::Gauge::Messages::FileChanges, :fileChanges, 4
223
245
  end
224
246
 
225
247
  class StepNameRequest < ::ProtocolBuffers::Message
@@ -234,6 +256,8 @@ module Gauge
234
256
  optional :bool, :isStepPresent, 1
235
257
  repeated :string, :stepName, 2
236
258
  optional :bool, :hasAlias, 3
259
+ optional :string, :fileName, 4
260
+ optional ::Gauge::Messages::Span, :span, 5
237
261
  end
238
262
 
239
263
  class UnsupportedMessageResponse < ::ProtocolBuffers::Message
@@ -242,6 +266,70 @@ module Gauge
242
266
  optional :string, :message, 1
243
267
  end
244
268
 
269
+ class CacheFileRequest < ::ProtocolBuffers::Message
270
+ set_fully_qualified_name "gauge.messages.CacheFileRequest"
271
+
272
+ optional :string, :content, 1
273
+ optional :string, :filePath, 2
274
+ optional :bool, :isClosed, 3
275
+ end
276
+
277
+ class StepPositionsRequest < ::ProtocolBuffers::Message
278
+ set_fully_qualified_name "gauge.messages.StepPositionsRequest"
279
+
280
+ optional :string, :filePath, 1
281
+ end
282
+
283
+ class StepPositionsResponse < ::ProtocolBuffers::Message
284
+ # forward declarations
285
+ class StepPosition < ::ProtocolBuffers::Message; end
286
+
287
+ set_fully_qualified_name "gauge.messages.StepPositionsResponse"
288
+
289
+ # nested messages
290
+ class StepPosition < ::ProtocolBuffers::Message
291
+ set_fully_qualified_name "gauge.messages.StepPositionsResponse.StepPosition"
292
+
293
+ optional :string, :stepValue, 1
294
+ optional ::Gauge::Messages::Span, :span, 2
295
+ end
296
+
297
+ repeated ::Gauge::Messages::StepPositionsResponse::StepPosition, :stepPositions, 1
298
+ optional :string, :error, 2
299
+ end
300
+
301
+ class ImplementationFileListRequest < ::ProtocolBuffers::Message
302
+ set_fully_qualified_name "gauge.messages.ImplementationFileListRequest"
303
+
304
+ end
305
+
306
+ class ImplementationFileListResponse < ::ProtocolBuffers::Message
307
+ set_fully_qualified_name "gauge.messages.ImplementationFileListResponse"
308
+
309
+ repeated :string, :implementationFilePaths, 1
310
+ end
311
+
312
+ class StubImplementationCodeRequest < ::ProtocolBuffers::Message
313
+ set_fully_qualified_name "gauge.messages.StubImplementationCodeRequest"
314
+
315
+ optional :string, :implementationFilePath, 1
316
+ repeated :string, :codes, 2
317
+ end
318
+
319
+ class TextDiff < ::ProtocolBuffers::Message
320
+ set_fully_qualified_name "gauge.messages.TextDiff"
321
+
322
+ optional ::Gauge::Messages::Span, :span, 1
323
+ optional :string, :content, 2
324
+ end
325
+
326
+ class FileDiff < ::ProtocolBuffers::Message
327
+ set_fully_qualified_name "gauge.messages.FileDiff"
328
+
329
+ optional :string, :filePath, 1
330
+ repeated ::Gauge::Messages::TextDiff, :textDiffs, 2
331
+ end
332
+
245
333
  class Message < ::ProtocolBuffers::Message
246
334
  # forward declarations
247
335
 
@@ -275,6 +363,13 @@ module Gauge
275
363
  RefactorRequest = 21
276
364
  RefactorResponse = 22
277
365
  UnsupportedMessageResponse = 23
366
+ CacheFileRequest = 24
367
+ StepPositionsRequest = 25
368
+ StepPositionsResponse = 26
369
+ ImplementationFileListRequest = 27
370
+ ImplementationFileListResponse = 28
371
+ StubImplementationCodeRequest = 29
372
+ FileDiff = 30
278
373
  end
279
374
 
280
375
  set_fully_qualified_name "gauge.messages.Message"
@@ -305,6 +400,13 @@ module Gauge
305
400
  optional ::Gauge::Messages::RefactorRequest, :refactorRequest, 24
306
401
  optional ::Gauge::Messages::RefactorResponse, :refactorResponse, 25
307
402
  optional ::Gauge::Messages::UnsupportedMessageResponse, :unsupportedMessageResponse, 26
403
+ optional ::Gauge::Messages::CacheFileRequest, :cacheFileRequest, 27
404
+ optional ::Gauge::Messages::StepPositionsRequest, :stepPositionsRequest, 28
405
+ optional ::Gauge::Messages::StepPositionsResponse, :stepPositionsResponse, 29
406
+ optional ::Gauge::Messages::ImplementationFileListRequest, :implementationFileListRequest, 30
407
+ optional ::Gauge::Messages::ImplementationFileListResponse, :implementationFileListResponse, 31
408
+ optional ::Gauge::Messages::StubImplementationCodeRequest, :stubImplementationCodeRequest, 32
409
+ optional ::Gauge::Messages::FileDiff, :fileDiff, 33
308
410
  end
309
411
 
310
412
  end
@@ -1,4 +1,4 @@
1
- # Copyright 2015 ThoughtWorks, Inc.
1
+ # Copyright 2018 ThoughtWorks, Inc.
2
2
 
3
3
  # This file is part of Gauge-Ruby.
4
4
 
@@ -19,39 +19,44 @@ require_relative 'configuration'
19
19
  module Gauge
20
20
  # @api private
21
21
  class MethodCache
22
- ["before_step", "after_step", "before_spec", "after_spec", "before_scenario", "after_scenario", "before_suite", "after_suite"].each { |hook|
23
- define_singleton_method "add_#{hook}_hook" do |options={}, &block|
22
+ %w[before_step after_step before_spec after_spec before_scenario after_scenario before_suite after_suite].each { |hook|
23
+ define_singleton_method "add_#{hook}_hook" do |options = {}, &block|
24
24
  options = {operator: "AND", tags: []}.merge options
25
- self.class_variable_get("@@#{hook}_hooks").push :block=> block, :options=> options
25
+ class_variable_get("@@#{hook}_hooks").push :block => block, :options => options
26
26
  end
27
27
  define_singleton_method "get_#{hook}_hooks" do
28
- self.class_variable_get("@@#{hook}_hooks")
28
+ class_variable_get("@@#{hook}_hooks")
29
29
  end
30
30
  }
31
31
 
32
32
  def self.clear_hooks(hook)
33
- self.class_variable_get("@@#{hook}_hooks").clear
33
+ class_variable_get("@@#{hook}_hooks").clear
34
34
  end
35
35
 
36
- def self.add_step(parameterized_step_text, &block)
37
- @@steps_map[parameterized_step_text] = @@steps_map[parameterized_step_text] || []
38
- @@steps_map[parameterized_step_text].push(block)
36
+ def self.clear()
37
+ @@steps_map.clear
39
38
  end
40
39
 
41
- def self.get_step(parameterized_step_text)
42
- @@steps_map[parameterized_step_text][0]
40
+ def self.add_step(step_value, step_info)
41
+ if @@steps_map.key? step_value
42
+ @@steps_map[step_value][:locations].push(step_info[:location])
43
+ else
44
+ @@steps_map[step_value] = {
45
+ locations: [step_info[:location]],
46
+ block: step_info[:block],
47
+ step_text: step_info[:step_text],
48
+ recoverable: step_info[:recoverable]
49
+ }
50
+ end
43
51
  end
44
52
 
45
- def self.get_steps(parameterized_step_text)
46
- @@steps_map[parameterized_step_text] || []
53
+ def self.get_step_info(step_value)
54
+ @@steps_map[step_value]
47
55
  end
48
56
 
49
- def self.add_step_text(parameterized_step_text, step_text)
50
- @@steps_text_map[parameterized_step_text] = step_text
51
- end
52
57
 
53
- def self.get_step_text(parameterized_step_text)
54
- @@steps_text_map[parameterized_step_text]
58
+ def self.get_step_text(step_value)
59
+ @@steps_map[step_value][:step_text]
55
60
  end
56
61
 
57
62
  def self.add_step_alias(*step_texts)
@@ -63,26 +68,43 @@ module Gauge
63
68
  end
64
69
 
65
70
  def self.valid_step?(step)
66
- @@steps_map.has_key? step
71
+ @@steps_map.key? step
67
72
  end
68
73
 
69
74
  def self.all_steps
70
- @@steps_text_map.values
75
+ @@steps_map.values.map { |si| si[:step_text] }
76
+ end
77
+
78
+ def self.recoverable?(step_value)
79
+ @@steps_map[step_value][:recoverable]
71
80
  end
72
81
 
73
- def self.is_recoverable?(parameterized_step_text)
74
- @@recoverable_steps.include? parameterized_step_text
82
+ def self.remove_steps(file)
83
+ @@steps_map.each_pair do |step, info|
84
+ l = info[:locations].reject { |loc| File.identical? loc[:file], file }
85
+ l.empty? ? @@steps_map.delete(step) : @@steps_map[step][:locations] = l
86
+ end
87
+ end
88
+
89
+ def self.multiple_implementation?(step_value)
90
+ @@steps_map[step_value][:locations].length > 1
75
91
  end
76
92
 
77
- def self.set_recoverable(parameterized_step_text)
78
- @@recoverable_steps.push parameterized_step_text
93
+ def self.step_positions(file)
94
+ step_positions = []
95
+ @@steps_map.each_pair do |step, info|
96
+ info[:locations].each do |location|
97
+ if location[:file] == file
98
+ step_positions.push({stepValue: step, span: location[:span]})
99
+ end
100
+ end
101
+ end
102
+ step_positions
79
103
  end
80
104
 
81
105
  private
82
106
  @@steps_map = Hash.new
83
- @@steps_text_map = Hash.new
84
107
  @@steps_with_aliases = []
85
- @@recoverable_steps = []
86
108
  @@before_suite_hooks = []
87
109
  @@after_suite_hooks = []
88
110
  @@before_spec_hooks = []
@@ -0,0 +1,43 @@
1
+ # Copyright 2018 ThoughtWorks, Inc.
2
+
3
+ # This file is part of Gauge-Ruby.
4
+
5
+ # Gauge-Ruby is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # Gauge-Ruby is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Gauge-Ruby. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require_relative '../static_loader'
19
+ require_relative '../method_cache'
20
+ module Gauge
21
+ # @api private
22
+ module Processors
23
+ def process_cache_file_request(message)
24
+ if !message.cacheFileRequest.isClosed
25
+ ast = CodeParser.code_to_ast(message.cacheFileRequest.content)
26
+ StaticLoader.reload_steps(message.cacheFileRequest.filePath, ast)
27
+ else
28
+ load_from_disk message.cacheFileRequest.filePath
29
+ end
30
+ nil
31
+ end
32
+
33
+ def load_from_disk(f)
34
+ if File.file? f
35
+ ast = CodeParser.code_to_ast File.read(f)
36
+ StaticLoader.reload_steps(f, ast)
37
+ else
38
+ StaticLoader.remove_steps(f)
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -29,7 +29,7 @@ module Gauge
29
29
  begin
30
30
  Executor.execute_step step_text, args
31
31
  rescue Exception => e
32
- return handle_failure message, e, time_elapsed_since(start_time), MethodCache.is_recoverable?(step_text)
32
+ return handle_failure message, e, time_elapsed_since(start_time), MethodCache.recoverable?(step_text)
33
33
  end
34
34
  handle_pass message, time_elapsed_since(start_time)
35
35
  end
@@ -37,24 +37,35 @@ module Gauge
37
37
  end
38
38
 
39
39
  def handle_failure(message, exception, execution_time, recoverable)
40
+ project_dir = File.basename(Dir.getwd)
41
+ stacktrace = exception.backtrace.select {|x| x.match(project_dir) && !x.match(File.join(project_dir, "vendor"))}.join("\n")+"\n"
42
+ filepath = stacktrace.split("\n").first.split(":").first
43
+ line_number = stacktrace.split("\n").first.split("/").last.split(":")[1]
44
+ code_snippet = "\n" + '> ' + get_code_snippet(filepath, line_number.to_i)
40
45
  execution_status_response =
41
46
  Messages::ExecutionStatusResponse.new(
42
47
  :executionResult => Messages::ProtoExecutionResult.new(:failed => true,
43
48
  :recoverableError => recoverable,
44
49
  :errorMessage => exception.message,
45
- :stackTrace => exception.backtrace.join("\n")+"\n",
50
+ :stackTrace => code_snippet + stacktrace,
46
51
  :executionTime => execution_time,
47
52
  :screenShot => screenshot_bytes))
48
53
  Messages::Message.new(:messageType => Messages::Message::MessageType::ExecutionStatusResponse,
49
54
  :messageId => message.messageId, :executionStatusResponse => execution_status_response)
50
55
  end
51
56
 
57
+ def get_code_snippet(filename, number)
58
+ return nil if number < 1
59
+ line = File.readlines(filename)[number-1]
60
+ number.to_s + " | " + line.strip + "\n\n"
61
+ end
62
+
52
63
  def screenshot_bytes
53
64
  return nil if (ENV['screenshot_on_failure'] || "").downcase == "false" || which("gauge_screenshot").nil?
54
65
  begin
55
66
  Configuration.instance.screengrabber.call
56
67
  rescue Exception => e
57
- puts e
68
+ Gauge::Log.error e
58
69
  return nil
59
70
  end
60
71
  end
@@ -17,12 +17,16 @@
17
17
 
18
18
  require_relative "execution_handler"
19
19
  require_relative "../gauge_messages"
20
-
20
+ require_relative "../executor"
21
+ require_relative "../method_cache"
22
+ require_relative "../util"
21
23
  module Gauge
22
24
  module Processors
23
25
  include ExecutionHandler
24
26
 
25
27
  def process_execution_start_request(message)
28
+ Gauge::MethodCache.clear
29
+ Executor.load_steps(Util.get_step_implementation_dir)
26
30
  handle_hooks_execution(MethodCache.get_before_suite_hooks, message, message.executionStartingRequest.currentExecutionInfo,false)
27
31
  end
28
32
 
@@ -0,0 +1,29 @@
1
+ # Copyright 2018 ThoughtWorks, Inc.
2
+
3
+ # This file is part of Gauge-Ruby.
4
+
5
+ # Gauge-Ruby is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # Gauge-Ruby is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Gauge-Ruby. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require_relative '../util'
19
+
20
+ module Gauge
21
+ module Processors
22
+ def process_implementation_file_list_request(message)
23
+ implPath = Util.get_step_implementation_dir
24
+ fileList = Dir["#{implPath}/**/*.rb"]
25
+ r = Messages::ImplementationFileListResponse.new(:implementationFilePaths => fileList)
26
+ Messages::Message.new(:messageType => Messages::Message::MessageType::ImplementationFileListResponse, :messageId => message.messageId, :implementationFileListResponse => r)
27
+ end
28
+ end
29
+ end