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 +4 -4
- data/Rakefile +1 -1
- data/TODO.md +1 -1
- data/lib/cucumber/pro.rb +8 -20
- data/lib/cucumber/pro/errors.rb +25 -0
- data/lib/cucumber/pro/version +1 -1
- data/lib/cucumber/pro/web_socket/session.rb +26 -5
- data/spec/cucumber/pro/web_socket/worker_spec.rb +80 -56
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c1ea22ade2589bfaba0ea2b8b452133995630c9
|
4
|
+
data.tar.gz: 31a0837902dfacd353adf063083d2a5c6d9d1681
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ba8796ca612b363c444fb9308687d6dfdcc66e0620eb2d197e9461dacec93bb019cb2a5d13d9621d62753ac70113bc09b66183a02d528d4bc71e22c02b2a401
|
7
|
+
data.tar.gz: 4f3a0bf99cdd27ac75142da244443a1f5378b03e36cf66be3a2fed14db919d82d4fa5110635600b2a85d749bd0c79a74f8db810fd3503cd8b863dfcf7d197149
|
data/Rakefile
CHANGED
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
|
-
|
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
|
50
|
-
config.token
|
51
|
-
|
52
|
-
|
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
|
data/lib/cucumber/pro/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
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
|
-
|
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
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
40
|
+
it "throws an error if the server responds with an error"
|
13
41
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
39
|
-
|
54
|
+
attr_accessor :worker
|
55
|
+
attr_reader :data
|
40
56
|
|
41
|
-
|
42
|
-
|
57
|
+
def initialize
|
58
|
+
@q = Queue.new
|
59
|
+
end
|
43
60
|
|
44
|
-
|
45
|
-
|
46
|
-
|
61
|
+
def close
|
62
|
+
worker.method(:on_close).call(ws_event(1000))
|
63
|
+
end
|
47
64
|
|
48
|
-
|
49
|
-
|
50
|
-
|
65
|
+
def send(data)
|
66
|
+
@q << data
|
67
|
+
self
|
68
|
+
end
|
51
69
|
|
52
|
-
|
53
|
-
|
54
|
-
|
70
|
+
def send_ack
|
71
|
+
event = ws_event(1000, { 'type' => 'metadata_saved' })
|
72
|
+
worker.method(:on_message).call(event)
|
73
|
+
end
|
55
74
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
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
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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.
|
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-
|
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.
|
194
|
+
summary: cucumber-pro-0.0.12
|
194
195
|
test_files:
|
195
196
|
- features/publish_results.feature
|
196
197
|
- features/security.feature
|