cucumber-pro 0.0.4 → 0.0.6

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: c90f1ff93aa0791fcc5726992f81678704506523
4
- data.tar.gz: 4db71bb9349a648e404e787a4f808af24764b9c1
3
+ metadata.gz: 130928ede57f9a40d1b22d0e66f3ed254d614aeb
4
+ data.tar.gz: 00dd538d850dee73f4d8a2caf58858845942274c
5
5
  SHA512:
6
- metadata.gz: 52b7ef6e162dc95d32a8b48b8e3b2d67c82da83a48da92667b926d8478d9db2588a4d609e71c1f6b8f74fc3cda3de582141ed8d42882df329f0fd4b38ae10065
7
- data.tar.gz: 66d5412d15be33487e3a4cd163d70d1f9c2666dfda7074e1fac89dc86113d5d4f8d8bea66c3868b665ab24cb1eda6eb3a4b5dc6bf4fcdfe1834e0e8df249c610
6
+ metadata.gz: 52da99dc9bfd36bf1369d4f0e4069258bdfc4accde72781f6b63b555d2a239faa4472567eec372c5ece35a8ffd844e9705b513aee222734da7f6a9436c942687
7
+ data.tar.gz: 76a252ee7416ea06cac3c42743e9ec8b848b2952c788cd85ee0e804739813e887eca56905e2c06b336c19e1809dfff5bd5bd15043ddf9e0d73fcfcea5efb2465
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --order random
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require 'bundler'
3
3
  Bundler::GemHelper.install_tasks
4
4
 
5
5
  desc 'Run tests'
6
- task default: :cucumber
6
+ task default: [:rspec, :cucumber]
7
7
 
8
8
  ENV['cucumber_pro_log_path'] = File.dirname(__FILE__) + '/tmp/test.log'
9
9
 
@@ -11,6 +11,10 @@ task :cucumber do
11
11
  sh 'cucumber'
12
12
  end
13
13
 
14
+ task :rspec do
15
+ sh 'rspec'
16
+ end
17
+
14
18
  desc 'Run repeated tests to check for async bugs'
15
19
  task :soak, :repetitions do |task, args|
16
20
  reps = args[:repetitions] || 10
data/TODO.md CHANGED
@@ -1,9 +1,5 @@
1
- - Scenario for when the token is invalid
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
1
  - Unit tests for Messaging
7
2
  - Handle cases where some messages sent are not ack'd
8
3
  - Handle cases where some messages sent come back with an error
4
+ - Allow configuration of remote
9
5
 
data/lib/cucumber/pro.rb CHANGED
@@ -1,14 +1,14 @@
1
1
  require 'logger'
2
2
  require 'cucumber/pro/formatter'
3
- require 'cucumber/pro/web_socket_session'
3
+ require 'cucumber/pro/web_socket/session'
4
4
  require 'cucumber/pro/version'
5
5
 
6
6
  module Cucumber
7
7
  module Pro
8
8
 
9
9
  class << self
10
- def new(*)
11
- session = WebSocketSession.new(url, config.logger)
10
+ def new(runtime, output, options)
11
+ session = WebSocket::Session.new(url, logger(output))
12
12
  Formatter.new(session)
13
13
  end
14
14
 
@@ -26,6 +26,10 @@ module Cucumber
26
26
  token = config.token || raise(Error::MissingToken.new)
27
27
  config.url + "?token=#{token}"
28
28
  end
29
+
30
+ def logger(output)
31
+ config.logger || Logger.new(output)
32
+ end
29
33
  end
30
34
 
31
35
  class Config
@@ -35,7 +39,6 @@ module Cucumber
35
39
  # Default config
36
40
  configure do |config|
37
41
  config.url = 'wss://results.cucumber.pro/ws'
38
- config.logger = Logger.new(ENV['cucumber_pro_log_path'] || STDOUT)
39
42
  config.token = ENV['CUCUMBER_PRO_TOKEN']
40
43
  end
41
44
 
@@ -1,4 +1,5 @@
1
1
  require 'cucumber/pro/scm'
2
+ require 'securerandom'
2
3
 
3
4
  module Cucumber
4
5
  module Pro
@@ -79,7 +80,7 @@ module Cucumber
79
80
  end
80
81
 
81
82
  def get_run_id
82
- Time.now.to_i
83
+ SecureRandom.hex
83
84
  end
84
85
 
85
86
  end
@@ -9,33 +9,40 @@ module Cucumber
9
9
 
10
10
  def self.find(path = Dir.pwd)
11
11
  if Dir.entries(path).include? '.git'
12
- new(path)
12
+ GitRepo.new(path)
13
13
  else
14
14
  raise NoGitRepoFound if path == '/'
15
15
  find File.expand_path(path + '/..')
16
16
  end
17
17
  end
18
18
 
19
+ end
20
+
21
+ class GitRepo
22
+
19
23
  def initialize(path)
20
24
  @path = path
21
25
  end
22
26
 
23
27
  def remote
24
- cmd('git config --get remote.origin.url')
28
+ cmd('git config --get remote.origin.url').last
25
29
  end
