cucumber 2.1.0 → 2.2.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 +4 -4
- data/.travis.yml +10 -0
- data/Gemfile +3 -1
- data/History.md +18 -2
- data/README.md +5 -1
- data/cucumber.gemspec +3 -4
- data/cucumber.yml +2 -2
- data/features/docs/api/run_cli_main_with_existing_runtime.feature +4 -7
- data/features/docs/defining_steps/skip_scenario.feature +6 -2
- data/features/docs/formatters/api_methods.feature +36 -0
- data/features/docs/profiles.feature +2 -2
- data/features/lib/step_definitions/profile_steps.rb +1 -1
- data/lib/cucumber.rb +11 -4
- data/lib/cucumber/cli/configuration.rb +2 -2
- data/lib/cucumber/cli/options.rb +2 -2
- data/lib/cucumber/configuration.rb +25 -3
- data/lib/cucumber/deprecate.rb +29 -0
- data/lib/cucumber/filters/activate_steps.rb +39 -5
- data/lib/cucumber/formatter/console.rb +4 -4
- data/lib/cucumber/formatter/io.rb +1 -1
- data/lib/cucumber/formatter/legacy_api/adapter.rb +30 -30
- data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +4 -9
- data/lib/cucumber/platform.rb +2 -7
- data/lib/cucumber/rb_support/rb_language.rb +72 -26
- data/lib/cucumber/rb_support/rb_step_definition.rb +2 -2
- data/lib/cucumber/rb_support/rb_world.rb +6 -1
- data/lib/cucumber/rb_support/snippet.rb +21 -0
- data/lib/cucumber/running_test_case.rb +5 -1
- data/lib/cucumber/runtime.rb +11 -15
- data/lib/cucumber/runtime/support_code.rb +20 -128
- data/lib/cucumber/step_argument.rb +25 -0
- data/lib/cucumber/step_match.rb +6 -12
- data/lib/cucumber/step_match_search.rb +67 -0
- data/lib/cucumber/version +1 -0
- data/spec/cucumber/configuration_spec.rb +3 -2
- data/spec/cucumber/filters/activate_steps_spec.rb +95 -3
- data/spec/cucumber/formatter/html_spec.rb +1 -1
- data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +55 -28
- data/spec/cucumber/formatter/pretty_spec.rb +2 -2
- data/spec/cucumber/formatter/spec_helper.rb +22 -12
- data/spec/cucumber/rb_support/rb_language_spec.rb +9 -45
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +2 -2
- data/spec/cucumber/rb_support/rb_world_spec.rb +47 -0
- data/spec/cucumber/runtime/for_programming_languages_spec.rb +1 -1
- data/spec/cucumber/runtime/support_code_spec.rb +4 -111
- data/spec/cucumber/step_argument_spec.rb +18 -0
- data/spec/cucumber/step_match_search_spec.rb +122 -0
- data/spec/cucumber/step_match_spec.rb +8 -2
- data/spec/cucumber/world/pending_spec.rb +2 -1
- data/spec/cucumber_spec.rb +39 -0
- metadata +45 -50
- data/features/docs/wire_protocol/erb_configuration.feature +0 -56
- data/features/docs/wire_protocol/handle_unexpected_response.feature +0 -30
- data/features/docs/wire_protocol/invoke_message.feature +0 -216
- data/features/docs/wire_protocol/readme.md +0 -26
- data/features/docs/wire_protocol/snippets_message.feature +0 -51
- data/features/docs/wire_protocol/step_matches_message.feature +0 -81
- data/features/docs/wire_protocol/table_diffing.feature +0 -126
- data/features/docs/wire_protocol/tags.feature +0 -87
- data/features/docs/wire_protocol/timeouts.feature +0 -64
- data/lib/cucumber/events/bus.rb +0 -86
- data/lib/cucumber/gherkin/formatter/argument.rb +0 -17
- data/lib/cucumber/gherkin/formatter/hashable.rb +0 -27
- data/lib/cucumber/language_support.rb +0 -30
- data/lib/cucumber/language_support/language_methods.rb +0 -72
- data/lib/cucumber/rb_support/regexp_argument_matcher.rb +0 -21
- data/lib/cucumber/wire_support/configuration.rb +0 -38
- data/lib/cucumber/wire_support/connection.rb +0 -61
- data/lib/cucumber/wire_support/request_handler.rb +0 -32
- data/lib/cucumber/wire_support/wire_exception.rb +0 -32
- data/lib/cucumber/wire_support/wire_language.rb +0 -68
- data/lib/cucumber/wire_support/wire_packet.rb +0 -34
- data/lib/cucumber/wire_support/wire_protocol.rb +0 -43
- data/lib/cucumber/wire_support/wire_protocol/requests.rb +0 -133
- data/lib/cucumber/wire_support/wire_step_definition.rb +0 -21
- data/spec/cucumber/events/bus_spec.rb +0 -94
- data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +0 -22
- data/spec/cucumber/wire_support/configuration_spec.rb +0 -64
- data/spec/cucumber/wire_support/connection_spec.rb +0 -64
- data/spec/cucumber/wire_support/wire_exception_spec.rb +0 -50
- data/spec/cucumber/wire_support/wire_language_spec.rb +0 -46
- data/spec/cucumber/wire_support/wire_packet_spec.rb +0 -44
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'cucumber/gherkin/formatter/argument'
|
2
|
-
|
3
|
-
module Cucumber
|
4
|
-
module RbSupport
|
5
|
-
class RegexpArgumentMatcher
|
6
|
-
def self.arguments_from(regexp, step_name)
|
7
|
-
match = regexp.match(step_name)
|
8
|
-
if match
|
9
|
-
n = 0
|
10
|
-
match.captures.map do |val|
|
11
|
-
n += 1
|
12
|
-
offset = match.offset(n)[0]
|
13
|
-
Cucumber::Gherkin::Formatter::Argument.new(offset, val)
|
14
|
-
end
|
15
|
-
else
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'erb'
|
3
|
-
|
4
|
-
module Cucumber
|
5
|
-
module WireSupport
|
6
|
-
class Configuration
|
7
|
-
attr_reader :host, :port, :unix
|
8
|
-
|
9
|
-
def self.from_file(wire_file)
|
10
|
-
settings = YAML.load(ERB.new(File.read(wire_file)).result)
|
11
|
-
new(settings)
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(args)
|
15
|
-
@host = args['host']
|
16
|
-
@port = args['port']
|
17
|
-
@unix = args['unix'] if RUBY_PLATFORM !~ /mingw|mswin/
|
18
|
-
@timeouts = DEFAULT_TIMEOUTS.merge(args['timeout'] || {})
|
19
|
-
end
|
20
|
-
|
21
|
-
def timeout(message = nil)
|
22
|
-
return @timeouts[message.to_s] || 3
|
23
|
-
end
|
24
|
-
|
25
|
-
def to_s
|
26
|
-
return @unix if @unix
|
27
|
-
"#{@host}:#{@port}"
|
28
|
-
end
|
29
|
-
|
30
|
-
DEFAULT_TIMEOUTS = {
|
31
|
-
'connect' => 11,
|
32
|
-
'invoke' => 120,
|
33
|
-
'begin_scenario' => 120,
|
34
|
-
'end_scenario' => 120
|
35
|
-
}
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'timeout'
|
2
|
-
require 'cucumber/wire_support/wire_protocol'
|
3
|
-
|
4
|
-
module Cucumber
|
5
|
-
module WireSupport
|
6
|
-
class Connection
|
7
|
-
class ConnectionError < StandardError; end
|
8
|
-
|
9
|
-
include WireProtocol
|
10
|
-
|
11
|
-
def initialize(config)
|
12
|
-
@config = config
|
13
|
-
end
|
14
|
-
|
15
|
-
def call_remote(request_handler, message, params)
|
16
|
-
packet = WirePacket.new(message, params)
|
17
|
-
|
18
|
-
begin
|
19
|
-
send_data_to_socket(packet.to_json)
|
20
|
-
response = fetch_data_from_socket(@config.timeout(message))
|
21
|
-
response.handle_with(request_handler)
|
22
|
-
rescue Timeout::Error => e
|
23
|
-
backtrace = e.backtrace ; backtrace.shift # because Timeout puts some wierd stuff in there
|
24
|
-
raise Timeout::Error, "Timed out calling wire server with message '#{message}'", backtrace
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def exception(params)
|
29
|
-
WireException.new(params, @config)
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def send_data_to_socket(data)
|
35
|
-
Timeout.timeout(@config.timeout('connect')) { socket.puts(data) }
|
36
|
-
end
|
37
|
-
|
38
|
-
def fetch_data_from_socket(timeout)
|
39
|
-
raw_response =
|
40
|
-
if timeout == :never
|
41
|
-
socket.gets
|
42
|
-
else
|
43
|
-
Timeout.timeout(timeout) { socket.gets }
|
44
|
-
end
|
45
|
-
raise exception({'message' => "Remote Socket with #{@config.host}:#{@config.port} closed."}) if raw_response.nil?
|
46
|
-
WirePacket.parse(raw_response)
|
47
|
-
end
|
48
|
-
|
49
|
-
def socket
|
50
|
-
return @socket if @socket
|
51
|
-
if @config.unix
|
52
|
-
@socket = UNIXSocket.new(@config.unix)
|
53
|
-
else
|
54
|
-
@socket = TCPSocket.new(@config.host, @config.port)
|
55
|
-
end
|
56
|
-
rescue Errno::ECONNREFUSED => exception
|
57
|
-
raise(ConnectionError, "Unable to contact the wire server at #{@config}. Is it up?")
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module Cucumber
|
2
|
-
module WireSupport
|
3
|
-
class RequestHandler
|
4
|
-
def initialize(connection)
|
5
|
-
@connection = connection
|
6
|
-
@message = underscore(self.class.name.split('::').last)
|
7
|
-
end
|
8
|
-
|
9
|
-
def execute(request_params = nil)
|
10
|
-
@connection.call_remote(self, @message, request_params)
|
11
|
-
end
|
12
|
-
|
13
|
-
def handle_fail(params)
|
14
|
-
raise @connection.exception(params)
|
15
|
-
end
|
16
|
-
|
17
|
-
def handle_success(params)
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
# Props to Rails
|
23
|
-
def underscore(camel_cased_word)
|
24
|
-
camel_cased_word.to_s.gsub(/::/, '/').
|
25
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
26
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
27
|
-
tr("-", "_").
|
28
|
-
downcase
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module Cucumber
|
2
|
-
module WireSupport
|
3
|
-
# Proxy for an exception that occured at the remote end of the wire
|
4
|
-
class WireException < StandardError
|
5
|
-
module CanSetName
|
6
|
-
attr_writer :exception_name
|
7
|
-
def to_s
|
8
|
-
@exception_name
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize(args, config)
|
13
|
-
super args['message']
|
14
|
-
if args['exception']
|
15
|
-
self.class.extend(CanSetName)
|
16
|
-
self.class.exception_name = "#{args['exception']} from #{config}"
|
17
|
-
end
|
18
|
-
if args['backtrace']
|
19
|
-
@backtrace = if args['backtrace'].is_a?(String)
|
20
|
-
args['backtrace'].split("\n") # TODO: change cuke4nuke to pass an array instead of a big string
|
21
|
-
else
|
22
|
-
args['backtrace']
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def backtrace
|
28
|
-
@backtrace || super
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'multi_json'
|
2
|
-
require 'socket'
|
3
|
-
require 'cucumber/wire_support/connection'
|
4
|
-
require 'cucumber/wire_support/configuration'
|
5
|
-
require 'cucumber/wire_support/wire_packet'
|
6
|
-
require 'cucumber/wire_support/wire_exception'
|
7
|
-
require 'cucumber/wire_support/wire_step_definition'
|
8
|
-
|
9
|
-
module Cucumber
|
10
|
-
module WireSupport
|
11
|
-
|
12
|
-
# The wire-protocol (language independent) implementation of the programming
|
13
|
-
# language API.
|
14
|
-
class WireLanguage
|
15
|
-
include LanguageSupport::LanguageMethods
|
16
|
-
|
17
|
-
def initialize(_=nil)
|
18
|
-
@connections = []
|
19
|
-
end
|
20
|
-
|
21
|
-
def load_code_file(wire_file)
|
22
|
-
config = Configuration.from_file(wire_file)
|
23
|
-
@connections << Connection.new(config)
|
24
|
-
end
|
25
|
-
|
26
|
-
def snippet_text(code_keyword, step_name, multiline_arg, snippet_type)
|
27
|
-
snippets = @connections.map do |remote|
|
28
|
-
remote.snippet_text(code_keyword, step_name, MultilineArgClassName.new(multiline_arg).to_s)
|
29
|
-
end
|
30
|
-
snippets.flatten.join("\n")
|
31
|
-
end
|
32
|
-
|
33
|
-
def step_matches(step_name, formatted_step_name)
|
34
|
-
@connections.map{ |c| c.step_matches(step_name, formatted_step_name)}.flatten
|
35
|
-
end
|
36
|
-
|
37
|
-
def begin_scenario(scenario)
|
38
|
-
@connections.each { |c| c.begin_scenario(scenario) }
|
39
|
-
@current_scenario = scenario
|
40
|
-
end
|
41
|
-
|
42
|
-
def end_scenario
|
43
|
-
scenario = @current_scenario
|
44
|
-
@connections.each { |c| c.end_scenario(scenario) }
|
45
|
-
@current_scenario = nil
|
46
|
-
end
|
47
|
-
|
48
|
-
class MultilineArgClassName
|
49
|
-
def initialize(arg)
|
50
|
-
arg.describe_to(self)
|
51
|
-
@result = ""
|
52
|
-
end
|
53
|
-
|
54
|
-
def data_table(*)
|
55
|
-
@result = "Cucumber::MultilineArgument::DataTable"
|
56
|
-
end
|
57
|
-
|
58
|
-
def doc_string(*)
|
59
|
-
@result = "Cucumber::MultilineArgument::DocString"
|
60
|
-
end
|
61
|
-
|
62
|
-
def to_s
|
63
|
-
@result
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'multi_json'
|
2
|
-
|
3
|
-
module Cucumber
|
4
|
-
module WireSupport
|
5
|
-
# Represents the packet of data sent over the wire as JSON data, containing
|
6
|
-
# a message and a hash of arguments
|
7
|
-
class WirePacket
|
8
|
-
class << self
|
9
|
-
def parse(raw)
|
10
|
-
attributes = MultiJson.load(raw.strip)
|
11
|
-
message = attributes[0]
|
12
|
-
params = attributes[1]
|
13
|
-
new(message, params)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
attr_reader :message, :params
|
18
|
-
|
19
|
-
def initialize(message, params = nil)
|
20
|
-
@message, @params = message, params
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_json
|
24
|
-
packet = [@message]
|
25
|
-
packet << @params if @params
|
26
|
-
MultiJson.dump(packet)
|
27
|
-
end
|
28
|
-
|
29
|
-
def handle_with(handler)
|
30
|
-
handler.send("handle_#{@message}", @params)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'cucumber/wire_support/wire_protocol/requests'
|
2
|
-
|
3
|
-
module Cucumber
|
4
|
-
module WireSupport
|
5
|
-
module WireProtocol
|
6
|
-
def step_matches(name_to_match, name_to_report)
|
7
|
-
handler = Requests::StepMatches.new(self)
|
8
|
-
handler.execute(name_to_match, name_to_report)
|
9
|
-
end
|
10
|
-
|
11
|
-
def snippet_text(step_keyword, step_name, multiline_arg_class_name)
|
12
|
-
handler = Requests::SnippetText.new(self)
|
13
|
-
handler.execute(step_keyword, step_name, multiline_arg_class_name)
|
14
|
-
end
|
15
|
-
|
16
|
-
def invoke(step_definition_id, args)
|
17
|
-
handler = Requests::Invoke.new(self)
|
18
|
-
handler.execute(step_definition_id, args)
|
19
|
-
end
|
20
|
-
|
21
|
-
def diff_failed
|
22
|
-
handler = Requests::DiffFailed.new(self)
|
23
|
-
handler.execute
|
24
|
-
end
|
25
|
-
|
26
|
-
def diff_ok
|
27
|
-
handler = Requests::DiffOk.new(self)
|
28
|
-
handler.execute
|
29
|
-
end
|
30
|
-
|
31
|
-
def begin_scenario(scenario)
|
32
|
-
handler = Requests::BeginScenario.new(self)
|
33
|
-
handler.execute(scenario)
|
34
|
-
end
|
35
|
-
|
36
|
-
def end_scenario(scenario)
|
37
|
-
handler = Requests::EndScenario.new(self)
|
38
|
-
handler.execute(scenario)
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,133 +0,0 @@
|
|
1
|
-
require 'cucumber/wire_support/request_handler'
|
2
|
-
require 'cucumber/gherkin/formatter/argument'
|
3
|
-
|
4
|
-
module Cucumber
|
5
|
-
module WireSupport
|
6
|
-
module WireProtocol
|
7
|
-
module Requests
|
8
|
-
class StepMatches < RequestHandler
|
9
|
-
def execute(name_to_match, name_to_report)
|
10
|
-
@name_to_match, @name_to_report = name_to_match, name_to_report
|
11
|
-
request_params = {
|
12
|
-
:name_to_match => name_to_match
|
13
|
-
}
|
14
|
-
super(request_params)
|
15
|
-
end
|
16
|
-
|
17
|
-
def handle_success(params)
|
18
|
-
params.map do |raw_step_match|
|
19
|
-
create_step_match(raw_step_match)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
alias :handle_step_matches :handle_success
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def create_step_match(raw_step_match)
|
28
|
-
step_definition = WireStepDefinition.new(@connection, raw_step_match)
|
29
|
-
step_args = raw_step_match['args'].map do |raw_arg|
|
30
|
-
Cucumber::Gherkin::Formatter::Argument.new(raw_arg['pos'], raw_arg['val'])
|
31
|
-
end
|
32
|
-
step_match(step_definition, step_args)
|
33
|
-
end
|
34
|
-
|
35
|
-
def step_match(step_definition, step_args)
|
36
|
-
StepMatch.new(step_definition, @name_to_match, @name_to_report, step_args)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class SnippetText < RequestHandler
|
41
|
-
def execute(step_keyword, step_name, multiline_arg_class_name)
|
42
|
-
request_params = {
|
43
|
-
:step_keyword => step_keyword,
|
44
|
-
:step_name => step_name,
|
45
|
-
:multiline_arg_class => multiline_arg_class_name
|
46
|
-
}
|
47
|
-
super(request_params)
|
48
|
-
end
|
49
|
-
|
50
|
-
def handle_success(snippet_text)
|
51
|
-
snippet_text
|
52
|
-
end
|
53
|
-
|
54
|
-
alias :handle_snippet_text :handle_success
|
55
|
-
end
|
56
|
-
|
57
|
-
class Invoke < RequestHandler
|
58
|
-
def execute(step_definition_id, args)
|
59
|
-
request_params = {
|
60
|
-
:id => step_definition_id,
|
61
|
-
:args => args
|
62
|
-
}
|
63
|
-
super(request_params)
|
64
|
-
end
|
65
|
-
|
66
|
-
def handle_pending(message)
|
67
|
-
raise Pending, message || "TODO"
|
68
|
-
end
|
69
|
-
|
70
|
-
def handle_diff!(tables)
|
71
|
-
# TODO: figure out if / how we could get a location for a table from the wire (or make a null location)
|
72
|
-
location = Core::Ast::Location.new(__FILE__, __LINE__)
|
73
|
-
table1 = table(tables[0], location)
|
74
|
-
table2 = table(tables[1], location)
|
75
|
-
table1.diff!(table2)
|
76
|
-
end
|
77
|
-
|
78
|
-
def handle_diff(tables)
|
79
|
-
begin
|
80
|
-
handle_diff!(tables)
|
81
|
-
rescue Cucumber::MultilineArgument::DataTable::Different
|
82
|
-
@connection.diff_failed
|
83
|
-
end
|
84
|
-
@connection.diff_ok
|
85
|
-
end
|
86
|
-
|
87
|
-
alias :handle_step_failed :handle_fail
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
def table(data, location)
|
92
|
-
Cucumber::MultilineArgument.from_core(Core::Ast::DataTable.new(data, location))
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
class DiffFailed < RequestHandler
|
97
|
-
alias :handle_step_failed :handle_fail
|
98
|
-
end
|
99
|
-
|
100
|
-
class DiffOk < RequestHandler
|
101
|
-
alias :handle_step_failed :handle_fail
|
102
|
-
end
|
103
|
-
|
104
|
-
module Tags
|
105
|
-
def clean_tag_names(scenario)
|
106
|
-
scenario.tags.map { |tag| tag.name.gsub(/^@/, '') }.sort
|
107
|
-
end
|
108
|
-
|
109
|
-
def request_params(scenario)
|
110
|
-
return nil unless scenario.tags.any?
|
111
|
-
{ "tags" => clean_tag_names(scenario) }
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
class BeginScenario < RequestHandler
|
116
|
-
include Tags
|
117
|
-
|
118
|
-
def execute(scenario)
|
119
|
-
super(request_params(scenario))
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
class EndScenario < RequestHandler
|
124
|
-
include Tags
|
125
|
-
|
126
|
-
def execute(scenario)
|
127
|
-
super(request_params(scenario))
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|