cucumber-pro 0.0.2 → 0.0.4
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/TODO.md +7 -2
- data/cucumber-pro.gemspec +2 -4
- data/features/publish_results.feature +6 -0
- data/features/security.feature +27 -0
- data/features/step_definitions/steps.rb +2 -0
- data/features/support/fake_results_service.rb +1 -2
- data/lib/cucumber/pro.rb +20 -1
- data/lib/cucumber/pro/scm.rb +10 -5
- data/lib/cucumber/pro/version +1 -0
- data/lib/cucumber/pro/web_socket_session.rb +76 -64
- data/tmp/.gitkeep +0 -0
- metadata +11 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c90f1ff93aa0791fcc5726992f81678704506523
|
4
|
+
data.tar.gz: 4db71bb9349a648e404e787a4f808af24764b9c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52b7ef6e162dc95d32a8b48b8e3b2d67c82da83a48da92667b926d8478d9db2588a4d609e71c1f6b8f74fc3cda3de582141ed8d42882df329f0fd4b38ae10065
|
7
|
+
data.tar.gz: 66d5412d15be33487e3a4cd163d70d1f9c2666dfda7074e1fac89dc86113d5d4f8d8bea66c3868b665ab24cb1eda6eb3a4b5dc6bf4fcdfe1834e0e8df249c610
|
data/TODO.md
CHANGED
@@ -1,4 +1,9 @@
|
|
1
1
|
- Scenario for when the token is invalid
|
2
|
-
-
|
3
|
-
-
|
2
|
+
- Scenario for when branch is invalid
|
3
|
+
- Branch has a * in it
|
4
|
+
- Better (more unique) run ID - use a UUID
|
5
|
+
- Log to Cucumber's IO instead of STDOUT by default
|
6
|
+
- Unit tests for Messaging
|
7
|
+
- Handle cases where some messages sent are not ack'd
|
8
|
+
- Handle cases where some messages sent come back with an error
|
4
9
|
|
data/cucumber-pro.gemspec
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
3
|
-
require "cucumber/pro/version"
|
4
3
|
|
5
4
|
Gem::Specification.new do |s|
|
6
5
|
s.name = 'cucumber-pro'
|
7
|
-
s.version =
|
6
|
+
s.version = File.read(File.expand_path("../lib/cucumber/pro/version", __FILE__))
|
8
7
|
s.authors = ["Matt Wynne"]
|
9
8
|
s.description = "Client library for publishing results to the Cucumber Pro service"
|
10
9
|
s.summary = "cucumber-pro-#{s.version}"
|
@@ -14,8 +13,7 @@ Gem::Specification.new do |s|
|
|
14
13
|
s.license = "MIT"
|
15
14
|
s.required_ruby_version = ">= 1.9.3"
|
16
15
|
|
17
|
-
s.add_dependency '
|
18
|
-
s.add_dependency 'faye-websocket'
|
16
|
+
s.add_dependency 'faye-websocket', '~> 0.7'
|
19
17
|
|
20
18
|
s.add_development_dependency 'bundler', '>= 1.3.5'
|
21
19
|
s.add_development_dependency 'rake', '>= 0.9.2'
|
@@ -1,6 +1,11 @@
|
|
1
1
|
@announce
|
2
2
|
Feature: Publish results
|
3
3
|
|
4
|
+
Background:
|
5
|
+
Given I set the environment variables to:
|
6
|
+
| variable | value |
|
7
|
+
| CUCUMBER_PRO_TOKEN | valid-token |
|
8
|
+
|
4
9
|
Scenario: A couple of scenarios
|
5
10
|
Given a git repo
|
6
11
|
And a feature "features/test.feature" with:
|
@@ -22,6 +27,7 @@ Feature: Publish results
|
|
22
27
|
| status | path | location |
|
23
28
|
| passed | features/test.feature | 2 |
|
24
29
|
| failed | features/test.feature | 5 |
|
30
|
+
And the stderr should not contain anything
|
25
31
|
|
26
32
|
Scenario: A scenario outline
|
27
33
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
@announce
|
2
|
+
Feature: Security
|
3
|
+
|
4
|
+
Scenario: Bad access token
|
5
|
+
Given a git repo
|
6
|
+
And a feature "features/test.feature" with:
|
7
|
+
"""
|
8
|
+
Feature:
|
9
|
+
Scenario:
|
10
|
+
Given passing
|
11
|
+
"""
|
12
|
+
When I set the environment variables to:
|
13
|
+
| variable | value |
|
14
|
+
| CUCUMBER_PRO_TOKEN | invalid-token |
|
15
|
+
And I run `cucumber -f Cucumber::Pro -o /dev/null -f pretty`
|
16
|
+
And the stderr should contain "Access denied"
|
17
|
+
|
18
|
+
Scenario: No access token
|
19
|
+
Given a git repo
|
20
|
+
And a feature "features/test.feature" with:
|
21
|
+
"""
|
22
|
+
Feature:
|
23
|
+
Scenario:
|
24
|
+
Given passing
|
25
|
+
"""
|
26
|
+
When I run `cucumber -f Cucumber::Pro -o /dev/null -f pretty`
|
27
|
+
And the stderr should contain "Missing access token"
|
@@ -11,6 +11,8 @@ end
|
|
11
11
|
|
12
12
|
Given(/^a git repo$/) do
|
13
13
|
run_simple "git init"
|
14
|
+
run_simple "git config user.email \"test@test.com\""
|
15
|
+
run_simple "git config user.name \"Test user\""
|
14
16
|
run_simple "git commit --allow-empty -m 'Initial commit'"
|
15
17
|
run_simple "git remote add origin #{repo_url}"
|
16
18
|
run_simple "git config --get remote.origin.url"
|
@@ -3,7 +3,7 @@ require 'json'
|
|
3
3
|
|
4
4
|
module FakeResultsService
|
5
5
|
PORT = 5000
|
6
|
-
VALID_TOKEN = 'valid-
|
6
|
+
VALID_TOKEN = 'valid-token'
|
7
7
|
|
8
8
|
class << self
|
9
9
|
def messages
|
@@ -91,7 +91,6 @@ else
|
|
91
91
|
require 'cucumber/pro'
|
92
92
|
Cucumber::Pro.configure do |c|
|
93
93
|
c.url = 'ws://localhost:#{FakeResultsService::PORT}'
|
94
|
-
c.token = "#{FakeResultsService::VALID_TOKEN}"
|
95
94
|
end
|
96
95
|
END
|
97
96
|
end
|
data/lib/cucumber/pro.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'cucumber/pro/formatter'
|
3
3
|
require 'cucumber/pro/web_socket_session'
|
4
|
+
require 'cucumber/pro/version'
|
4
5
|
|
5
6
|
module Cucumber
|
6
7
|
module Pro
|
7
8
|
|
8
9
|
class << self
|
9
10
|
def new(*)
|
10
|
-
url = config.url + "?token=#{config.token}"
|
11
11
|
session = WebSocketSession.new(url, config.logger)
|
12
12
|
Formatter.new(session)
|
13
13
|
end
|
@@ -21,6 +21,11 @@ module Cucumber
|
|
21
21
|
def config
|
22
22
|
@config ||= Config.new
|
23
23
|
end
|
24
|
+
|
25
|
+
def url
|
26
|
+
token = config.token || raise(Error::MissingToken.new)
|
27
|
+
config.url + "?token=#{token}"
|
28
|
+
end
|
24
29
|
end
|
25
30
|
|
26
31
|
class Config
|
@@ -34,6 +39,20 @@ module Cucumber
|
|
34
39
|
config.token = ENV['CUCUMBER_PRO_TOKEN']
|
35
40
|
end
|
36
41
|
|
42
|
+
module Error
|
43
|
+
AccessDenied = Class.new(StandardError) {
|
44
|
+
def initialize
|
45
|
+
super "Access denied."
|
46
|
+
end
|
47
|
+
}
|
48
|
+
|
49
|
+
MissingToken = Class.new(StandardError) {
|
50
|
+
def initialize
|
51
|
+
super "Missing access token. Please visit https://app.cucumber.pro/api-token for instructions."
|
52
|
+
end
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
37
56
|
end
|
38
57
|
end
|
39
58
|
|
data/lib/cucumber/pro/scm.rb
CHANGED
@@ -3,7 +3,6 @@ module Cucumber
|
|
3
3
|
|
4
4
|
module Scm
|
5
5
|
|
6
|
-
require 'grit'
|
7
6
|
class Repo
|
8
7
|
|
9
8
|
NoGitRepoFound = Class.new(StandardError)
|
@@ -18,19 +17,25 @@ module Cucumber
|
|
18
17
|
end
|
19
18
|
|
20
19
|
def initialize(path)
|
21
|
-
@
|
20
|
+
@path = path
|
22
21
|
end
|
23
22
|
|
24
23
|
def remote
|
25
|
-
|
24
|
+
cmd('git config --get remote.origin.url')
|
26
25
|
end
|
27
26
|
|
28
27
|
def branch
|
29
|
-
|
28
|
+
cmd("git branch --contains #{rev}")
|
30
29
|
end
|
31
30
|
|
32
31
|
def rev
|
33
|
-
|
32
|
+
cmd("git rev-parse HEAD")
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def cmd(cmd)
|
38
|
+
Dir.chdir(@path) { `#{cmd}` }.strip
|
34
39
|
end
|
35
40
|
end
|
36
41
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
0.0.4
|
@@ -4,106 +4,118 @@ require 'eventmachine'
|
|
4
4
|
|
5
5
|
module Cucumber
|
6
6
|
module Pro
|
7
|
-
module Error
|
8
|
-
AccessDenied = Class.new(StandardError) {
|
9
|
-
def initialize
|
10
|
-
super "Access denied."
|
11
|
-
end
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
7
|
class WebSocketSession
|
16
8
|
|
17
|
-
|
18
|
-
class SendMessage
|
19
|
-
def initialize(data)
|
20
|
-
@data = data
|
21
|
-
end
|
22
|
-
|
23
|
-
def send_to(ws)
|
24
|
-
ws.send(@data.to_json)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class Close
|
29
|
-
def send_to(ws)
|
30
|
-
ws.close
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
9
|
def initialize(url, logger)
|
35
10
|
@url, @logger = url, logger
|
36
11
|
@queue = Queue.new
|
37
|
-
|
12
|
+
@socket = SocketWorker.new(url, logger, self) do
|
13
|
+
queue.pop.call if !queue.empty?
|
14
|
+
end
|
38
15
|
end
|
39
16
|
|
40
17
|
def send(message)
|
41
18
|
logger.debug [:session, :send, message]
|
42
|
-
queue.push
|
19
|
+
queue.push -> { socket.send(message.to_json) }
|
20
|
+
self
|
43
21
|
end
|
44
22
|
|
45
23
|
def close
|
46
24
|
logger.debug [:session, :close]
|
47
|
-
queue.push
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
25
|
+
queue.push -> { socket.close }
|
26
|
+
loop until socket.closed?
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def error(exception)
|
31
|
+
logger.fatal exception
|
32
|
+
$stderr.puts "Cucumber Pro failed to send results: #{exception}"
|
33
|
+
$stderr.puts exception.backtrace.join("\n")
|
34
|
+
self
|
52
35
|
end
|
53
36
|
|
54
37
|
private
|
55
38
|
|
56
|
-
attr_reader :logger, :queue
|
39
|
+
attr_reader :logger, :queue, :socket
|
57
40
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
@ws_error = exception
|
65
|
-
end
|
41
|
+
class SocketWorker
|
42
|
+
|
43
|
+
def initialize(url, logger, error_handler, &next_task)
|
44
|
+
@url, @logger, @error_handler = url, logger, error_handler
|
45
|
+
@next_task = next_task
|
46
|
+
@em = Thread.new { start_client }
|
66
47
|
end
|
67
|
-
end
|
68
48
|
|
69
|
-
|
70
|
-
|
71
|
-
|
49
|
+
def close
|
50
|
+
@ws.close
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def send(data)
|
55
|
+
@ws.send data
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
def closed?
|
60
|
+
!@em.alive?
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
attr_reader :logger, :error_handler, :next_task
|
72
66
|
|
73
|
-
|
67
|
+
def start_client
|
68
|
+
EM.run do
|
69
|
+
logger.debug [:ws, :start]
|
70
|
+
@ws = Faye::WebSocket::Client.new(@url)
|
71
|
+
@ws.on :open, &self.method(:on_open)
|
72
|
+
@ws.on :error, &self.method(:on_error)
|
73
|
+
@ws.on :message, &self.method(:on_message)
|
74
|
+
@ws.on :close, &self.method(:on_close)
|
75
|
+
end
|
76
|
+
self
|
77
|
+
rescue => exception
|
78
|
+
error_handler.error exception
|
79
|
+
end
|
80
|
+
|
81
|
+
def on_open(event)
|
74
82
|
logger.debug [:ws, :open]
|
75
|
-
|
83
|
+
process_tasks
|
84
|
+
self
|
76
85
|
end
|
77
86
|
|
78
|
-
|
87
|
+
def on_error(event)
|
79
88
|
logger.error [:ws, :error]
|
89
|
+
self
|
80
90
|
end
|
81
91
|
|
82
|
-
|
92
|
+
def on_message(event)
|
83
93
|
logger.debug [:ws, :message, event.data]
|
94
|
+
self
|
84
95
|
end
|
85
96
|
|
86
|
-
|
97
|
+
def on_close(event)
|
87
98
|
logger.debug [:ws, :close]
|
88
|
-
|
89
|
-
|
99
|
+
if access_denied?(event)
|
100
|
+
raise Error::AccessDenied.new
|
101
|
+
end
|
102
|
+
@ws = nil
|
90
103
|
EM.stop_event_loop
|
104
|
+
self
|
91
105
|
end
|
92
|
-
self
|
93
|
-
end
|
94
106
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
107
|
+
def process_tasks
|
108
|
+
next_task.call
|
109
|
+
EM.next_tick { process_tasks }
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
def access_denied?(event)
|
114
|
+
event.code == 1002 &&
|
115
|
+
event.reason == \
|
116
|
+
"Error during WebSocket handshake: Unexpected response code: 401"
|
99
117
|
end
|
100
|
-
end
|
101
118
|
|
102
|
-
def process_next_message(ws)
|
103
|
-
return if queue.empty?
|
104
|
-
message = queue.pop
|
105
|
-
message.send_to(ws)
|
106
|
-
logger.debug [:ws, :send, message]
|
107
119
|
end
|
108
120
|
|
109
121
|
end
|
data/tmp/.gitkeep
ADDED
File without changes
|
metadata
CHANGED
@@ -1,43 +1,29 @@
|
|
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.4
|
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-
|
11
|
+
date: 2014-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: grit
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: faye-websocket
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
|
-
- - "
|
17
|
+
- - "~>"
|
32
18
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
19
|
+
version: '0.7'
|
34
20
|
type: :runtime
|
35
21
|
prerelease: false
|
36
22
|
version_requirements: !ruby/object:Gem::Requirement
|
37
23
|
requirements:
|
38
|
-
- - "
|
24
|
+
- - "~>"
|
39
25
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
26
|
+
version: '0.7'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: bundler
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -163,6 +149,7 @@ files:
|
|
163
149
|
- TODO.md
|
164
150
|
- cucumber-pro.gemspec
|
165
151
|
- features/publish_results.feature
|
152
|
+
- features/security.feature
|
166
153
|
- features/step_definitions/steps.rb
|
167
154
|
- features/support/aruba.rb
|
168
155
|
- features/support/env.rb
|
@@ -171,8 +158,10 @@ files:
|
|
171
158
|
- lib/cucumber/pro.rb
|
172
159
|
- lib/cucumber/pro/formatter.rb
|
173
160
|
- lib/cucumber/pro/scm.rb
|
161
|
+
- lib/cucumber/pro/version
|
174
162
|
- lib/cucumber/pro/version.rb
|
175
163
|
- lib/cucumber/pro/web_socket_session.rb
|
164
|
+
- tmp/.gitkeep
|
176
165
|
homepage: https://cucumber.pro
|
177
166
|
licenses:
|
178
167
|
- MIT
|
@@ -197,9 +186,10 @@ rubyforge_project:
|
|
197
186
|
rubygems_version: 2.0.14
|
198
187
|
signing_key:
|
199
188
|
specification_version: 4
|
200
|
-
summary: cucumber-pro-0.0.
|
189
|
+
summary: cucumber-pro-0.0.4
|
201
190
|
test_files:
|
202
191
|
- features/publish_results.feature
|
192
|
+
- features/security.feature
|
203
193
|
- features/step_definitions/steps.rb
|
204
194
|
- features/support/aruba.rb
|
205
195
|
- features/support/env.rb
|