26
30
 
27
31
  def branch
28
- cmd("git branch --contains #{rev}")
32
+ branch = cmd("git branch --contains #{rev}").
33
+ reject { |b| /^\* \(detached from \w+\)/.match b }.
34
+ first.
35
+ gsub(/^\* /, '')
29
36
  end
30
37
 
31
38
  def rev
32
- cmd("git rev-parse HEAD")
39
+ cmd("git rev-parse HEAD").last
33
40
  end
34
41
 
35
42
  private
36
43
 
37
44
  def cmd(cmd)
38
- Dir.chdir(@path) { `#{cmd}` }.strip
45
+ Dir.chdir(@path) { `#{cmd}` }.lines.map &:strip
39
46
  end
40
47
  end
41
48
  end
@@ -1 +1 @@
1
- 0.0.4
1
+ 0.0.6
@@ -0,0 +1,139 @@
1
+ require 'json'
2
+ require 'faye/websocket'
3
+ require 'eventmachine'
4
+
5
+ module Cucumber
6
+ module Pro
7
+ module WebSocket
8
+
9
+ class Session
10
+
11
+ def initialize(url, logger)
12
+ @url, @logger = url, logger
13
+ create_socket = -> worker {
14
+ ws = Faye::WebSocket::Client.new(@url)
15
+ ws.on :open, &worker.method(:on_open)
16
+ ws.on :error, &worker.method(:on_error)
17
+ ws.on :message, &worker.method(:on_message)
18
+ ws.on :close, &worker.method(:on_close)
19
+ ws
20
+ }
21
+ @queue = Queue.new
22
+ @socket = Worker.new(create_socket, logger, self)
23
+ end
24
+
25
+ def send(message)
26
+ logger.debug [:session, :send, message]
27
+ socket.send(message.to_json)
28
+ self
29
+ end
30
+
31
+ def close
32
+ logger.debug [:session, :close]
33
+ socket.close
34
+ loop until socket.closed?
35
+ self
36
+ end
37
+
38
+ def error(exception)
39
+ logger.fatal exception
40
+ $stderr.puts "Cucumber Pro failed to send results: #{exception}"
41
+ $stderr.puts exception.backtrace.join("\n")
42
+ self
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :logger, :queue, :socket
48
+ end
49
+
50
+ class Worker
51
+
52
+ def initialize(create_socket, logger, error_handler)
53
+ @create_socket, @logger, @error_handler = create_socket, logger, error_handler
54
+ @q = Queue.new
55
+ @em = Thread.new { start_client }
56
+ @ack_count = 0
57
+ end
58
+
59
+ def close
60
+ @q << -> {
61
+ if @ack_count == 0
62
+ @ws.close
63
+ else
64
+ EM.next_tick { close }
65
+ end
66
+ }
67
+ self
68
+ end
69
+
70
+ def send(data)
71
+ @q << -> {
72
+ @ws.send data
73
+ @ack_count += 1
74
+ }
75
+ self
76
+ end
77
+
78
+ def closed?
79
+ !@em.alive?
80
+ end
81
+
82
+ private
83
+
84
+ attr_reader :logger, :error_handler, :next_task
85
+
86
+ def start_client
87
+ EM.run do
88
+ logger.debug [:ws, :start]
89
+ @ws = @create_socket.call(self)
90
+ end
91
+ self
92
+ rescue => exception
93
+ error_handler.error exception
94
+ end
95
+
96
+ def on_open(event)
97
+ logger.debug [:ws, :open]
98
+ process_tasks
99
+ self
100
+ end
101
+
102
+ def on_error(event)
103
+ logger.error [:ws, :error]
104
+ self
105
+ end
106
+
107
+ def on_message(event)
108
+ logger.debug [:ws, :message, event.data]
109
+ @ack_count -= 1
110
+ self
111
+ end
112
+
113
+ def on_close(event)
114
+ logger.debug [:ws, :close]
115
+ if access_denied?(event)
116
+ raise Error::AccessDenied.new
117
+ end
118
+ @ws = nil
119
+ EM.stop_event_loop
120
+ self
121
+ end
122
+
123
+ def process_tasks
124
+ @q.pop.call if !@q.empty?
125
+ EM.next_tick { process_tasks }
126
+ self
127
+ end
128
+
129
+ def access_denied?(event)
130
+ event.code == 1002 &&
131
+ event.reason == \
132
+ "Error during WebSocket handshake: Unexpected response code: 401"
133
+ end
134
+
135
+ end
136
+
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,40 @@
1
+ require 'cucumber/pro/scm'
2
+ require 'aruba/api'
3
+
4
+ module Cucumber
5
+ module Pro
6
+ module Scm
7
+ describe GitRepo do
8
+ include Aruba::Api
9
+ before do
10
+ clean_current_dir
11
+ end
12
+
13
+ it "figures out the name of the branch, even on CI" do
14
+ in_current_dir do
15
+ run_simple "git init"
16
+ run_simple "git config user.email \"test@test.com\""
17
+ run_simple "git config user.name \"Test user\""
18
+ run_simple "git commit --allow-empty -m 'Initial commit'"
19
+ run_simple "git rev-parse HEAD"
20
+ rev = all_stdout.split("\n").last
21
+ run_simple "git checkout #{rev}"
22
+ repo = Repo.find(current_dir)
23
+ expect( repo.branch ).to eq "master"
24
+ end
25
+ end
26
+
27
+ it "figures out the name of the branch when that's what's checked out" do
28
+ in_current_dir do
29
+ run_simple "git init"
30
+ run_simple "git config user.email \"test@test.com\""
31
+ run_simple "git config user.name \"Test user\""
32
+ run_simple "git commit --allow-empty -m 'Initial commit'"
33
+ repo = Repo.find(current_dir)
34
+ expect( repo.branch ).to eq "master"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,79 @@
1
+ require 'cucumber/pro/web_socket/session'
2
+ require 'logger'
3
+
4
+ module Cucumber::Pro::WebSocket
5
+
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) }
11
+
12
+ before { logger.level = Logger::DEBUG }
13
+
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
26
+ end
27
+ end
28
+
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
+
37
+
38
+ class FakeSocket
39
+ include RSpec::Mocks::ExampleMethods
40
+
41
+ attr_accessor :worker
42
+ attr_reader :data
43
+
44
+ def initialize
45
+ @data = []
46
+ end
47
+
48
+ def close
49
+ worker.method(:on_close).call(ws_event(1000))
50
+ end
51
+
52
+ def send(data)
53
+ @data << data
54
+ end
55
+
56
+ def send_ack
57
+ event = ws_event(1000, { 'type' => 'metadata_saved' })
58
+ worker.method(:on_message).call(event)
59
+ end
60
+
61
+ private
62
+
63
+ def ws_event(code, data = {})
64
+ double('ws event', code: 1000, data: data)
65
+ end
66
+ end
67
+
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
74
+ end
75
+ result
76
+ end
77
+ end
78
+
79
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber-pro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Wynne
@@ -142,6 +142,7 @@ executables: []
142
142
  extensions: []
