cucumber-pro 0.0.11 → 0.0.12

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: aba26207747344dda383814db4114cb91cee6d20
4
- data.tar.gz: f809da648aed73a7eca530eb31391c02343b00e4
3
+ metadata.gz: 4c1ea22ade2589bfaba0ea2b8b452133995630c9
4
+ data.tar.gz: 31a0837902dfacd353adf063083d2a5c6d9d1681
5
5
  SHA512:
6
- metadata.gz: f246995c5281209a5cd2340ab3a3f3fec7cbfbc1f79cdd9d3f80769cf186e782d3677c9b360401a7d92f8a1648dab7ae1a96c6e4bb691895fadf5971b7972523
7
- data.tar.gz: 349ae812ab5017bb077a5f378370498323b7a68119bb7349025a5a4009770277f131039c8b93a645dd5e56e75521221138e467e0c4d6b2e542454d54eab05d7e
6
+ metadata.gz: 3ba8796ca612b363c444fb9308687d6dfdcc66e0620eb2d197e9461dacec93bb019cb2a5d13d9621d62753ac70113bc09b66183a02d528d4bc71e22c02b2a401
7
+ data.tar.gz: 4f3a0bf99cdd27ac75142da244443a1f5378b03e36cf66be3a2fed14db919d82d4fa5110635600b2a85d749bd0c79a74f8db810fd3503cd8b863dfcf7d197149
data/Rakefile CHANGED
@@ -25,7 +25,7 @@ desc 'Run repeated tests to check for async bugs'
25
25
  task :soak, :repetitions do |task, args|
26
26
  reps = args[:repetitions] || 10
27
27
  results = reps.to_i.times.map do
28
- `cucumber`
28
+ `rspec > tmp/test.log`
29
29
  print $? == 0 ? '.' : 'x'
30
30
  $?
31
31
  end
data/TODO.md CHANGED
@@ -1,7 +1,7 @@
1
1
  - Unit tests for Messaging
2
2
  - Handle cases where some messages sent are not ack'd with a timeout
3
3
  - Handle cases where some messages sent come back with an error
4
- - e.g. upgrade your client error
4
+ - e.g. upgrade your client error
5
5
  - Allow configuration of git remote
6
6
  - Build against Cucumber 2.0 and 1.3.x
7
7
  - SVN support
data/lib/cucumber/pro.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'logger'
2
2
  require 'cucumber/pro/formatter'
3
3
  require 'cucumber/pro/web_socket/session'
4
+ require 'cucumber/pro/errors'
4
5
 
5
6
  module Cucumber
6
7
  module Pro
@@ -8,7 +9,7 @@ module Cucumber
8
9
  class << self
9
10
  def new(runtime, output, options)
10
11
  create_logger(output)
11
- session = WebSocket::Session.new(url, logger)
12
+ session = WebSocket::Session.new(url, logger, timeout: config.timeout)
12
13
  Formatter.new(session)
13
14
  end
14
15
 
@@ -41,31 +42,18 @@ module Cucumber
41
42
  end
42
43
 
43
44
  class Config
44
- attr_accessor :url, :logger, :token
45
+ attr_accessor :url, :logger, :token, :timeout
45
46
  end
46
47
 
47
48
  # Default config
48
49
  configure do |config|
49
- config.url = ENV['CUCUMBER_PRO_URL'] || 'wss://results.cucumber.pro/ws'
50
- config.token = ENV['CUCUMBER_PRO_TOKEN']
51
- ENV['cucumber_pro_log_path'].tap do |path|
52
- config.logger = Logger.new(path) if path
50
+ config.url = ENV['CUCUMBER_PRO_URL'] || 'wss://results.cucumber.pro/ws'
51
+ config.token = ENV['CUCUMBER_PRO_TOKEN']
52
+ config.timeout = 5
53
+ if file = ENV['CUCUMBER_PRO_LOG_FILE']
54
+ config.logger = Logger.new(file)
53
55
  end
54
56
  end
55
57
 
56
- module Error
57
- AccessDenied = Class.new(StandardError) {
58
- def initialize
59
- super "Access denied."
60
- end
61
- }
62
-
63
- MissingToken = Class.new(StandardError) {
64
- def initialize
65
- super "Missing access token. Please visit https://app.cucumber.pro/api-token for instructions."
66
- end
67
- }
68
- end
69
-
70
58
  end
71
59
  end
