cucumber 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.
Files changed (78) hide show
  1. data/History.txt +30 -4
  2. data/Rakefile +11 -8
  3. data/VERSION.yml +1 -1
  4. data/bin/cucumber +1 -2
  5. data/cucumber.gemspec +40 -38
  6. data/examples/i18n/da/features/{summering.feature → sammenlaegning.feature} +5 -5
  7. data/examples/i18n/da/features/step_definitons/{kalkulator_steps.rb → lommeregner_steps.rb} +3 -3
  8. data/examples/i18n/da/lib/{kalkulator.rb → lommeregner.rb} +2 -2
  9. data/examples/tickets/Rakefile +5 -1
  10. data/examples/tickets/features.html +138 -0
  11. data/examples/watir/Rakefile +4 -0
  12. data/examples/watir/features/{step_definitons → step_definitions}/search_steps.rb +0 -0
  13. data/examples/watir/features/support/screenshots.rb +45 -0
  14. data/features/announce.feature +122 -0
  15. data/features/html_formatter/a.html +1 -1
  16. data/features/step_definitions/cucumber_steps.rb +1 -1
  17. data/features/step_definitions/wire_steps.rb +14 -0
  18. data/features/support/env.rb +1 -1
  19. data/features/support/fake_wire_server.rb +63 -0
  20. data/features/tag_logic.feature +226 -0
  21. data/features/wire_protocol.feature +177 -0
  22. data/lib/cucumber/ast/examples.rb +4 -0
  23. data/lib/cucumber/ast/feature_element.rb +2 -1
  24. data/lib/cucumber/ast/scenario_outline.rb +4 -0
  25. data/lib/cucumber/ast/table.rb +13 -8
  26. data/lib/cucumber/ast/tags.rb +56 -12
  27. data/lib/cucumber/ast/tree_walker.rb +6 -0
  28. data/lib/cucumber/cli/main.rb +7 -5
  29. data/lib/cucumber/cli/options.rb +19 -10
  30. data/lib/cucumber/filter.rb +1 -2
  31. data/lib/cucumber/formatter/ansicolor.rb +17 -2
  32. data/lib/cucumber/formatter/console.rb +50 -32
  33. data/lib/cucumber/formatter/html.rb +21 -1
  34. data/lib/cucumber/formatter/junit.rb +8 -0
  35. data/lib/cucumber/formatter/pretty.rb +3 -0
  36. data/lib/cucumber/formatter/summary.rb +35 -0
  37. data/lib/cucumber/formatter/usage.rb +4 -4
  38. data/lib/cucumber/rails/active_record.rb +18 -10
  39. data/lib/cucumber/rb_support/rb_language.rb +7 -2
  40. data/lib/cucumber/rb_support/rb_world.rb +4 -0
  41. data/lib/cucumber/step_match.rb +3 -2
  42. data/lib/cucumber/step_mother.rb +6 -1
  43. data/lib/cucumber/wire_support/connection.rb +42 -0
  44. data/lib/cucumber/wire_support/request_handler.rb +19 -0
  45. data/lib/cucumber/wire_support/wire_exception.rb +10 -0
  46. data/lib/cucumber/wire_support/wire_language.rb +52 -0
  47. data/lib/cucumber/wire_support/wire_packet.rb +34 -0
  48. data/lib/cucumber/wire_support/wire_protocol.rb +64 -0
  49. data/lib/cucumber/wire_support/wire_step_definition.rb +21 -0
  50. data/rails_generators/cucumber/cucumber_generator.rb +7 -4
  51. data/rails_generators/cucumber/templates/cucumber_environment.rb +4 -4
  52. data/rails_generators/cucumber/templates/version_check.rb +6 -4
  53. data/spec/cucumber/ast/table_spec.rb +11 -1
  54. data/spec/cucumber/ast/tags_spec.rb +29 -0
  55. data/spec/cucumber/cli/options_spec.rb +8 -4
  56. data/spec/cucumber/formatter/junit_spec.rb +11 -0
  57. data/spec/cucumber/step_match_spec.rb +11 -0
  58. data/spec/cucumber/wire_support/wire_language_spec.rb +47 -0
  59. data/spec/cucumber/wire_support/wire_packet_spec.rb +26 -0
  60. metadata +38 -36
  61. data/examples/cs/.gitignore +0 -1
  62. data/examples/cs/README.textile +0 -1
  63. data/examples/cs/Rakefile +0 -12
  64. data/examples/cs/compile.bat +0 -1
  65. data/examples/cs/features/addition.feature +0 -16
  66. data/examples/cs/features/step_definitons/calculator_steps.rb +0 -19
  67. data/examples/cs/src/demo/Calculator.cs +0 -20
  68. data/examples/java/.gitignore +0 -1
  69. data/examples/java/README.textile +0 -18
  70. data/examples/java/build.xml +0 -33
  71. data/examples/java/features/hello.feature +0 -11
  72. data/examples/java/features/step_definitons/hello_steps.rb +0 -23
  73. data/examples/java/features/step_definitons/tree_steps.rb +0 -14
  74. data/examples/java/features/tree.feature +0 -9
  75. data/examples/java/src/.gitignore +0 -1
  76. data/examples/java/src/cucumber/demo/.gitignore +0 -1
  77. data/examples/java/src/cucumber/demo/Hello.java +0 -16
  78. data/examples/pure_java/README.textile +0 -5