143
143
  extra_rdoc_files: []
144
144
  files:
145
+ - ".rspec"
145
146
  - Gemfile
146
147
  - LICENSE
147
148
  - README.md
@@ -160,7 +161,9 @@ files:
160
161
  - lib/cucumber/pro/scm.rb
161
162
  - lib/cucumber/pro/version
162
163
  - lib/cucumber/pro/version.rb
163
- - lib/cucumber/pro/web_socket_session.rb
164
+ - lib/cucumber/pro/web_socket/session.rb
165
+ - spec/cucumber/pro/scm/git_repo_spec.rb
166
+ - spec/cucumber/pro/web_socket/worker_spec.rb
164
167
  - tmp/.gitkeep
165
168
  homepage: https://cucumber.pro
166
169
  licenses:
@@ -186,7 +189,7 @@ rubyforge_project:
186
189
  rubygems_version: 2.0.14
187
190
  signing_key:
188
191
  specification_version: 4
189
- summary: cucumber-pro-0.0.4
192
+ summary: cucumber-pro-0.0.6
190
193
  test_files:
191
194
  - features/publish_results.feature
192
195
  - features/security.feature
@@ -195,4 +198,6 @@ test_files:
195
198
  - features/support/env.rb
196
199
  - features/support/fake_results_service.rb
197
200
  - features/support/world.rb
201
+ - spec/cucumber/pro/scm/git_repo_spec.rb
202
+ - spec/cucumber/pro/web_socket/worker_spec.rb
198
203
  has_rdoc:
@@ -1,123 +0,0 @@
1
- require 'json'
2
- require 'faye/websocket'
3
- require 'eventmachine'
4
-
5
- module Cucumber
6
- module Pro
7
- class WebSocketSession
8
-
9
- def initialize(url, logger)
10
- @url, @logger = url, logger
11
- @queue = Queue.new
12
- @socket = SocketWorker.new(url, logger, self) do
13
- queue.pop.call if !queue.empty?
14
- end
15
- end
16
-
17
- def send(message)
18
- logger.debug [:session, :send, message]
19
- queue.push -> { socket.send(message.to_json) }
20
- self
21
- end
22
-
23
- def close
24
- logger.debug [:session, :close]
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
35
- end
36
-
37
- private
38
-
39
- attr_reader :logger, :queue, :socket
40
-
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 }
47
- end
48
-
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
66
-
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)
82
- logger.debug [:ws, :open]
83
- process_tasks
84
- self
85
- end
86
-
87
- def on_error(event)
88
- logger.error [:ws, :error]
89
- self
90
- end
91
-
92
- def on_message(event)
93
- logger.debug [:ws, :message, event.data]
94
- self
95
- end
96
-
97
- def on_close(event)
98
- logger.debug [:ws, :close]
99
- if access_denied?(event)
100
- raise Error::AccessDenied.new
101
- end
102
- @ws = nil
103
- EM.stop_event_loop
104
- self
105
- end
106
-
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"
117
- end
118
-
119
- end
120
-
121
- end
122
- end
123
- end