gauge-ruby 0.2.1 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4e04db5143c0125740f2adb38e62d1dd57ad9670
4
- data.tar.gz: 14d3f58fdf3e195028b69bc0c7758922cb2a27f8
3
+ metadata.gz: 3d02594acc904fc72ca2ee33b36d035f16a2f7d6
4
+ data.tar.gz: 101648409eacd64b386ee67a779676fb4c7e3d34
5
5
  SHA512:
6
- metadata.gz: eb5ada07b9e706a722b480a17e75f8e88bc17c32e0317e88f2ece1f9cd6b744fdc3199cbfec05159fc7ebe4ba26be5fa68291781b6f892fff1b2692665aa027e
7
- data.tar.gz: 3c11170de25a233e43d309d7eb47bba637a1124a0af38dfa78b2cfc16ec236899badf59ee5d2aa67330fa09244a585c612263183ce71a441b462e08717d45434
6
+ metadata.gz: 4447626f14695ddf0f3ce41562007a4544e4f55451ef0a9d613c83e552f8d1c2c77a04c41021826ae58f31edfb4bbaf18753a4048064d4cb33ed74aabee3012b
7
+ data.tar.gz: 99a5cf6190e7e4ab33736ee3dfd15c7b568a30d6fee44681341c4123664f0ddc91b0fca511f47fd489ba23d9e9a9d3a5074ee452ee9bee82dd42c5c995e54713
data/lib/code_parser.rb CHANGED
@@ -19,6 +19,7 @@ require 'parser/current'
19
19
  require 'method_source'
20
20
  require 'fileutils'
21
21
  require 'tempfile'
22
+ require 'util'
22
23
 
23
24
  module Gauge
24
25
  # @api private
@@ -32,9 +33,13 @@ module Gauge
32
33
  def self.refactor_args(code, param_positions, new_param_values, new_step_text)
33
34
  new_params = []
34
35
  args = step_args_from_code code