@@ -0,0 +1,42 @@
1
+ require 'timeout'
2
+ require 'cucumber/wire_support/wire_protocol'
3
+
4
+ module Cucumber
5
+ module WireSupport
6
+ class Connection
7
+ include WireProtocol
8
+
9
+ def initialize(config)
10
+ @host, @port = config['host'], config['port']
11
+ end
12
+
13
+ def call_remote(response_handler, message, params)
14
+ timeout = 3
15
+ packet = WirePacket.new(message, params)
16
+
17
+ begin
18
+ send_data_to_socket(packet.to_json, timeout)
19
+ response = fetch_data_from_socket(timeout)
20
+ response.handle_with(response_handler)
21
+ rescue Timeout::Error
22
+ raise "Timed out calling server with message #{message}"
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def send_data_to_socket(data, timeout)
29
+ Timeout.timeout(timeout) { socket.puts(data) }
30
+ end
31
+
32
+ def fetch_data_from_socket(timeout)
33
+ raw_response = Timeout.timeout(timeout) { socket.gets }
34
+ WirePacket.parse(raw_response)
35
+ end
36
+
37
+ def socket
38
+ @socket ||= TCPSocket.new(@host, @port)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,19 @@
1
+ module Cucumber
2
+ module WireSupport
3
+ class RequestHandler
4
+ def initialize(connection, message, &block)
5
+ @connection = connection
6
+ @message = message
7
+ instance_eval(&block) if block
8
+ end
9
+
10
+ def execute(request_params)
11
+ @connection.call_remote(self, @message, request_params)
12
+ end
13
+
14
+ def handle_fail(params)
15
+ raise WireException.new(params)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
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
+ def initialize(args)
6
+ super args['message']
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,52 @@
1
+ require 'socket'
2
+ require 'json'
3
+ require 'cucumber/wire_support/connection'
4
+ require 'cucumber/wire_support/wire_packet'
5
+ require 'cucumber/wire_support/wire_exception'
6
+ require 'cucumber/wire_support/wire_step_definition'
7
+
8
+ module Cucumber
9
+ module WireSupport
10
+
11
+ # The wire-protocol (lanugage independent) implementation of the programming language API.
12
+ class WireLanguage
13
+ include LanguageSupport::LanguageMethods
14
+
15
+ def load_code_file(wire_file)
16
+ config = YAML.load_file(wire_file)
17
+ @connections << Connection.new(config)
18
+ end
19
+
20
+ def step_matches(step_name, formatted_step_name)
21
+ @connections.map{ |remote| remote.step_matches(step_name, formatted_step_name)}.flatten
22
+ end
23
+
24
+ def initialize(step_mother)
25
+ @connections = []
26
+ end
27
+
28
+ def alias_adverbs(adverbs)
29
+ end
30
+
31
+ def snippet_text(step_keyword, step_name, multiline_arg_class)
32
+ "Snippets are not implemented for the wire yet"
33
+ end
34
+
35
+ protected
36
+
37
+ def begin_scenario
38
+ @connections.each { |remote| remote.begin_scenario }
39
+ end
40
+
41
+ def end_scenario
42
+ @connections.each { |remote| remote.end_scenario }
43
+ end
44
+
45
+ private
46
+
47
+ def step_definitions
48
+ @step_definitions ||= {}
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,34 @@
1
+ module Cucumber
2
+ module WireSupport
3
+ # Represents the packet of data sent over the wire as JSON data, containing
4
+ # a message and a hash of arguments
5
+ class WirePacket
6
+ class << self
7
+ def parse(raw)
8
+ attributes = JSON.parse(raw.strip)
9
+ message = attributes[0]
10
+ params = attributes[1]
11
+ new(message, params)
12
+ end
13
+ end
14
+
15
+ attr_reader :message, :params
16
+
17
+ def initialize(message, params)
18
+ @message, @params = message, params
19
+ end
20
+
21
+ def to_json
22
+ [@message, @params].to_json
23
+ end
24
+
25
+ def raise_if_bad
26
+ raise WireException.new(@params) if @message == 'fail' || @message == 'step_failed'
27
+ end
28
+
29
+ def handle_with(handler)
30
+ handler.send("handle_#{@message}", @params)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,64 @@
1
+ require 'cucumber/step_argument'
2
+ require 'cucumber/wire_support/request_handler'
3
+
4
+ module Cucumber
5
+ module WireSupport
6
+ module WireProtocol
7
+ def step_matches(name_to_match, name_to_report)
8
+ @name_to_match, @name_to_report = name_to_match, name_to_report
9
+ make_request(:step_matches, :name_to_match => name_to_match) do
10
+ def handle_step_matches(params)
11
+ params.map do |raw_step_match|
12
+ step_definition = WireStepDefinition.new(raw_step_match['id'], @connection)
13
+ step_args = raw_step_match['args'].map do |raw_arg|
14
+ StepArgument.new(raw_arg['val'], raw_arg['pos'])
15
+ end
16
+ @connection.step_match(step_definition, step_args) # convoluted!
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def step_match(step_definition, step_args)
23
+ StepMatch.new(step_definition, @name_to_match, @name_to_report, step_args)
24
+ end
25
+
26
+ def invoke(step_definition_id, args)
27
+ request_params = { :id => step_definition_id, :args => args }
28
+
29
+ make_request(:invoke, request_params) do
30
+ def handle_success(params)
31
+ end
32
+
33
+ def handle_step_failed(params)
34
+ handle_fail(params)
35
+ end
36
+ end
37
+ end
38
+
39
+ def begin_scenario
40
+ make_request(:begin_scenario) do
41
+ def handle_success(params)
42
+ end
43
+ end
44
+ end
45
+
46
+ def end_scenario
47
+ make_request(:end_scenario) do
48
+ def handle_success(params)
49
+ end
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def handler(request_message, &block)
56
+ RequestHandler.new(self, request_message, &block)
57
+ end
58
+
59
+ def make_request(request_message, params = nil, &block)
60
+ handler(request_message, &block).execute(params)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,21 @@
1
+ module Cucumber
2
+ module WireSupport
3
+ class WireStepDefinition
4
+ def initialize(id, connection)
5
+ @id, @connection = id, connection
6
+ end
7
+
8
+ def invoke(args)
9
+ @connection.invoke(@id, args)
10
+ end
11
+
12
+ def regexp_source
13
+ "/FIXME/"
14
+ end
15
+
16
+ def file_colon_line
17
+ "FIXME:0"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -76,18 +76,21 @@ protected
76
76
  end
