cucumber-pro 0.0.4 → 0.0.6

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