cucumber 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
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>"