77
77
 
78
78
  def after_generate
79
+ require 'cucumber/formatter/ansicolor'
80
+ extend Cucumber::Formatter::ANSIColor
81
+
79
82
  if @default_framework
80
83
  puts <<-WARNING
81
84
 
82
- (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::)
85
+ #{yellow_cukes(15)}
83
86
 
84
- (::) T E S T F R A M E W O R K A L E R T (::)
87
+ #{yellow_cukes(1)} T E S T F R A M E W O R K A L E R T #{yellow_cukes(1)}
85
88
 
86
89
  You didn't explicitly generate with --rspec or --testunit, so I looked at
87
- your gems and saw that you had #{@default_framework} installed, so I went with that.
90
+ your gems and saw that you had #{green(@default_framework.to_s)} installed, so I went with that.
88
91
  If you want something else, be specific about it. Otherwise, relax.
89
92
 
90
- (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::)
93
+ #{yellow_cukes(15)}
91
94
 
92
95
  WARNING
93
96
  end
@@ -20,11 +20,11 @@ config.action_controller.allow_forgery_protection = false
20
20
  config.action_mailer.delivery_method = :test
21
21
 
22
22
  config.gem 'cucumber', :lib => false, :version => '>=<%= cucumber_version %>' unless File.directory?(File.join(Rails.root, 'vendor/plugins/cucumber'))