@@ -0,0 +1,25 @@
1
+ module Cucumber
2
+ module Pro
3
+
4
+ module Error
5
+ AccessDenied = Class.new(StandardError) {
6
+ def initialize
7
+ super "Access denied."
8
+ end
9
+ }
10
+
11
+ MissingToken = Class.new(StandardError) {
12
+ def initialize
13
+ super "Missing access token. Please visit https://app.cucumber.pro/my/profile for instructions."
14
+ end
15
+ }
16
+
17
+ Timeout = Class.new(StandardError) {
18
+ def initialize
19
+ super "Timed out waiting for a reply from the Cucumber Pro server."
20
+ end
21
+ }
22
+ end
23
+
24
+ end
25
+ end
@@ -1 +1 @@
1
- 0.0.11
1
+ 0.0.12
@@ -1,6 +1,7 @@
1
1
  require 'json'
2
2
  require 'faye/websocket'
3
3
  require 'eventmachine'
4
+ require 'cucumber/pro/errors'
4
5
 
5
6
  module Cucumber
6
7
  module Pro
@@ -8,7 +9,7 @@ module Cucumber
8
9
 
9
10
  class Session
10
11
 
11
- def initialize(url, logger)
12
+ def initialize(url, logger, options)
12
13
  @url, @logger = url, logger
13
14
  create_socket = -> worker {
14
15
  ws = Faye::WebSocket::Client.new(@url, nil, ping: 15)
@@ -19,7 +20,7 @@ module Cucumber
19
20
  ws
20
21
  }
21
22
  @queue = Queue.new
22
- @socket = Worker.new(create_socket, logger, self)
23
+ @socket = Worker.new(create_socket, logger, self, options)
23
24
  end
24
25
 
25
26
  def send(message)
@@ -49,8 +50,9 @@ module Cucumber
49
50
 
50
51
  class Worker
51
52
 
52
- def initialize(create_socket, logger, error_handler)
53
+ def initialize(create_socket, logger, error_handler, options = {})
53
54
  @create_socket, @logger, @error_handler = create_socket, logger, error_handler
55
+ @timeout = options.fetch(:timeout) { raise ArgumentError("Please specify timeout") }
54
56
  @q = Queue.new
55
57
  @em = Thread.new { start_client }
56
58
  @ack_count = 0
@@ -59,8 +61,9 @@ module Cucumber
59
61
  def close
60
62
  @q << -> {
61
63
  if @ack_count == 0
62
- @ws.close
64
+ close_websocket
63
65
  else
66
+ ensure_close_timer_started
64
67
  EM.next_tick { close }
65
68
  end
66
69
  }
@@ -81,7 +84,25 @@ module Cucumber
81
84
 
82
85
  private
83
86
 
84
- attr_reader :logger, :error_handler, :next_task
87
+ attr_reader :logger, :error_handler, :next_task, :timeout
88
+
89
+ def ensure_close_timer_started
90
+ return if @close_timer
91
+ logger.debug [:ws, :set_close_timeout, timeout]
92
+ @close_timer = EM.add_timer(timeout) { handle_close_timeout }
93
+ end
94
+
95
+ def handle_close_timeout
96
+ logger.debug [:ws, :handle_close_timeout]
97
+ return unless @ws
98
+ error_handler.error Error::Timeout.new
99
+ close_websocket
100
+ end
101
+
102
+ def close_websocket
103
+ logger.debug [:ws, :close_socket]
104
+ @ws.close
105
+ end
85
106
 
86
107
  def start_client
87
108
  EM.run do
@@ -1,79 +1,103 @@
1
1
  require 'cucumber/pro/web_socket/session'
2
2
  require 'logger'
3
3
 
4
- module Cucumber::Pro::WebSocket
4
+ module Cucumber::Pro
5
+ module WebSocket
6
+
7
+ describe Worker do
8
+ let(:good_data) { double('good data') }
9
+ let(:error_handler) { double('error handler') }
10
+ let(:logger) { Logger.new(ENV['CUCUMBER_PRO_LOG_PATH'] || STDOUT) }
11
+ let!(:socket) { SpySocket.new }
12
+ let(:worker) { Worker.new(self.method(:create_fake_socket), logger, error_handler, timeout: 0.5) }
13
+
14
+ before { logger.level = Logger::DEBUG }
15
+
16
+ it "closes once all messages have been acknowledged (but not before)" do
17
+ worker.send(good_data)
18
+ worker.close
19
+ eventually do
20
+ socket.data.last.should == good_data
21
+ end
22
+ eventually do
23
+ expect( worker ).to_not be_closed
24
+ end
25
+ socket.send_ack
26
+ eventually do
27
+ expect( worker ).to be_closed
28
+ end
29
+ end
5
30
 