35
- param_positions.sort_by!(&:newPosition).each { |e|
36
+ param_positions.sort_by!(&:newPosition).each.with_index { |e,i|
36
37
  if e.oldPosition == -1
37
- new_params[e.newPosition] = "arg_#{new_param_values[e.newPosition].downcase.split.join('_')}"
38
+ param = Util.remove_special_chars new_param_values[e.newPosition].downcase.split.join('_')
39
+ if param == ''
40
+ param = i
41
+ end
42
+ new_params[e.newPosition] = "arg_#{param}"
38
43
  else
39
44
  new_params[e.newPosition] = args[e.oldPosition].children[0]
40
45
  end
@@ -58,8 +63,7 @@ module Gauge
58
63
 
59
64
  def self.refactor(code, param_positions, new_param_values, new_step_text)
60
65
  source_code=code.source
61
- ast = code_to_ast source_code
62
- file, line = code.source_location
66
+ file, _ = code.source_location
63
67
  refactored_code=refactor_args(source_code, param_positions, new_param_values, new_step_text)
64
68
  tmp_file = Tempfile.new File.basename(file, ".rb")
65
69
  tmp_file.write(File.open(file, "r") { |f| f.read.gsub(source_code, refactored_code)})
data/lib/configuration.rb CHANGED
@@ -22,7 +22,8 @@ module Gauge
22
22
  class << self
23
23
  # @api public
24
24
  # Custom configuration for Gauge
25
- # Lets you configure modules that need to be included at runtime.
25
+ # - Lets you configure modules that need to be included at runtime.
26
+ # - Lets you define a custom screengrabber, which will be invoked to capture screenshot on failure.
26
27
  #
27
28
  # @example
28
29
  # # Given there are two modules defined
@@ -37,6 +38,12 @@ module Gauge
37
38
  # Gauge.configure do |config|
38
39
  # config.include Foo, Bar
39
40
  # end
41
+ # @example
42
+ # # Default behaviour is to capture the active desktop at the point of failure.
43
+ # # The implementation should return a byte array of the image.
44
+ # Gauge.configure do |config|
45
+ # config.screengrabber = -> { return File.binread("/path/to/screenshot")}
46
+ # end
40
47
  def configure(&block)
41
48
  Configuration.instance.instance_eval &block
42
49
  end
@@ -46,6 +53,13 @@ module Gauge
46
53
  class Configuration
47
54
  def initialize
48
55
  @includes=[]
56
+ @screengrabber = -> {
57
+ file = File.open("#{Dir.tmpdir}/screenshot.png", "w+")
58
+ `gauge_screenshot #{file.path}`
59
+ file_content = File.binread(file.path)
60
+ File.delete file
61
+ return file_content
62
+ }
49
63
  end
50
64
 
51
65
  def self.instance
@@ -60,6 +74,14 @@ module Gauge
60
74
  @includes
61
75
  end
62
76
 
77
+ def screengrabber
78
+ @screengrabber
79
+ end
80
+
81
+ def screengrabber=(block)
82
+ @screengrabber=block
83
+ end
84
+
63
85
  def self.include_configured_modules
64
86
  # include all modules that have been configured
65
87
  # TODO: move this feature to something more specific, ex look at supporting Sandboxed execution.
data/lib/executor.rb CHANGED
@@ -21,7 +21,13 @@ module Gauge
21
21
  # @api private
22
22
  module Executor
23
23
  def self.load_steps(steps_implementation_dir)
24
- Dir["#{steps_implementation_dir}/**/*.rb"].each { |x| require x }
24
+ Dir["#{steps_implementation_dir}/**/*.rb"].each { |x|
25
+ begin
26
+ require x
27
+ rescue Exception => e
28
+ puts "[ERROR] Cannot import #{x}. Reason: #{e.message}"
29
+ end
30
+ }
25
31
  end
26
32
 
27
33
  def self.execute_step(step, args)
data/lib/gauge.rb CHANGED
@@ -89,13 +89,28 @@ module Kernel
89
89
  # puts x.columns.join("|")
90
90
  # x.rows.each { |r| puts r.join("|") }
91
91
  # end
92
+ # @example
93
+ # # for a given step say
94
+ # # setting :continue_on_failure=>true in implementation will not break on failure of this step
95
+ # # and will continue to execute the next step in the scenario
96
+ # # * say "hello" to "gauge"
97
+ # step 'say <what> to <who>', :continue_on_failure => false do |what, who|
98
+ # puts "say #{what} to #{who}"
99
+ # raise "Some Failure"
100
+ # end
101
+ #
92
102
  # @param step_texts [string, ...] the step text(s)
103
+ # @param opts [Hash] pass :continue_on_failure => true to tell Gauge not to break on failure for this step
93
104
  # @param block [block] the implementation block for given step.
94
- def step(*step_texts, &block)
105
+ def step(*args, &block)
106
+ opts = args.select {|x| x.is_a? Hash}
107
+ step_texts = args-opts
108
+ opts = {:continue_on_failure => false}.merge opts.reduce({}, :merge)
95
109
  step_texts.each do |text|
96
110
  parameterized_step_text = Gauge::Connector.step_value(text)
97
111
  Gauge::MethodCache.add_step(parameterized_step_text, &block)
98
112
  Gauge::MethodCache.add_step_text(parameterized_step_text, text)
113
+ Gauge::MethodCache.set_recoverable(parameterized_step_text) if opts[:continue_on_failure]
99
114
  end
100
115
  Gauge::MethodCache.add_step_alias(*step_texts)
101
116
  end
data/lib/gauge_runtime.rb CHANGED
@@ -74,5 +74,6 @@ module Gauge
74
74
  Connector.make_connections()
75
75
  Executor.load_steps(DEFAULT_IMPLEMENTATIONS_DIR_PATH)
76
76
  dispatch_messages(Connector.executionSocket)
77
+ exit(0)
77
78
  end
78
79
  end
data/lib/messages.pb.rb CHANGED
@@ -157,6 +157,7 @@ module Gauge
157
157
  set_fully_qualified_name "gauge.messages.StepValidateResponse.ErrorType"
158
158
 
159
159
  STEP_IMPLEMENTATION_NOT_FOUND = 0
160
+ DUPLICATE_STEP_IMPLEMENTATION = 1
160
161
  end
161
162
 
162
163
  set_fully_qualified_name "gauge.messages.StepValidateResponse"
data/lib/method_cache.rb CHANGED
@@ -34,11 +34,16 @@ module Gauge
34
34
  end
35
35
 
36
36
  def self.add_step(parameterized_step_text, &block)
37
- @@steps_map[parameterized_step_text] = block
37
+ @@steps_map[parameterized_step_text] = @@steps_map[parameterized_step_text] || []
38
+ @@steps_map[parameterized_step_text].push(block)
38
39
  end
39
40
 
40
41
  def self.get_step(parameterized_step_text)
41
- @@steps_map[parameterized_step_text]
42
+ @@steps_map[parameterized_step_text][0]
43
+ end
44
+
45
+ def self.get_steps(parameterized_step_text)
46
+ @@steps_map[parameterized_step_text] || []
42
47
  end
43
48
 
44
49
  def self.add_step_text(parameterized_step_text, step_text)
@@ -65,10 +70,19 @@ module Gauge
65
70
  @@steps_text_map.values
66
71
  end
67
72
 
73
+ def self.is_recoverable?(parameterized_step_text)
74
+ @@recoverable_steps.include? parameterized_step_text
75
+ end
76
+
77
+ def self.set_recoverable(parameterized_step_text)
78
+ @@recoverable_steps.push parameterized_step_text
79
+ end
80
+
68
81
  private
69
82
  @@steps_map = Hash.new
70
83
  @@steps_text_map = Hash.new
71
84
  @@steps_with_aliases = []
85
+ @@recoverable_steps = []
72
86
  @@before_suite_hooks = []
73
87
  @@after_suite_hooks = []
74
88
  @@before_spec_hooks = []
@@ -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)
32
+ return handle_failure message, e, time_elapsed_since(start_time), MethodCache.is_recoverable?(step_text)
33
33
  end
34
34
  handle_pass message, time_elapsed_since(start_time)
35
35
  end
@@ -27,7 +27,7 @@ module Gauge
27
27
  if execution_error == nil
28
28
  return handle_pass message, time_elapsed_since(start_time)
29
29
  else
30
- return handle_failure message, execution_error, time_elapsed_since(start_time)
30
+ return handle_failure message, execution_error, time_elapsed_since(start_time), false
31
31
  end
32
32
  end
33
33
 
@@ -36,11 +36,11 @@ module Gauge
36
36
  Messages::Message.new(:messageType => Messages::Message::MessageType::ExecutionStatusResponse, :messageId => message.messageId, :executionStatusResponse => execution_status_response)
37
37
  end
38
38
 
39
- def handle_failure(message, exception, execution_time)
39
+ def handle_failure(message, exception, execution_time, recoverable)
40
40
  execution_status_response =
41
41
  Messages::ExecutionStatusResponse.new(
42
42
  :executionResult => Messages::ProtoExecutionResult.new(:failed => true,
43
- :recoverableError => false,
43
+ :recoverableError => recoverable,
44
44
  :errorMessage => exception.message,
45
45
  :stackTrace => exception.backtrace.join("\n")+"\n",
46
46
  :executionTime => execution_time,
@@ -51,11 +51,12 @@ module Gauge
51
51
 
52
52
  def screenshot_bytes
53
53
  return nil if (ENV['screenshot_enabled'] || "").downcase == "false" || which("gauge_screenshot").nil?
54
- file = File.open("#{Dir.tmpdir}/screenshot.png", "w+")
55
- `gauge_screenshot #{file.path}`
56
- file_content = File.binread(file.path)
57
- File.delete file
58
- return file_content
54
+ begin
55
+ Configuration.instance.screengrabber.call
56
+ rescue Exception => e
57
+ puts e
58
+ return nil
59
+ end
59
60
  end
60
61
 
61
62
  def time_elapsed_since(start_time)
@@ -85,7 +86,7 @@ module Gauge
85
86
  }
86
87
  end
87
88
  return nil
88
- end
89
+ end
89
90
  end
90
91
  end
91
92
  end
@@ -22,15 +22,23 @@ module Gauge
22
22
  def refactor_step(message)
23
23
  oldStepValue = message.refactorRequest.oldStepValue.stepValue
24
24
  newStep = message.refactorRequest.newStepValue
25
- stepBlock = MethodCache.get_step oldStepValue
26
25
  refactor_response = Messages::RefactorResponse.new(success: true)
27
26
  begin
27
+ stepBlock = get_step oldStepValue
28
28
  CodeParser.refactor stepBlock, message.refactorRequest.paramPositions, newStep.parameters, newStep.parameterizedStepValue
29
+ file, _ = stepBlock.source_location
30
+ refactor_response.filesChanged = [file]
29
31
  rescue Exception => e
30
32
  refactor_response.success=false
31
33
  refactor_response.error=e.message
32
34
  end
33
35
  Messages::Message.new(:messageType => Messages::Message::MessageType::RefactorResponse, :messageId => message.messageId, refactorResponse: refactor_response)
34
36
  end
37
+
38
+ def get_step(step_text)
39
+ blocks = MethodCache.get_steps step_text
40
+ raise "Multiple step implementations found for => '#{step_text}'" if blocks.length > 1
41
+ blocks[0]
42
+ end
35
43
  end
36
44
  end
@@ -19,9 +19,20 @@ module Gauge
19
19
  module Processors
20
20
  def process_step_validation_request(message)
21
21
  step_validate_request = message.stepValidateRequest
22
- is_valid = MethodCache.valid_step?(step_validate_request.stepText)
23
- step_validate_response = Messages::StepValidateResponse.new(:isValid => is_valid,
24
- :errorMessage => is_valid ? "" : "Step implementation not found", :errorType => Messages::StepValidateResponse::ErrorType::STEP_IMPLEMENTATION_NOT_FOUND)
22
+ is_valid = true
23
+ msg = ''
24
+ err_type = nil
25
+ blocks = MethodCache.get_steps(step_validate_request.stepText)
26
+ if blocks.length > 1
27
+ is_valid = false
28
+ msg = "Multiple step implementations found for => '#{step_validate_request.stepText}'"
29
+ err_type = Messages::StepValidateResponse::ErrorType::DUPLICATE_STEP_IMPLEMENTATION
30
+ elsif blocks.length == 0
31
+ is_valid = false
32
+ msg = 'Step implementation not found'
33
+ err_type = Messages::StepValidateResponse::ErrorType::STEP_IMPLEMENTATION_NOT_FOUND
34
+ end
35
+ step_validate_response = Messages::StepValidateResponse.new(:isValid => is_valid, :errorMessage => msg, :errorType => err_type)
25
36
  Messages::Message.new(:messageType => Messages::Message::MessageType::StepValidateResponse,
26
37
  :messageId => message.messageId,
27
38
  :stepValidateResponse => step_validate_response)
data/lib/spec.pb.rb CHANGED
@@ -9,6 +9,7 @@ module Gauge
9
9
  class ProtoSpec < ::ProtocolBuffers::Message; end
10
10
  class ProtoItem < ::ProtocolBuffers::Message; end
11
11
  class ProtoScenario < ::ProtocolBuffers::Message; end
12
+ class Span < ::ProtocolBuffers::Message; end
12
13
  class ProtoTableDrivenScenario < ::ProtocolBuffers::Message; end
13
14
  class ProtoStep < ::ProtocolBuffers::Message; end
14
15
  class ProtoConcept < ::ProtocolBuffers::Message; end
@@ -80,6 +81,16 @@ module Gauge
80
81
  optional :int64, :executionTime, 8
81
82
  required :bool, :skipped, 9
82
83
  repeated :string, :skipErrors, 10
84
+ optional :string, :ID, 11
85
+ repeated ::Gauge::Messages::ProtoItem, :tearDownSteps, 12
86
+ optional ::Gauge::Messages::Span, :span, 13
87
+ end
88
+
89
+ class Span < ::ProtocolBuffers::Message
90
+ set_fully_qualified_name "gauge.messages.Span"
91
+
92
+ required :int64, :start, 1
93
+ required :int64, :end, 2
83
94
  end
84
95
 
85
96
  class ProtoTableDrivenScenario < ::ProtocolBuffers::Message
@@ -185,6 +196,18 @@ module Gauge
185
196
  end
186
197
 
187
198
  class ProtoExecutionResult < ::ProtocolBuffers::Message
199
+ # forward declarations
200
+
201
+ # enums
202
+ module ErrorType
203
+ include ::ProtocolBuffers::Enum
204
+
205
+ set_fully_qualified_name "gauge.messages.ProtoExecutionResult.ErrorType"
206
+
207
+ ASSERTION = 1
208
+ VERIFICATION = 2
209
+ end
210
+
188
211
  set_fully_qualified_name "gauge.messages.ProtoExecutionResult"
189
212
 
190
213
  required :bool, :failed, 1
@@ -194,6 +217,7 @@ module Gauge
194
217
  optional :bytes, :screenShot, 5
195
218
  required :int64, :executionTime, 6
196
219
  repeated :string, :message, 7
220
+ optional ::Gauge::Messages::ProtoExecutionResult::ErrorType, :errorType, 8, :default => ::Gauge::Messages::ProtoExecutionResult::ErrorType::ASSERTION
197
221
  end
198
222
 
199
223
  class ProtoHookFailure < ::ProtocolBuffers::Message
data/lib/table.rb CHANGED
@@ -24,20 +24,18 @@ module Gauge
24
24
  @columns = protoTable.headers.cells
25
25
  @rows = []
26
26
  protoTable.rows.each do |row|
27
- @rows.push row.cells
27
+ @rows.push Row.new(@columns, row.cells)
28
28
  end
29
29
  end
30
30
 
31
31
  # Gets the column headers of the table
32
32
  # @return [string[]]
33
- # @deprecated Use [] accessor instead
34
33
  def columns
35
34
  @columns
36
35
  end
37
36
 
38
37
  # Gets the rows of the table. The rows are two dimensional arrays.
39
38
  # @return [string[][]]
40
- # @deprecated Use {#[]} accessor instead
41
39
  def rows
42
40
  @rows
43
41
  end
@@ -53,18 +51,38 @@ module Gauge
53
51
  # table["Col1"] => ["Row1.Cell1", "Row1.Cell1", ...]
54
52
  # table["Invalid_Col_Name"] => nil
55
53
  def [](index)
56
- return row_values_as_hash(@rows[index]) if index.is_a?(Integer)
54
+ return @rows[index] if index.is_a?(Integer)
57
55
  column_values_as_array(index)
58
56
  end
59
57
 
60
58
  private
61
- def row_values_as_hash(row)
62
- row.nil? ? nil : Hash[@columns.zip(row)]
63
- end
64
59
 
65
60
  def column_values_as_array(col_name)
66
61
  i = @columns.index col_name
67
62
  i.nil? ? nil : @rows.map { |r| r[i] }
68
63
  end
69
64
  end
65
+
66
+ # Holds a row of a table.
67
+ # @api public
68
+ class Row
69
+ # @api private
70
+ def initialize(columns, values)
71
+ @values = values
72
+ @columns = columns
73
+ end
74
+
75
+ # Gets the row cell.
76
+ # @param index Either cell index, or Column name.
77
+ # @return [string] value of the row cell
78
+ # @example
79
+ # row[0] => 'value'
80
+ # row['column'] => 'value'
81
+ # row[i] => nil # when index is out of range
82
+ def [](index)
83
+ return @values[index] if index.is_a?(Integer)
84
+ columns_index = @columns.index(index)
85
+ columns_index.nil? ? nil : @values[columns_index]
86
+ end
87
+ end
70
88
  end
data/lib/util.rb ADDED
@@ -0,0 +1,37 @@
1
+ # Copyright 2015 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
+ module Gauge
19
+ class Util
20
+ def self.valid_variable_name?(var_name)
21
+ Object.new.instance_variable_set ('@'+var_name).to_sym, nil
22
+ true
23
+ rescue NameError
24
+ !!(var_name =~ /^[0-9]+$/)
25
+ end
26
+
27
+ def self.remove_special_chars(param)
28
+ new_param = ''
29
+ param.each_char { |c|
30
+ if valid_variable_name? c
31
+ new_param += c
32
+ end
33
+ }
34
+ return new_param
35
+ end
36
+ end
37
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gauge-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gauge Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-15 00:00:00.000000000 Z
11
+ date: 2016-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-protocol-buffers
@@ -96,6 +96,7 @@ files:
96
96
  - lib/processors/step_validation_request_processor.rb
97
97
  - lib/spec.pb.rb
98
98
  - lib/table.rb
99
+ - lib/util.rb
99
100
  homepage: http://www.getgauge.io
100
101
  licenses:
101
102
  - GPL-3.0
@@ -116,8 +117,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
117
  version: '1.9'
117
118
  requirements: []
118
119
  rubyforge_project:
119
- rubygems_version: 2.4.6
120
+ rubygems_version: 2.5.1
120
121
  signing_key:
121
122
  specification_version: 4
122
123
  summary: Ruby support for Gauge
123
124
  test_files: []
125
+ has_rdoc: yard