23
- config.gem 'webrat', :lib => false, :version => '>=0.5.0' unless File.directory?(File.join(Rails.root, 'vendor/plugins/webrat'))
23
+ config.gem 'webrat', :lib => false, :version => '>=0.5.3' unless File.directory?(File.join(Rails.root, 'vendor/plugins/webrat'))
24
24
  <% if framework == :rspec -%>
25
- config.gem 'rspec', :lib => false, :version => '>=1.2.8' unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec'))
26
- config.gem 'rspec-rails', :lib => false, :version => '>=1.2.7.1' unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails'))
25
+ config.gem 'rspec', :lib => false, :version => '>=1.2.9' unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec'))
26
+ config.gem 'rspec-rails', :lib => false, :version => '>=1.2.9' unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails'))
27
27
  <% end %>
28
28
  <% if spork? -%>
29
- config.gem 'spork', :lib => false, :version => '>=0.7.2' unless File.directory?(File.join(Rails.root, 'vendor/plugins/spork'))
29
+ config.gem 'spork', :lib => false, :version => '>=0.7.3' unless File.directory?(File.join(Rails.root, 'vendor/plugins/spork'))
30
30
  <% end %>
@@ -1,8 +1,10 @@
1
+ require 'cucumber/formatter/ansicolor'
2
+ extend Cucumber::Formatter::ANSIColor
1
3
  if Cucumber::VERSION != '<%= Cucumber::VERSION %>'
2
4
  warning = <<-WARNING
3
- (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::)
5
+ #{red_cukes(15)}
4
6
 
5
- (::) R O T T E N C U C U M B E R A L E R T (::)
7
+ #{red_cukes(1)} R O T T E N C U C U M B E R A L E R T #{red_cukes(1)}
6
8
 
7
9
  Your #{__FILE__.gsub(/version_check.rb$/, 'env.rb')} file was generated with Cucumber <%= Cucumber::VERSION %>,
8
10
  but you seem to be running Cucumber #{Cucumber::VERSION}. If you're running an older
@@ -18,11 +20,11 @@ version than #{Cucumber::VERSION} you should:
18
20
  If you get prompted to replace a file, hit 'd' to see the difference.
19
21
  When you're sure you have captured any personal edits, confirm that you
20
22
  want to overwrite #{__FILE__.gsub(/version_check.rb$/, 'env.rb')} by pressing 'y'. Then reapply any
21
- personal changes that may have been overwritten.
23
+ personal changes that may have been overwritten, preferably in separate files.
22
24
 
23
25
  This message will then self destruct.
24
26
 
25
- (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::)
27
+ #{red_cukes(15)}
26
28
  WARNING
27
29
  warn(warning)
28
30
  at_exit {warn(warning)}
@@ -393,7 +393,17 @@ module Cucumber
393
393
  @table_parser.parse_or_fail(text.strip, file, line_offset)
394
394
  end
395
395
  end
396
-
396
+
397
+ describe "#new" do
398
+ it "should allow Array of Hash" do
399
+ t1 = Table.new([{'name' => 'aslak', 'male' => 'true'}])
400
+ t1.to_s(:indent => 12, :color => false).should == %{
401
+ | name | male |
402
+ | aslak | true |
403
+ }
404
+ end
405
+ end
406
+
397
407
  it "should convert to sexp" do
398
408
  @table.to_sexp.should ==