6
- describe Worker do
7
- let(:good_data) { double('good data') }
8
- let(:logger) { Logger.new(STDOUT) }
9
- let(:socket) { FakeSocket.new }
10
- let(:worker) { Worker.new(self.method(:create_fake_socket), logger, logger) }
31
+ it "throws an error and closes if all messages are not acknowledged within a timeout period" do
32
+ expect( error_handler ).to receive(:error).with(Error::Timeout.new)
33
+ worker.send(good_data)
34
+ worker.close
35
+ eventually do
36
+ expect( worker ).to be_closed
37
+ end
38
+ end
11
39
 
12
- before { logger.level = Logger::DEBUG }
40
+ it "throws an error if the server responds with an error"
13
41
 
14
- it "closes once all messages have been acknowledged (but not before)" do
15
- worker.send(good_data)
16
- worker.close
17
- eventually do
18
- socket.data.last.should == good_data
19
- end
20
- eventually do
21
- expect( worker ).to_not be_closed
22
- end
23
- socket.send_ack
24
- eventually do
25
- expect( worker ).to be_closed
42
+ def create_fake_socket(worker)
43
+ socket.worker = worker
44
+ EM.next_tick {
45
+ worker.method(:on_open).call(double('ws event'))
46
+ }
47
+ socket
26
48
  end
27
- end
28
49
 
29
- def create_fake_socket(worker)
30
- socket.worker = worker
31
- EM.next_tick {
32
- worker.method(:on_open).call(double('ws event'))
33
- }
34
- socket
35
- end
36
50
 
51
+ class SpySocket
52
+ include RSpec::Mocks::ExampleMethods
37
53
 
38
- class FakeSocket
39
- include RSpec::Mocks::ExampleMethods
54
+ attr_accessor :worker
55
+ attr_reader :data
40
56
 
41
- attr_accessor :worker
42
- attr_reader :data
57
+ def initialize
58
+ @q = Queue.new
59
+ end
43
60
 
44
- def initialize
45
- @data = []
46
- end
61
+ def close
62
+ worker.method(:on_close).call(ws_event(1000))
63
+ end
47
64
 
48
- def close
49
- worker.method(:on_close).call(ws_event(1000))
50
- end
65
+ def send(data)
66
+ @q << data
67
+ self
68
+ end
51
69
 
52
- def send(data)
53
- @data << data
54
- end
70
+ def send_ack
71
+ event = ws_event(1000, { 'type' => 'metadata_saved' })
72
+ worker.method(:on_message).call(event)
73
+ end
55
74
 
56
- def send_ack
57
- event = ws_event(1000, { 'type' => 'metadata_saved' })
58
- worker.method(:on_message).call(event)
59
- end
75
+ def data
76
+ @data ||= []
77
+ while !@q.empty?
78
+ @data << @q.pop
79
+ end
80
+ @data
81
+ end
82
+
83
+ private
60
84
 
61
- private
85
+ def ws_event(code, data = {})
86
+ double('ws event', code: 1000, data: data)
87
+ end
62
88
 
63
- def ws_event(code, data = {})
64
- double('ws event', code: 1000, data: data)
65
89
  end
66
- end
67
90
 
68
- require 'anticipate'
69
- include Anticipate
70
- def eventually(&block)
71
- result = nil
72
- sleeping(0.1).seconds.between_tries.failing_after(30).tries do
73
- result = block.call
91
+ require 'anticipate'
92
+ include Anticipate
93
+ def eventually(&block)
94
+ result = nil
95
+ sleeping(0.1).seconds.between_tries.failing_after(50).tries do
96
+ result = block.call
97
+ end
98
+ result
74
99
  end
75
- result
76
100
  end
77
- end
78
101
 
102
+ end
79
103
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber-pro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Wynne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-22 00:00:00.000000000 Z
11
+ date: 2014-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye-websocket
@@ -158,6 +158,7 @@ files:
158
158
  - features/support/fake_results_service.rb
159
159
  - features/support/world.rb
160
160
  - lib/cucumber/pro.rb
161
+ - lib/cucumber/pro/errors.rb
161
162
  - lib/cucumber/pro/formatter.rb
162
163
  - lib/cucumber/pro/info.rb
163
164
  - lib/cucumber/pro/scm/working_copy.rb
@@ -190,7 +191,7 @@ rubyforge_project:
190
191
  rubygems_version: 2.0.14
191
192
  signing_key:
192
193
  specification_version: 4
193
- summary: cucumber-pro-0.0.11
194
+ summary: cucumber-pro-0.0.12
194
195
  test_files:
195
196
  - features/publish_results.feature
196
197
  - features/security.feature