399
409
  [:table,
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require 'cucumber/ast/tags'
3
+
4
+ module Cucumber
5
+ module Ast
6
+ describe Tags do
7
+ describe "#matches" do
8
+ it "should AND tags which are are in a list" do
9
+ Tags.matches?(['@one','@two','@three'], [['@one','@two']]).should == true
10
+ Tags.matches?(['@one','@three'], [['@one','@two']]).should == false
11
+ end
12
+
13
+ it "should OR tags in different lists" do
14
+ Tags.matches?(['@one'], [['@one'], ['@two']]).should == true
15
+ end
16
+
17
+ it "should AND and OR tags" do
18
+ Tags.matches?(['@one','@two'], [['@one'],['@two','@four']]).should == true
19
+ end
20
+
21
+ it "should NOT tags" do
22
+ Tags.matches?(['@one','@three'], [['@one', '~@two']]).should == true
23
+ Tags.matches?(['@one','@three'], [['~@one']]).should == false
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -85,7 +85,7 @@ module Cli
85
85
  after_parsing('-o file.txt') { options[:formats].should == [['pretty', 'file.txt']] }
86
86
  end
87
87
  it "sets the output for the formatter defined immediatly before it" do
88
- after_parsing('-f profile --out file.txt -f pretty -o file2.txt') do
88
+ after_parsing('-f profile --out file.txt -f pretty -o file2.txt') do
89
89
  options[:formats].should == [['profile', 'file.txt'], ['pretty', 'file2.txt']]
90
90
  end
91
91
  end
@@ -93,7 +93,11 @@ module Cli
93
93
 
94
94
  context '-t TAGS --tags TAGS' do
95
95
  it "designates tags prefixed with ~ as tags to be excluded" do
96
- after_parsing('--tags ~@foo,@bar') { options[:tag_names].should == {'~@foo' => nil, '@bar' => nil} }
96
+ after_parsing('--tags ~@foo,@bar') { options[:tag_names].should == [{'~@foo' => nil, '@bar' => nil}] }
97
+ end
98
+
99
+ it "stores tags passed with different --tags seperately" do
100
+ after_parsing('--tags @foo --tags @bar') { options[:tag_names].should == [{'@foo' => nil}, {'@bar' => nil}] }
97
101
  end
98
102
  end
99
103
 
@@ -160,7 +164,7 @@ module Cli
160
164
  it "combines the tag names of both" do
161
165
  given_cucumber_yml_defined_as('baz' => %w[-t @bar])
162
166
  options.parse!(%w[--tags @foo -p baz])
163
- options[:tag_names].should == {'@foo' => nil, '@bar' => nil}
167
+ options[:tag_names].should == [{'@foo' => nil}, {'@bar' => nil}]
164
168
  end
165
169
 
166
170
  it "only takes the paths from the original options, and disgregards the profiles" do
@@ -286,7 +290,7 @@ module Cli
286
290
 
287
291
  describe '#expanded_args_without_drb' do
288
292
  it "returns the orginal args in additon to the args from any profiles" do
289
- given_cucumber_yml_defined_as('foo' => '-v',
293
+ given_cucumber_yml_defined_as('foo' => '-v',
290
294
  'bar' => '--wip -p baz',
291
295
  'baz' => '-r some_file.rb')
292
296
  options.parse!(%w[features -p foo --profile bar])
@@ -22,6 +22,17 @@ module Cucumber::Formatter
22
22
  File.stub!(:directory?).and_return(true)
23
23
  @formatter = TestDoubleJunitFormatter.new(step_mother, '', {})
24
24
  end
25
+
26
+ describe "a feature with no name" do
27
+ define_feature <<-FEATURE
28
+ Scenario: Passing
29
+ Given a passing scenario
30
+ FEATURE
31
+
32
+ it "should raise an exception" do
33
+ lambda { run_defined_feature }.should raise_error(Junit::UnNamedFeatureError)
34
+ end
35
+ end
25
36
 
26
37
  describe "given a single feature" do
27
38
  before(:each) do
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require File.dirname(__FILE__) + '/../spec_helper'
2
3
  require 'cucumber/rb_support/rb_step_definition'
3
4
  require 'cucumber/rb_support/rb_language'
@@ -17,6 +18,16 @@ module Cucumber
17
18
  StepMatch.new(stepdef, name, nil, stepdef.arguments_from(name))
18
19
  end
19
20
 
21
+ it "should format one groups when we use Unicode" do
22
+ m = step_match(/I (\w+) ok/, "I æøåÆØÅæøåÆØÅæøåÆØÅæøåÆØÅ ok")
23
+ m.format_args("<span>%s</span>").should == "I <span>æøåÆØÅæøåÆØÅæøåÆØÅæøåÆØÅ</span> ok"
24
+ end
25
+
26
+ it "should format several groups when we use Unicode" do
27
+ m = step_match(/I (\w+) (\w+) (\w+) this (\w+)/, "I ate æøåÆØÅæøåÆØÅæøåÆØÅæøåÆØÅ egg this morning")
28
+ m.format_args("<span>%s</span>").should == "I <span>ate</span> <span>æøåÆØÅæøåÆØÅæøåÆØÅæøåÆØÅ</span> <span>egg</span> this <span>morning</span>"
29
+ end
30
+
20
31
  it "should format groups with format string" do
21
32
  m = step_match(/I (\w+) (\d+) (\w+) this (\w+)/, "I ate 1 egg this morning")
22
33
  m.format_args("<span>%s</span>").should == "I <span>ate</span> <span>1</span> <span>egg</span> this <span>morning</span>"