tddium-preview 0.0.1 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/spec/tddium_spec.rb CHANGED
@@ -1,100 +1,156 @@
1
+ =begin
2
+ #foo
3
+ Copyright (c) 2011 Solano Labs All Rights Reserved
4
+ =end
5
+
1
6
  require 'spec_helper'
2
7
 
3
- # TODO: Test what happens if an error occurs in the POST and GET requests
4
8
  describe Tddium do
5
9
  include FakeFS::SpecHelpers
10
+ include TddiumSpecHelpers
11
+
12
+ SAMPLE_API_KEY = "afb12412bdafe124124asfasfabebafeabwbawf1312342erbfasbb"
13
+ SAMPLE_APP_NAME = "tddelicious"
14
+ SAMPLE_BRANCH_NAME = "test"
15
+ SAMPLE_BUNDLER_VERSION = "1.10.10"
16
+ SAMPLE_CALL_API_RESPONSE = [0, 200, nil]
17
+ SAMPLE_CALL_API_ERROR = [1, 501, "an error"]
18
+ SAMPLE_DATE_TIME = "2011-03-11T08:43:02Z"
19
+ SAMPLE_EMAIL = "someone@example.com"
20
+ SAMPLE_INVITATION_TOKEN = "TZce3NueiXp2lMTmaeRr"
21
+ SAMPLE_GIT_REPO_URI = "ssh://git@api.tddium.com/home/git/repo/#{SAMPLE_APP_NAME}"
22
+ SAMPLE_LICENSE_TEXT = "LICENSE"
23
+ SAMPLE_PASSWORD = "foobar"
24
+ SAMPLE_REPORT_URL = "http://api.tddium.com/1/sessions/1/test_executions/report"
25
+ SAMPLE_RUBYGEMS_VERSION = "1.3.7"
26
+ SAMPLE_RUBY_VERSION = "1.8.7"
27
+ SAMPLE_RECURLY_URL = "https://tddium.recurly.com/account/1"
28
+ SAMPLE_SESSION_ID = 1
29
+ SAMPLE_SUITE_ID = 1
30
+ SAMPLE_SUITES_RESPONSE = {"suites" => [{"repo_name" => SAMPLE_APP_NAME, "branch" => SAMPLE_BRANCH_NAME, "id" => SAMPLE_SUITE_ID}]}
31
+ SAMPLE_TDDIUM_CONFIG_FILE = ".tddium.test"
32
+ SAMPLE_TEST_PATTERN = "**/*_spec.rb"
33
+ SAMPLE_USER_RESPONSE = {"user"=> {"api_key" => SAMPLE_API_KEY, "email" => SAMPLE_EMAIL, "created_at" => SAMPLE_DATE_TIME, "recurly_url" => SAMPLE_RECURLY_URL}}
34
+
35
+ def call_api_should_receive(options = {})
36
+ params = [options[:method] || anything, options[:path] || anything, options[:params] || anything, (options[:api_key] || options[:api_key] == false) ? options[:api_key] : anything]
37
+ tddium_client.stub(:call_api).with(*params) # To prevent the yield
38
+ tddium_client.should_receive(:call_api).with(*params).and_return(SAMPLE_CALL_API_ERROR)
39
+ end
6
40
 
7
- SSH_KEY_PROMPT = "Enter your ssh key or press 'Return'. Using ~/.ssh/id_rsa.pub by default:"
8
- TEST_PATTERN_PROMPT = "Enter a test pattern or press 'Return'. Using **/*_spec.rb by default:"
9
- DEFAULT_APP_NAME = "tddelicious"
10
- DEFAULT_BRANCH_NAME = "test"
11
- DEFAULT_SUITE_ID = "66"
12
- DEFAULT_API_KEY = "afb12412bdafe124124asfasfabebafeabwbawf1312342erbfasbb"
41
+ def extract_options!(array, *option_keys)
42
+ is_options = false
43
+ option_keys.each do |option_key|
44
+ is_options ||= array.last.include?(option_key.to_sym)
45
+ end
46
+ (array.last.is_a?(Hash) && is_options) ? array.pop : {}
47
+ end
13
48
 
14
- def run(tddium)
15
- send("run_#{example.example_group.ancestors.map(&:description)[-2][1..-1]}", tddium)
49
+ def run(tddium, options = {:environment => "test"})
50
+ send("run_#{example.example_group.ancestors.map(&:description)[-2][1..-1]}", tddium, options)
16
51
  end
17
52
 
18
- def run_suite(tddium)
19
- tddium.suite
53
+ [:suite, :spec, :status, :account, :login, :logout].each do |method|
54
+ define_method("run_#{method}") do |tddium, *params|
55
+ options = params.first || {}
56
+ options[:environment] = "test" unless options.has_key?(:environment)
57
+ stub_cli_options(tddium, options)
58
+ tddium.send(method)
59
+ end
20
60
  end
21
61
 
22
- def run_spec(tddium)
23
- tddium.spec
62
+ def stub_bundler_version(tddium, version = SAMPLE_BUNDLER_VERSION)
63
+ tddium.stub(:`).with("bundle -v").and_return("Bundler version #{version}")
24
64
  end
25
65
 
26
- def suite_name_prompt(default = default_suite_name)
27
- "Enter a suite name or press 'Return'. Using '#{default}' by default:"
66
+ def stub_call_api_response(method, path, *response)
67
+ options = extract_options!(response, :and_return, :and_yield)
68
+ options[:and_yield] = true unless options[:and_yield] == false
69
+ result = tddium_client.stub(:call_api).with(method, path, anything, anything)
70
+ result = result.and_yield(response.first) if options[:and_yield]
71
+ result.and_return(options[:and_return] || SAMPLE_CALL_API_ERROR)
72
+ response.each_with_index do |current_response, index|
73
+ result = result.and_yield(current_response) unless index.zero? || !options[:and_yield]
74
+ end
28
75
  end
29
76
 
30
- def default_suite_name
31
- "#{DEFAULT_APP_NAME}/#{DEFAULT_BRANCH_NAME}"
77
+ def stub_cli_options(tddium, options = {})
78
+ tddium.stub(:options).and_return(options)
32
79
  end
33
80
 
34
- def stub_default_suite_name(tddium, default_app_name = DEFAULT_APP_NAME, default_branch_name = DEFAULT_BRANCH_NAME)
35
- Dir.stub(:pwd).and_return(default_app_name)
36
- stub_git_branch(tddium, default_branch_name)
81
+ def stub_config_file(options = {})
82
+ params = {}
83
+ params.merge!(:branches => (options[:branches].is_a?(Hash)) ? options[:branches] : {SAMPLE_BRANCH_NAME => SAMPLE_SUITE_ID}) if options[:branches]
84
+ params.merge!(:api_key => (options[:api_key].is_a?(String)) ? options[:api_key] : SAMPLE_API_KEY) if options[:api_key]
85
+ json = params.to_json unless params.empty?
86
+ create_file(SAMPLE_TDDIUM_CONFIG_FILE, json)
37
87
  end
38
88
 
39
- def stub_ruby_version(tddium, ruby_version = "1.9.2")
40
- tddium.stub(:`).with("ruby -v").and_return("ruby #{ruby_version} (2010-08-16 patchlevel 302) [i686-darwin10.5.0]")
89
+ def stub_default_suite_name
90
+ Dir.stub(:pwd).and_return(SAMPLE_APP_NAME)
91
+ end
92
+
93
+ def stub_defaults
94
+ tddium.stub(:say)
95
+ stub_git_branch(tddium)
96
+ stub_tddium_client
97
+ create_file(File.join(".git", "something"), "something")
41
98
  end
42
99
 
43
- def stub_git_branch(tddium, default_branch_name = DEFAULT_BRANCH_NAME)
100
+ def stub_git_branch(tddium, default_branch_name = SAMPLE_BRANCH_NAME)
44
101
  tddium.stub(:`).with("git symbolic-ref HEAD").and_return(default_branch_name)
45
102
  end
46
103
 
47
- def parse_request_params
48
- Rack::Utils.parse_nested_query(FakeWeb.last_request.body)
104
+ def stub_git_push(tddium, success = true)
105
+ tddium.stub(:system).with(/^git push/).and_return(success)
49
106
  end
50
107
 
51
- def create_file(path, content = "blah")
52
- FileUtils.mkdir_p(File.dirname(path))
53
- File.open(path, 'w') do |f|
54
- f.write(content)
55
- end
108
+ def stub_ruby_version(tddium, version = SAMPLE_RUBY_VERSION)
109
+ tddium.stub(:`).with("ruby -v").and_return("ruby #{version} (2010-08-16 patchlevel 302) [i686-darwin10.5.0]")
56
110
  end
57
111
 
58
- def register_uri_options(options = {})
59
- if options.is_a?(Array)
60
- options_array = []
61
- options.each do |sub_options|
62
- options_array << register_uri_options(sub_options)
63
- end
64
- options_array
65
- else
66
- options_for_fake_web = {:body => options[:body], :status => options[:status]}
67
- if options[:response]
68
- FakeFS.deactivate!
69
- response = File.open(options[:response]) { |f| f.read }
70
- FakeFS.activate!
71
- options_for_fake_web.merge!(:response => response)
72
- end
73
- options_for_fake_web
74
- end
112
+ def stub_rubygems_version(tddium, version = SAMPLE_RUBYGEMS_VERSION)
113
+ tddium.stub(:`).with("gem -v").and_return(version)
75
114
  end
76
115
 
77
- def stub_http_response(method, path, options = {})
78
- FakeWeb.register_uri(method, URI.join(Tddium::API_HOST, "#{Tddium::API_VERSION}/#{path}").to_s, register_uri_options(options))
116
+ def stub_sleep(tddium)
117
+ tddium.stub(:sleep).with(Tddium::Default::SLEEP_TIME_BETWEEN_POLLS)
79
118
  end
80
119
 
81
- def stub_defaults
82
- FakeWeb.clean_registry
83
- tddium.stub(:say)
84
- stub_git_branch(tddium)
85
- create_file(".git/something", "something")
86
- create_file(".tddium", {:branches => {DEFAULT_BRANCH_NAME => DEFAULT_SUITE_ID}, :api_key => DEFAULT_API_KEY}.to_json)
120
+ def stub_tddium_client
121
+ TddiumClient.stub(:new).and_return(tddium_client)
122
+ tddium_client.stub(:environment).and_return(:test)
123
+ tddium_client.stub(:call_api).and_return(SAMPLE_CALL_API_ERROR)
87
124
  end
88
125
 
89
- def stub_git_push(tddium)
90
- tddium.stub(:`).with(/^git push/)
126
+ let(:tddium) { Tddium.new }
127
+ let(:tddium_client) { mock(TddiumClient).as_null_object }
128
+
129
+
130
+ shared_examples_for "a password prompt" do
131
+ context "--password was not passed in" do
132
+ it "should prompt for a password or confirmation" do
133
+ highline = mock(HighLine)
134
+ HighLine.should_receive(:ask).with(password_prompt).and_yield(highline)
135
+ highline.should_receive(:echo=).with("*")
136
+ run(tddium)
137
+ end
138
+ end
139
+ context "--password was passed in" do
140
+ it "should not prompt for a password or confirmation" do
141
+ HighLine.should_not_receive(:ask).with(password_prompt)
142
+ run(tddium, :password => SAMPLE_PASSWORD)
143
+ end
144
+ end
91
145
  end
92
146
 
93
- def stub_sleep(tddium)
94
- tddium.stub(:sleep).with(Tddium::SLEEP_TIME_BETWEEN_POLLS)
147
+ shared_examples_for "an unsuccessful api call" do
148
+ it "should show the error" do
149
+ tddium_client.stub(:call_api).and_return(SAMPLE_CALL_API_ERROR)
150
+ tddium.should_receive(:say).with(SAMPLE_CALL_API_ERROR[2])
151
+ run(tddium)
152
+ end
95
153
  end
96
-
97
- let(:tddium) { Tddium.new }
98
154
 
99
155
  shared_examples_for "git repo has not been initialized" do
100
156
  context "git repo has not been initialized" do
@@ -103,338 +159,453 @@ describe Tddium do
103
159
  end
104
160
 
105
161
  it "should return git is uninitialized" do
106
- tddium.should_receive(:say).with("git repo must be initialized. Try 'git init'.")
162
+ tddium.should_receive(:say).with(Tddium::Text::Error::GIT_NOT_INITIALIZED)
107
163
  run(tddium)
108
164
  end
109
165
  end
110
166
  end
111
167
 
112
- shared_examples_for ".tddium file is missing or corrupt" do
113
- context ".tddium file is missing" do
114
- before do
115
- FileUtils.rm_rf(".tddium")
116
- end
168
+ shared_examples_for "getting the current suite from the API" do
169
+ it "should send a 'GET' request to '#{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}'" do
170
+ call_api_should_receive(:method => :get, :path => "#{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}")
171
+ run(tddium)
172
+ end
173
+ end
174
+
175
+ shared_examples_for "logging in a user" do
176
+ context "there is a tddium config file with an api key" do
177
+ before {stub_config_file(:api_key => "some api key")}
117
178
 
118
- it "should tell the user '#{Tddium::NOT_INITIALIZED_ERROR}'" do
119
- tddium.should_receive(:say).with(Tddium::NOT_INITIALIZED_ERROR)
179
+ it "should send a 'GET' request to '#{Tddium::Api::Path::USERS}'" do
180
+ call_api_should_receive(:method => :get, :path => /#{Tddium::Api::Path::USERS}$/)
120
181
  run(tddium)
121
182
  end
122
183
  end
123
184
 
124
- context ".tddium file is corrupt" do
125
- before do
126
- create_file(".tddium", "corrupt file")
185
+ context "the tddium config file is missing or corrupt or the api key is invalid" do
186
+ context "--email was not passed in" do
187
+ it "should prompt for the user's email address" do
188
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::EMAIL)
189
+ run(tddium)
190
+ end
127
191
  end
128
192
 
129
- it "should tell the user '#{Tddium::NOT_INITIALIZED_ERROR}'" do
130
- tddium.should_receive(:say).with(Tddium::INVALID_TDDIUM_FILE)
193
+ context "--email was passed in" do
194
+ it "should not prompt for the user's email address" do
195
+ tddium.should_not_receive(:ask).with(Tddium::Text::Prompt::EMAIL)
196
+ run(tddium, :email => SAMPLE_EMAIL)
197
+ end
198
+ end
199
+
200
+ it_should_behave_like "a password prompt" do
201
+ let(:password_prompt) {Tddium::Text::Prompt::PASSWORD}
202
+ end
203
+
204
+ it "should try to sign in the user with their email & password" do
205
+ tddium.stub(:ask).with(Tddium::Text::Prompt::EMAIL).and_return(SAMPLE_EMAIL)
206
+ HighLine.stub(:ask).with(Tddium::Text::Prompt::PASSWORD).and_return(SAMPLE_PASSWORD)
207
+ call_api_should_receive(:method => :post, :path => /#{Tddium::Api::Path::SIGN_IN}$/, :params => {:user => {:email => SAMPLE_EMAIL, :password => SAMPLE_PASSWORD}}, :api_key => false)
131
208
  run(tddium)
132
209
  end
133
210
  end
211
+
212
+ context "the user logs in successfully with their email and password" do
213
+ before{stub_call_api_response(:post, Tddium::Api::Path::SIGN_IN, {"api_key" => SAMPLE_API_KEY})}
214
+ it_should_behave_like "writing the api key to the .tddium file"
215
+ end
134
216
  end
135
217
 
136
218
  shared_examples_for "sending the api key" do
137
- it "should include the api key in the headers" do
219
+ it "should call the api with the api key" do
220
+ call_api_should_receive(:api_key => SAMPLE_API_KEY)
138
221
  run(tddium)
139
- FakeWeb.last_request[Tddium::API_KEY_HEADER].should == DEFAULT_API_KEY
140
222
  end
141
223
  end
142
224
 
143
- describe "#suite" do
144
- before do
145
- stub_defaults
146
- tddium.stub(:ask).and_return("")
147
- stub_http_response(:post, Tddium::SUITES_PATH)
148
- stub_ruby_version(tddium)
149
- create_file("~/.ssh/id_rsa.pub", "ssh-rsa blah")
225
+ shared_examples_for "set the default environment" do
226
+ context "with environment parameter" do
227
+ it "should should set the environment as the parameter of environment" do
228
+ tddium_client.should_receive(:environment=).with(:test)
229
+ run(tddium, :environment => "test")
230
+ end
150
231
  end
151
232
 
152
- it "should ask the user for their ssh key" do
153
- tddium.should_receive(:ask).with(SSH_KEY_PROMPT)
154
- run_suite(tddium)
155
- end
233
+ context "without environment parameter" do
234
+ before do
235
+ FileUtils.rm_rf(".tddium")
236
+ FileUtils.rm_rf(".tddium.development")
237
+ tddium_client.stub(:environment).and_return(:development)
238
+ end
156
239
 
157
- it "should ask for a suite name" do
158
- stub_default_suite_name(tddium)
159
- tddium.should_receive(:ask).with(suite_name_prompt)
160
- run_suite(tddium)
161
- end
240
+ it "should should set the environment as production if the file '.tddium.development' does not exist" do
241
+ tddium_client.should_receive(:environment=).with(:production)
242
+ run(tddium, :environment => nil)
243
+ end
162
244
 
163
- it "should ask for a test file pattern" do
164
- tddium.should_receive(:ask).with(TEST_PATTERN_PROMPT)
165
- run_suite(tddium)
245
+ it "should should set the environment as development if the file '.tddium.development' exists" do
246
+ create_file(".tddium.development")
247
+ tddium_client.should_receive(:environment=).with(:development)
248
+ tddium_client.should_not_receive(:environment=).with(:production)
249
+ run(tddium, :environment => nil)
250
+ end
166
251
  end
252
+ end
167
253
 
168
- it "should send a 'POST' request to '#{Tddium::SUITES_PATH}'" do
169
- run_suite(tddium)
170
- FakeWeb.last_request.method.should == "POST"
171
- FakeWeb.last_request.path.should =~ /\/#{Tddium::SUITES_PATH}$/
172
- end
254
+ shared_examples_for "suite has not been initialized" do
255
+ context ".tddium file is missing" do
256
+ before do
257
+ stub_config_file(:api_key => true)
258
+ end
173
259
 
174
- it "should post the current ruby version to the API" do
175
- stub_ruby_version(tddium, "1.9.2")
176
- run_suite(tddium)
177
- parse_request_params["suite"].should include("ruby_version" => "1.9.2")
260
+ it "should tell the user '#{Tddium::Text::Error::NO_SUITE_EXISTS % SAMPLE_BRANCH_NAME}'" do
261
+ tddium.should_receive(:say).with(Tddium::Text::Error::NO_SUITE_EXISTS % SAMPLE_BRANCH_NAME)
262
+ run(tddium)
263
+ end
178
264
  end
265
+ end
179
266
 
180
- it_should_behave_like "sending the api key"
181
-
182
- it_should_behave_like "git repo has not been initialized"
183
- it_should_behave_like ".tddium file is missing or corrupt"
184
-
185
- context "using defaults" do
267
+ shared_examples_for ".tddium file is missing or corrupt" do
268
+ context ".tddium file is missing" do
186
269
  before do
187
- stub_default_suite_name(tddium)
270
+ FileUtils.rm_rf(SAMPLE_TDDIUM_CONFIG_FILE)
188
271
  end
189
272
 
190
- it "should POST the default values to the API" do
191
- run_suite(tddium)
192
- parse_request_params["suite"].should include("ssh_key" => "ssh-rsa blah", "suite_name" => default_suite_name,
193
- "test_pattern" => "**/*_spec.rb")
273
+ it "should tell the user '#{Tddium::Text::Error::NOT_INITIALIZED}'" do
274
+ tddium.should_receive(:say).with(Tddium::Text::Error::NOT_INITIALIZED)
275
+ run(tddium)
194
276
  end
195
-
196
277
  end
197
278
 
198
- context "passing arguments" do
279
+ context ".tddium file is corrupt" do
199
280
  before do
200
- ssh_key_file = "~/.ssh/blah.txt"
201
- tddium.stub(:options).and_return(
202
- :ssh_key => ssh_key_file,
203
- :name => "my_suite_name",
204
- :test_pattern => "**/*_test.rb"
205
- )
206
- create_file(ssh_key_file, "ssh-rsa 1234")
281
+ create_file(SAMPLE_TDDIUM_CONFIG_FILE, "corrupt file")
207
282
  end
208
283
 
209
- it "should POST the passed in values to the API" do
210
- run_suite(tddium)
211
- parse_request_params["suite"].should include("ssh_key" => "ssh-rsa 1234", "suite_name" => "my_suite_name",
212
- "test_pattern" => "**/*_test.rb")
284
+ it "should tell the user '#{Tddium::Text::Error::INVALID_TDDIUM_FILE % 'test'}'" do
285
+ tddium.should_receive(:say).with(Tddium::Text::Error::INVALID_TDDIUM_FILE % 'test')
286
+ run(tddium)
213
287
  end
288
+ end
289
+ end
290
+
291
+ shared_examples_for "writing the api key to the .tddium file" do
292
+ it "should write the api key to the .tddium file" do
293
+ run(tddium)
294
+ tddium_file = File.open(SAMPLE_TDDIUM_CONFIG_FILE) { |file| file.read }
295
+ JSON.parse(tddium_file)["api_key"].should == SAMPLE_API_KEY
296
+ end
297
+ end
214
298
 
299
+ describe "#account" do
300
+ before do
301
+ stub_defaults
302
+ tddium.stub(:ask).and_return("")
303
+ HighLine.stub(:ask).and_return("")
304
+ create_file(File.join(File.dirname(__FILE__), "..", Tddium::License::FILE_NAME), SAMPLE_LICENSE_TEXT)
305
+ create_file(Tddium::Default::SSH_FILE, "ssh-rsa blah")
215
306
  end
216
307
 
217
- context "interactive mode" do
308
+ it_should_behave_like "set the default environment"
309
+
310
+ context "the user is already logged in" do
218
311
  before do
219
- ssh_key_file = "~/.ssh/foo.txt"
220
- tddium.stub(:ask).with(SSH_KEY_PROMPT).and_return(ssh_key_file)
221
- tddium.stub(:ask).with(TEST_PATTERN_PROMPT).and_return("**/*_selenium.rb")
222
- tddium.stub(:ask).with(suite_name_prompt).and_return("foobar")
223
- stub_default_suite_name(tddium)
224
- create_file(ssh_key_file, "ssh-rsa 65431")
312
+ stub_config_file(:api_key => SAMPLE_API_KEY)
313
+ stub_call_api_response(:get, Tddium::Api::Path::USERS, SAMPLE_USER_RESPONSE)
225
314
  end
226
315
 
227
- it "should POST the passed in values to the API" do
228
- run_suite(tddium)
229
- parse_request_params["suite"].should include("ssh_key" => "ssh-rsa 65431", "suite_name" => "foobar",
230
- "test_pattern" => "**/*_selenium.rb")
316
+ it "should show the user's email address" do
317
+ tddium.should_receive(:say).with(SAMPLE_EMAIL)
318
+ run_account(tddium)
231
319
  end
232
- end
233
320
 
234
- context "API response successful" do
235
- before do
236
- stub_http_response(:post, Tddium::SUITES_PATH, :response => fixture_path("post_suites_201.json"))
237
- tddium.stub(:`).with(/^git remote/)
238
- stub_git_push(tddium)
321
+ it "should show the user's account creation date" do
322
+ tddium.should_receive(:say).with(SAMPLE_DATE_TIME)
323
+ run_account(tddium)
239
324
  end
240
325
 
241
- it "should remove any existing remotes named 'tddium'" do
242
- tddium.should_receive(:`).with("git remote rm tddium")
243
- run_suite(tddium)
326
+ it "should show the user's recurly account url" do
327
+ tddium.should_receive(:say).with(SAMPLE_RECURLY_URL)
328
+ run_account(tddium)
329
+ end
330
+
331
+ end
332
+
333
+ context "the user is not already logged in" do
334
+ let(:call_api_result) {[403, "Forbidden"]}
335
+
336
+ it_should_behave_like "a password prompt" do
337
+ let(:password_prompt) {Tddium::Text::Prompt::PASSWORD_CONFIRMATION}
244
338
  end
245
339
 
246
- it "should add a new remote called 'tddium'" do
247
- stub_default_suite_name(tddium)
248
- tddium.should_receive(:`).with("git remote add tddium ssh://git@api.tddium.com/home/git/repo/#{DEFAULT_APP_NAME}")
249
- run_suite(tddium)
340
+ context "the user does not confirm their password correctly" do
341
+ before {HighLine.stub(:ask).with(Tddium::Text::Prompt::PASSWORD_CONFIRMATION).and_return("wrong confirmation")}
342
+ it "should tell the user '#{Tddium::Text::Process::PASSWORD_CONFIRMATION_INCORRECT}'" do
343
+ tddium.should_receive(:say).with(Tddium::Text::Process::PASSWORD_CONFIRMATION_INCORRECT)
344
+ run_account(tddium)
345
+ end
250
346
  end
251
347
 
252
- context "in the branch 'oaktree'" do
348
+ context "the user confirms their password correctly" do
253
349
  before do
254
- tddium.stub(:current_git_branch).and_return("oaktree")
350
+ HighLine.stub(:ask).with(Tddium::Text::Prompt::PASSWORD).and_return(SAMPLE_PASSWORD)
351
+ HighLine.stub(:ask).with(Tddium::Text::Prompt::PASSWORD_CONFIRMATION).and_return(SAMPLE_PASSWORD)
255
352
  end
256
353
 
257
- it "should push the current git branch to tddium oaktree" do
258
- tddium.should_receive(:`).with("git push tddium oaktree")
259
- run_suite(tddium)
354
+ context "--ssh-key-file is not supplied" do
355
+ it "should prompt the user for their ssh key file" do
356
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::SSH_KEY % Tddium::Default::SSH_FILE)
357
+ run_account(tddium)
358
+ end
260
359
  end
261
360
 
262
- it "should create '.tddium' and write the suite_id and branch name" do
263
- run_suite(tddium)
264
- tddium_file = File.open(".tddium") { |file| file.read }
265
- JSON.parse(tddium_file)["branches"]["oaktree"].should == 19 # From response
361
+ context "--ssh-key-file is supplied" do
362
+ it "should not prompt the user for their ssh key file" do
363
+ tddium.should_not_receive(:ask).with(Tddium::Text::Prompt::SSH_KEY % Tddium::Default::SSH_FILE)
364
+ run_account(tddium, :ssh_key_file => Tddium::Default::SSH_FILE)
365
+ end
366
+ end
367
+
368
+ it "should show the user the license" do
369
+ tddium.should_receive(:say).with(SAMPLE_LICENSE_TEXT)
370
+ run_account(tddium)
371
+ end
372
+
373
+ it "should ask the user to accept the license" do
374
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::LICENSE_AGREEMENT)
375
+ run_account(tddium)
376
+ end
377
+
378
+ context "accepting the license" do
379
+ before do
380
+ tddium.stub(:ask).with(Tddium::Text::Prompt::LICENSE_AGREEMENT).and_return(Tddium::Text::Prompt::Response::AGREE_TO_LICENSE)
381
+ tddium.stub(:ask).with(Tddium::Text::Prompt::INVITATION_TOKEN).and_return(SAMPLE_INVITATION_TOKEN)
382
+ create_file(Tddium::Default::SSH_FILE, "ssh-rsa 1234")
383
+ end
384
+
385
+ it "should send a 'POST' request to '#{Tddium::Api::Path::USERS}' with the user's invitation token, password and ssh key" do
386
+ call_api_should_receive(:method => :post, :path => /#{Tddium::Api::Path::USERS}$/, :params => {:user => {:invitation_token => SAMPLE_INVITATION_TOKEN, :password => SAMPLE_PASSWORD, :user_git_pubkey => "ssh-rsa 1234"}}, :api_key => false)
387
+ run_account(tddium)
388
+ end
389
+
390
+ context "'POST #{Tddium::Api::Path::USERS}' is successful" do
391
+ before{stub_call_api_response(:post, Tddium::Api::Path::USERS, SAMPLE_USER_RESPONSE)}
392
+
393
+ it_should_behave_like "writing the api key to the .tddium file"
394
+
395
+ it "should show the user '#{Tddium::Text::Process::ACCOUNT_CREATED % [SAMPLE_EMAIL, SAMPLE_RECURLY_URL]}'" do
396
+ tddium.should_receive(:say).with(Tddium::Text::Process::ACCOUNT_CREATED % [SAMPLE_EMAIL, SAMPLE_RECURLY_URL])
397
+ run_account(tddium)
398
+ end
399
+ end
400
+ context "'POST #{Tddium::Api::Path::USERS}' is unsuccessful" do
401
+
402
+ it_should_behave_like "an unsuccessful api call"
403
+
404
+ context "because the invitation is invalid" do
405
+ before { stub_call_api_response(:post, Tddium::Api::Path::USERS, :and_yield => false, :and_return => [Tddium::Api::ErrorCode::INVALID_INVITATION, 409, "Invitation is invalid"]) }
406
+ it "should show the user: '#{Tddium::Text::Error::INVALID_INVITATION}'" do
407
+ tddium.should_receive(:say).with(Tddium::Text::Error::INVALID_INVITATION)
408
+ run_account(tddium)
409
+ end
410
+ end
411
+ end
266
412
  end
267
413
  end
268
414
  end
415
+ end
416
+
417
+ describe "#login" do
418
+ before do
419
+ stub_defaults
420
+ tddium.stub(:ask).and_return("")
421
+ HighLine.stub(:ask).and_return("")
422
+ end
423
+
424
+ it_should_behave_like "set the default environment"
425
+ it_should_behave_like "logging in a user"
269
426
 
270
- context "API response successful but JSON status not 0" do
427
+ context "user is already logged in" do
271
428
  before do
272
- stub_http_response(:post, Tddium::SUITES_PATH, :response => fixture_path("post_suites_201_json_status_1.json"))
429
+ stub_config_file(:api_key => SAMPLE_API_KEY)
430
+ stub_call_api_response(:get, Tddium::Api::Path::USERS, :and_yield => false, :and_return => SAMPLE_CALL_API_RESPONSE)
273
431
  end
274
432
 
275
- it "should do show the explaination" do
276
- tddium.should_receive(:say).with("An error occured: {:suite_name=>[\"has already been taken\"]}")
277
- run_suite(tddium)
433
+ it "should show the user: '#{Tddium::Text::Process::ALREADY_LOGGED_IN}'" do
434
+ tddium.should_receive(:say).with(Tddium::Text::Process::ALREADY_LOGGED_IN)
435
+ run_login(tddium)
278
436
  end
279
437
  end
280
438
 
281
- context "API response unsuccessful" do
282
- before do
283
- stub_http_response(:post, Tddium::SUITES_PATH, :status => ["501", "Internal Server Error"])
439
+ context "the user logs in successfully" do
440
+ before{stub_call_api_response(:post, Tddium::Api::Path::SIGN_IN, {})}
441
+ it "should show the user: '#{Tddium::Text::Process::LOGGED_IN_SUCCESSFULLY}'" do
442
+ tddium.should_receive(:say).with(Tddium::Text::Process::LOGGED_IN_SUCCESSFULLY)
443
+ run_login(tddium)
284
444
  end
445
+ end
285
446
 
286
- it "should show that there was an error" do
287
- tddium.should_receive(:say).with(/^An error occured: /)
288
- run_suite(tddium)
289
- end
447
+ context "the user does not sign in successfully" do
448
+ it_should_behave_like "an unsuccessful api call"
449
+ end
450
+ end
290
451
 
291
- context "API status code != 0" do
292
- before do
293
- stub_http_response(:post, Tddium::SUITES_PATH, :response => fixture_path("post_suites_409.json"))
294
- end
452
+ describe "#logout" do
453
+ before { tddium.stub(:say) }
295
454
 
296
- it "should show the error message" do
297
- tddium.should_receive(:say).with(/Conflict \{\:suite_name\=\>\[\"has already been taken\"\]\}$/)
298
- run_suite(tddium)
299
- end
455
+ context ".tddium file exists" do
456
+ before { stub_config_file }
457
+ it "should delete the file" do
458
+ run_logout(tddium)
459
+ File.should_not be_exists(SAMPLE_TDDIUM_CONFIG_FILE)
300
460
  end
461
+ end
301
462
 
302
- context "501 Error" do
303
- before do
304
- stub_http_response(:post, Tddium::SUITES_PATH, :status => ["501", "Internal Server Error"])
305
- end
306
-
307
- it "should show the HTTP error message" do
308
- tddium.should_receive(:say).with(/Internal Server Error$/)
309
- run_suite(tddium)
310
- end
463
+ context ".tddium file does not exists" do
464
+ it "should do nothing" do
465
+ FileUtils.should_not_receive(:rm)
466
+ run_logout(tddium)
311
467
  end
312
468
  end
469
+
470
+ it "should show the user: '#{Tddium::Text::Process::LOGGED_OUT_SUCCESSFULLY}'" do
471
+ tddium.should_receive(:say).with(Tddium::Text::Process::LOGGED_OUT_SUCCESSFULLY)
472
+ run_logout(tddium)
473
+ end
313
474
  end
314
475
 
315
476
  describe "#spec" do
316
477
  before do
317
478
  stub_defaults
479
+ stub_config_file(:api_key => true, :branches => true)
318
480
  stub_git_push(tddium)
319
- stub_http_response(:get, "#{Tddium::SUITES_PATH}/#{DEFAULT_SUITE_ID}")
320
481
  end
321
-
482
+
483
+ it_should_behave_like "set the default environment"
322
484
  it_should_behave_like "git repo has not been initialized"
323
485
  it_should_behave_like ".tddium file is missing or corrupt"
486
+ it_should_behave_like "suite has not been initialized"
324
487
 
325
488
  it "should push the latest code to tddium" do
326
- tddium.should_receive(:`).with("git push #{Tddium::GIT_REMOTE_NAME} #{DEFAULT_BRANCH_NAME}")
489
+ tddium.should_receive(:system).with("git push #{Tddium::Git::REMOTE_NAME} #{SAMPLE_BRANCH_NAME}")
327
490
  run_spec(tddium)
328
491
  end
329
492
 
330
- it "should send a 'GET' request to '#{Tddium::SUITES_PATH}/#{DEFAULT_SUITE_ID}'" do
331
- run_spec(tddium)
332
- FakeWeb.last_request.method.should == "GET"
333
- FakeWeb.last_request.path.should =~ /#{Tddium::SUITES_PATH}\/#{DEFAULT_SUITE_ID}$/
493
+ context "git push was unsuccessful" do
494
+ before { stub_git_push(tddium, false) }
495
+ it "should not try to contact the api" do
496
+ tddium_client.should_not_receive(:call_api)
497
+ run_spec(tddium)
498
+ end
334
499
  end
335
500
 
501
+ it_should_behave_like "getting the current suite from the API"
336
502
  it_should_behave_like "sending the api key"
337
503
 
338
- context "'GET #{Tddium::SUITES_PATH}/#{DEFAULT_SUITE_ID}' is successful" do
504
+ context "'GET #{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}' is successful" do
339
505
  before do
340
- stub_http_response(:get, "#{Tddium::SUITES_PATH}/#{DEFAULT_SUITE_ID}", :response => fixture_path("get_suites_200.json"))
341
- stub_http_response(:post, Tddium::SESSIONS_PATH)
506
+ response = {"suite"=>{"test_pattern"=>SAMPLE_TEST_PATTERN, "id"=>SAMPLE_SUITE_ID, "suite_name"=>"tddium/demo", "ruby_version"=>SAMPLE_RUBY_VERSION}}
507
+ stub_call_api_response(:get, "#{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}", response)
342
508
  create_file("spec/mouse_spec.rb")
343
509
  create_file("spec/cat_spec.rb")
344
510
  create_file("spec/dog_spec.rb")
345
511
  end
346
512
 
347
- it "should send a 'POST' request to '#{Tddium::SESSIONS_PATH}'" do
513
+ it "should send a 'POST' request to '#{Tddium::Api::Path::SESSIONS}'" do
514
+ call_api_should_receive(:method => :post, :path => Tddium::Api::Path::SESSIONS)
348
515
  run_spec(tddium)
349
- FakeWeb.last_request.method.should == "POST"
350
- FakeWeb.last_request.path.should =~ /#{Tddium::SESSIONS_PATH}$/
351
516
  end
352
517
 
353
518
  it_should_behave_like "sending the api key"
354
519
 
355
- context "'POST #{Tddium::SESSIONS_PATH}' is successful" do
356
- let(:session_id) {7} # from the fixture 'post_sessions_201.json'
520
+ context "'POST #{Tddium::Api::Path::SESSIONS}' is successful" do
357
521
  before do
358
- stub_http_response(:post, "#{Tddium::SESSIONS_PATH}", :response => fixture_path("post_sessions_201.json"))
359
- stub_http_response(:post, "#{Tddium::SESSIONS_PATH}/#{session_id}/#{Tddium::REGISTER_TEST_EXECUTIONS_PATH}")
522
+ response = {"session"=>{"id"=>SAMPLE_SESSION_ID}}
523
+ stub_call_api_response(:post, "#{Tddium::Api::Path::SESSIONS}", response)
360
524
  end
361
525
 
362
- it "should send a 'POST' request to '#{Tddium::REGISTER_TEST_EXECUTIONS_PATH}'" do
526
+ it "should send a 'POST' request to '#{Tddium::Api::Path::REGISTER_TEST_EXECUTIONS}'" do
527
+ call_api_should_receive(:method => :post, :path => /#{Tddium::Api::Path::REGISTER_TEST_EXECUTIONS}$/)
363
528
  run_spec(tddium)
364
- FakeWeb.last_request.method.should == "POST"
365
- FakeWeb.last_request.path.should =~ /#{Tddium::REGISTER_TEST_EXECUTIONS_PATH}$/
366
529
  end
367
530
 
368
531
  it_should_behave_like "sending the api key"
369
532
 
370
533
  it "should POST the names of the file names extracted from the suite's test_pattern" do
534
+ current_dir = Dir.pwd
535
+ call_api_should_receive(:params => {:suite_id => SAMPLE_SUITE_ID,
536
+ :tests => [{:test_name => "#{current_dir}/spec/cat_spec.rb"},
537
+ {:test_name => "#{current_dir}/spec/dog_spec.rb"},
538
+ {:test_name => "#{current_dir}/spec/mouse_spec.rb"}]})
371
539
  run_spec(tddium)
372
- request_params = parse_request_params
373
- request_params.should include({"suite_id" => DEFAULT_SUITE_ID})
374
- request_params["tests"][0]["test_name"].should =~ /spec\/cat_spec.rb$/
375
- request_params["tests"][1]["test_name"].should =~ /spec\/dog_spec.rb$/
376
- request_params["tests"][2]["test_name"].should =~ /spec\/mouse_spec.rb$/
377
- request_params["tests"].size.should == 3
378
540
  end
379
541
 
380
- context "'POST #{Tddium::REGISTER_TEST_EXECUTIONS_PATH}' is successful" do
542
+ context "'POST #{Tddium::Api::Path::REGISTER_TEST_EXECUTIONS}' is successful" do
381
543
  before do
382
- stub_http_response(:post, "#{Tddium::SESSIONS_PATH}/#{session_id}/#{Tddium::REGISTER_TEST_EXECUTIONS_PATH}", :response => fixture_path("post_register_test_executions_200.json"))
383
- stub_http_response(:post, "#{Tddium::SESSIONS_PATH}/#{session_id}/#{Tddium::START_TEST_EXECUTIONS_PATH}")
544
+ response = {"added"=>0, "existing"=>1, "errors"=>0, "status"=>0}
545
+ stub_call_api_response(:post, "#{Tddium::Api::Path::SESSIONS}/#{SAMPLE_SESSION_ID}/#{Tddium::Api::Path::REGISTER_TEST_EXECUTIONS}", response)
384
546
  end
385
547
 
386
- it "should send a 'POST' request to '#{Tddium::START_TEST_EXECUTIONS_PATH}'" do
548
+ it "should send a 'POST' request to '#{Tddium::Api::Path::START_TEST_EXECUTIONS}'" do
549
+ call_api_should_receive(:method => :post, :path => /#{Tddium::Api::Path::START_TEST_EXECUTIONS}$/)
387
550
  run_spec(tddium)
388
- FakeWeb.last_request.method.should == "POST"
389
- FakeWeb.last_request.path.should =~ /#{Tddium::START_TEST_EXECUTIONS_PATH}$/
390
551
  end
391
552
 
392
553
  it_should_behave_like "sending the api key"
393
554
 
394
- context "'POST #{Tddium::START_TEST_EXECUTIONS_PATH}' is successful" do
555
+ context "'POST #{Tddium::Api::Path::START_TEST_EXECUTIONS}' is successful" do
556
+ let(:get_test_executions_response) { {"report"=>SAMPLE_REPORT_URL, "tests"=>{"spec/mouse_spec.rb"=>{"end_time"=>SAMPLE_DATE_TIME, "status"=>"pending"}, "spec/pig_spec.rb"=>{"end_time"=>nil, "status"=>"started"}, "spec/dog_spec.rb"=>{"end_time"=>SAMPLE_DATE_TIME, "status"=>"failed"}, "spec/cat_spec.rb"=>{"end_time"=>SAMPLE_DATE_TIME, "status"=>"passed"}}} }
395
557
  before do
396
- stub_http_response(:post, "#{Tddium::SESSIONS_PATH}/#{session_id}/#{Tddium::START_TEST_EXECUTIONS_PATH}", :response => fixture_path("post_start_test_executions_200.json"))
397
- stub_http_response(:get, "#{Tddium::SESSIONS_PATH}/#{session_id}/#{Tddium::TEST_EXECUTIONS_PATH}")
558
+ response = {"started"=>1, "status"=>0}
559
+ stub_call_api_response(:post, "#{Tddium::Api::Path::SESSIONS}/#{SAMPLE_SESSION_ID}/#{Tddium::Api::Path::START_TEST_EXECUTIONS}", response)
398
560
  end
399
561
 
400
- it "should tell the user to '#{Tddium::TERMINATE_PROCESS_INSTRUCTIONS}'" do
401
- tddium.should_receive(:say).with(Tddium::TERMINATE_PROCESS_INSTRUCTIONS)
562
+ it "should tell the user to '#{Tddium::Text::Process::TERMINATE_INSTRUCTION}'" do
563
+ tddium.should_receive(:say).with(Tddium::Text::Process::TERMINATE_INSTRUCTION)
402
564
  run_spec(tddium)
403
565
  end
404
566
 
405
- it "should send a 'GET' request to '#{Tddium::TEST_EXECUTIONS_PATH}'" do
567
+ it "should tell the user '#{Tddium::Text::Process::STARTING_TEST % 3}'" do
568
+ tddium.should_receive(:say).with(Tddium::Text::Process::STARTING_TEST % 3)
569
+ run_spec(tddium)
570
+ end
571
+
572
+ it "should send a 'GET' request to '#{Tddium::Api::Path::TEST_EXECUTIONS}'" do
573
+ call_api_should_receive(:method => :get, :path => /#{Tddium::Api::Path::TEST_EXECUTIONS}$/)
406
574
  run_spec(tddium)
407
- FakeWeb.last_request.method.should == "GET"
408
- FakeWeb.last_request.path.should =~ /#{Tddium::TEST_EXECUTIONS_PATH}$/
409
575
  end
410
576
 
411
577
  it_should_behave_like "sending the api key"
412
578
 
413
579
  shared_examples_for("test output summary") do
414
- it "should display a link to the report" do
415
- tddium.should_receive(:say).with("You can check out the test report details at http://api.tddium.com/1/sessions/7/test_executions/report")
580
+ it "should show the user a link to the report" do
581
+ tddium.should_receive(:say).with(Tddium::Text::Process::CHECK_TEST_REPORT % SAMPLE_REPORT_URL)
416
582
  run_spec(tddium)
417
583
  end
418
584
 
419
- it "should display the time taken" do
420
- tddium.should_receive(:say).with(/^Finished in [\d\.]+ seconds$/)
585
+ it "should show the user the time taken" do
586
+ tddium.should_receive(:say).with(/^#{Tddium::Text::Process::FINISHED_TEST % "[\\d\\.]+"}$/)
421
587
  run_spec(tddium)
422
588
  end
423
589
  end
424
590
 
425
591
  context "user presses 'Ctrl-C' during the process" do
426
592
  before do
427
- stub_http_response(:get, "#{Tddium::SESSIONS_PATH}/#{session_id}/#{Tddium::TEST_EXECUTIONS_PATH}", :response => fixture_path("get_test_executions_200.json"))
593
+ stub_call_api_response(:get, "#{Tddium::Api::Path::SESSIONS}/#{SAMPLE_SESSION_ID}/#{Tddium::Api::Path::TEST_EXECUTIONS}", get_test_executions_response)
428
594
  Signal.stub(:trap).with(:INT).and_yield
429
595
  stub_sleep(tddium)
430
596
  end
431
597
 
432
- it "should display '#{Tddium::INTERRUPT_TEXT}'" do
433
- tddium.should_receive(:say).with(Tddium::INTERRUPT_TEXT)
598
+ it "should show the user '#{Tddium::Text::Process::INTERRUPT}'" do
599
+ tddium.should_receive(:say).with(Tddium::Text::Process::INTERRUPT)
434
600
  run_spec(tddium)
435
601
  end
436
602
 
437
- it "should display a summary of all the tests" do
603
+ it "should show the user '#{Tddium::Text::Process::CHECK_TEST_STATUS}'" do
604
+ tddium.should_receive(:say).with(Tddium::Text::Process::CHECK_TEST_STATUS)
605
+ run_spec(tddium)
606
+ end
607
+
608
+ it "should show the user a summary of all the tests" do
438
609
  tddium.should_receive(:say).with("3 examples, 1 failures, 0 errors, 1 pending")
439
610
  run_spec(tddium)
440
611
  end
@@ -442,34 +613,35 @@ describe Tddium do
442
613
  it_should_behave_like("test output summary")
443
614
  end
444
615
 
445
- context "'GET #{Tddium::TEST_EXECUTIONS_PATH}' is successful" do
616
+ context "'GET #{Tddium::Api::Path::TEST_EXECUTIONS}' is successful" do
446
617
  before do
447
- stub_http_response(:get, "#{Tddium::SESSIONS_PATH}/#{session_id}/#{Tddium::TEST_EXECUTIONS_PATH}", [{:response => fixture_path("get_test_executions_200.json")}, {:response => fixture_path("get_test_executions_200_all_finished.json")}])
618
+ get_test_executions_response_all_finished = {"report"=>SAMPLE_REPORT_URL, "tests"=>{"spec/mouse_spec.rb"=>{"end_time"=>SAMPLE_DATE_TIME, "status"=>"pending"}, "spec/pig_spec.rb"=>{"end_time"=>SAMPLE_DATE_TIME, "status"=>"error"}, "spec/dog_spec.rb"=>{"end_time"=>SAMPLE_DATE_TIME, "status"=>"failed"}, "spec/cat_spec.rb"=>{"end_time"=>SAMPLE_DATE_TIME, "status"=>"passed"}}}
619
+ stub_call_api_response(:get, "#{Tddium::Api::Path::SESSIONS}/#{SAMPLE_SESSION_ID}/#{Tddium::Api::Path::TEST_EXECUTIONS}", get_test_executions_response, get_test_executions_response_all_finished)
448
620
  stub_sleep(tddium)
449
621
  end
450
622
 
451
- it "should sleep for #{Tddium::SLEEP_TIME_BETWEEN_POLLS} seconds" do
452
- tddium.should_receive(:sleep).exactly(1).times.with(Tddium::SLEEP_TIME_BETWEEN_POLLS)
623
+ it "should sleep for #{Tddium::Default::SLEEP_TIME_BETWEEN_POLLS} seconds" do
624
+ tddium.should_receive(:sleep).exactly(1).times.with(Tddium::Default::SLEEP_TIME_BETWEEN_POLLS)
453
625
  run_spec(tddium)
454
626
  end
455
627
 
456
628
  it "should display a green '.'" do
457
- tddium.should_receive(:say).with(".", :green)
629
+ tddium.should_receive(:say).with(".", :green, false)
458
630
  run_spec(tddium)
459
631
  end
460
632
 
461
633
  it "should display a red 'F'" do
462
- tddium.should_receive(:say).with("F", :red)
634
+ tddium.should_receive(:say).with("F", :red, false)
463
635
  run_spec(tddium)
464
636
  end
465
637
 
466
638
  it "should display a yellow '*'" do
467
- tddium.should_receive(:say).with("*", :yellow)
639
+ tddium.should_receive(:say).with("*", :yellow, false)
468
640
  run_spec(tddium)
469
641
  end
470
642
 
471
643
  it "should display 'E' with no color" do
472
- tddium.should_receive(:say).with("E", nil)
644
+ tddium.should_receive(:say).with("E", nil, false)
473
645
  run_spec(tddium)
474
646
  end
475
647
 
@@ -479,11 +651,404 @@ describe Tddium do
479
651
  end
480
652
 
481
653
  it_should_behave_like("test output summary")
654
+ end
655
+
656
+ it_should_behave_like "an unsuccessful api call"
657
+ end
658
+
659
+ it_should_behave_like "an unsuccessful api call"
660
+ end
661
+
662
+ it_should_behave_like "an unsuccessful api call"
663
+ end
664
+
665
+ it_should_behave_like "an unsuccessful api call"
666
+ end
667
+
668
+ it_should_behave_like "an unsuccessful api call"
669
+ end
670
+
671
+ describe "#status" do
672
+ before do
673
+ stub_defaults
674
+ stub_config_file(:api_key => true, :branches => true)
675
+ end
482
676
 
677
+ it_should_behave_like "set the default environment"
678
+ it_should_behave_like "git repo has not been initialized"
679
+ it_should_behave_like ".tddium file is missing or corrupt"
680
+ it_should_behave_like "suite has not been initialized"
681
+
682
+ context "'GET #{Tddium::Api::Path::SUITES}' is successful" do
683
+ context "returns no suites" do
684
+ before { stub_call_api_response(:get, Tddium::Api::Path::SUITES, {"suites" => []}) }
685
+
686
+ it "should show the user '#{Tddium::Text::Status::NO_SUITE}'" do
687
+ tddium.should_receive(:say).with(Tddium::Text::Status::NO_SUITE)
688
+ run_status(tddium)
689
+ end
690
+ end
691
+
692
+ context "returns some suites" do
693
+ let(:suite_attributes) { {"id"=>SAMPLE_SUITE_ID, "repo_name"=>SAMPLE_APP_NAME, "ruby_version"=>SAMPLE_RUBY_VERSION, "branch" => SAMPLE_BRANCH_NAME, "test_pattern" => SAMPLE_TEST_PATTERN, "bundler_version" => SAMPLE_BUNDLER_VERSION, "rubygems_version" => SAMPLE_RUBYGEMS_VERSION}}
694
+ before do
695
+ suites_response = {"suites"=>[suite_attributes], "status"=>0}
696
+ stub_call_api_response(:get, Tddium::Api::Path::SUITES, suites_response)
697
+ end
698
+
699
+ it "should show all suites" do
700
+ tddium.should_receive(:say).with(Tddium::Text::Status::ALL_SUITES % SAMPLE_APP_NAME)
701
+ run_status(tddium)
702
+ end
703
+
704
+ context "without current suite" do
705
+ before { stub_config_file(:branches => {SAMPLE_BRANCH_NAME => 0}) }
706
+ it "should show the user '#{Tddium::Text::Status::CURRENT_SUITE_UNAVAILABLE}'" do
707
+ tddium.should_receive(:say).with(Tddium::Text::Status::CURRENT_SUITE_UNAVAILABLE)
708
+ run_status(tddium)
709
+ end
710
+ end
711
+
712
+ context "with current suite" do
713
+ shared_examples_for "attribute details" do
714
+ it "should show the user the attribute details" do
715
+ attributes_to_display.each do |attr|
716
+ if attributes[attr]
717
+ tddium.should_receive(:say).with(Tddium::Text::Status::ATTRIBUTE_DETAIL % [attr.gsub("_", " ").capitalize, attributes[attr]])
718
+ else
719
+ tddium.should_not_receive(:say).with(/#{attr.gsub("_", " ").capitalize}/)
720
+ end
721
+ end
722
+ run_status(tddium)
723
+ end
724
+
725
+ it "should not show the user irrelevent attributes" do
726
+ attributes_to_hide.each do |regexp|
727
+ tddium.should_not_receive(:say).with(regexp)
728
+ end
729
+ run_status(tddium)
730
+ end
731
+ end
732
+
733
+ it "should show the separator" do
734
+ tddium.should_receive(:say).with(Tddium::Text::Status::SEPARATOR)
735
+ run_status(tddium)
736
+ end
737
+
738
+ it "should show user the current suite name" do
739
+ tddium.should_receive(:say).with(Tddium::Text::Status::CURRENT_SUITE % SAMPLE_APP_NAME)
740
+ run_status(tddium)
741
+ end
742
+
743
+ it_should_behave_like "attribute details" do
744
+ let(:attributes_to_display) {Tddium::DisplayedAttributes::SUITE}
745
+ let(:attributes_to_hide) { [/id/] }
746
+ let(:attributes) { suite_attributes }
747
+ end
748
+
749
+ context "show active sessions" do
750
+ context "without any session" do
751
+ before do
752
+ sessions_response = {"status"=>0, "sessions"=>[]}
753
+ stub_call_api_response(:get, Tddium::Api::Path::SESSIONS, sessions_response)
754
+ end
755
+
756
+ it "should display no active session message" do
757
+ tddium.should_receive(:say).with(Tddium::Text::Status::NO_ACTIVE_SESSION)
758
+ run_status(tddium)
759
+ end
760
+ end
761
+
762
+ context "with some sessions" do
763
+ let(:session_attributes) { {"id"=>SAMPLE_SESSION_ID, "user_id"=>3} }
764
+ before do
765
+ sessions_response = {"status"=>0, "sessions"=>[session_attributes]}
766
+ stub_call_api_response(:get, Tddium::Api::Path::SESSIONS, sessions_response)
767
+ end
768
+
769
+ it "should display the active sessions prompt" do
770
+ tddium.should_receive(:say).with(Tddium::Text::Status::ACTIVE_SESSIONS)
771
+ run_status(tddium)
772
+ end
773
+
774
+ it_should_behave_like "attribute details" do
775
+ let(:attributes_to_display) {Tddium::DisplayedAttributes::TEST_EXECUTION}
776
+ let(:attributes_to_hide) { [/id/] }
777
+ let(:attributes) { session_attributes }
778
+ end
779
+ end
780
+ end
781
+ end
782
+ end
783
+ end
784
+
785
+ it_should_behave_like "an unsuccessful api call"
786
+ end
787
+
788
+ describe "#suite" do
789
+ before do
790
+ stub_defaults
791
+ stub_config_file(:api_key => true)
792
+ stub_ruby_version(tddium)
793
+ stub_rubygems_version(tddium)
794
+ stub_bundler_version(tddium)
795
+ tddium.stub(:ask).and_return("")
796
+ end
797
+
798
+ it_should_behave_like "set the default environment"
799
+ it_should_behave_like "sending the api key"
800
+ it_should_behave_like "git repo has not been initialized"
801
+ it_should_behave_like ".tddium file is missing or corrupt"
802
+
803
+ context ".tddium file contains no suites" do
804
+ before do
805
+ stub_default_suite_name
806
+ stub_call_api_response(:get, Tddium::Api::Path::SUITES, {"suites" => []}, :and_return => SAMPLE_CALL_API_RESPONSE)
807
+ end
808
+
809
+ context "using defaults" do
810
+ it "should send a 'GET' request to '#{Tddium::Api::Path::SUITES} with the repo name and branch name'" do
811
+ call_api_should_receive(:method => :get, :path => Tddium::Api::Path::SUITES, :params => hash_including(:repo_name => SAMPLE_APP_NAME, :branch => SAMPLE_BRANCH_NAME))
812
+ run_suite(tddium)
813
+ end
814
+ end
815
+
816
+ context "passing '--name=my_suite'" do
817
+ let(:cli_args) { { :name => "my_suite" } }
818
+
819
+ it "should not ask for a suite name" do
820
+ tddium.should_not_receive(:ask).with(Tddium::Text::Prompt::SUITE_NAME % SAMPLE_APP_NAME)
821
+ run_suite(tddium, cli_args)
822
+ end
823
+
824
+ it "should send a GET request with the passed in values to the API" do
825
+ call_api_should_receive(:method => :get, :path => Tddium::Api::Path::SUITES, :params => hash_including(:repo_name => "my_suite"))
826
+ run_suite(tddium, cli_args)
827
+ end
828
+ end
829
+
830
+ context "interactive mode" do
831
+ before { tddium.stub(:ask).with(Tddium::Text::Prompt::SUITE_NAME % SAMPLE_APP_NAME).and_return("some_other_suite") }
832
+
833
+ it "should ask for a suite name" do
834
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::SUITE_NAME % SAMPLE_APP_NAME)
835
+ run_suite(tddium)
836
+ end
837
+
838
+ it "should send a GET request with the user's entries to the API" do
839
+ call_api_should_receive(:method => :get, :path => Tddium::Api::Path::SUITES, :params => hash_including(:repo_name => "some_other_suite"))
840
+ run_suite(tddium)
841
+ end
842
+ end
843
+
844
+ context "passing '--name=my_suite --test-pattern=**/*_selenium.rb'" do
845
+ it "should POST request with the passed in values to the API" do
846
+ call_api_should_receive(:method => :post, :path => Tddium::Api::Path::SUITES, :params => {:suite => hash_including(:repo_name => "my_suite", :test_pattern => "**/*_selenium.rb")})
847
+ run_suite(tddium, :name => "my_suite", :test_pattern => "**/*_selenium.rb")
848
+ end
849
+ end
850
+
851
+ context "but this user has already registered some suites" do
852
+ before do
853
+ stub_call_api_response(:get, Tddium::Api::Path::SUITES, SAMPLE_SUITES_RESPONSE, {"suites" => []}, :and_return => SAMPLE_CALL_API_RESPONSE)
854
+ tddium.stub(:ask).with(Tddium::Text::Prompt::USE_EXISTING_SUITE % SAMPLE_APP_NAME).and_return(Tddium::Text::Prompt::Response::YES)
855
+ end
856
+
857
+ shared_examples_for "writing the suite to file" do
858
+ it "should write the suite id and branch name to the .tddium file" do
859
+ run_suite(tddium)
860
+ tddium_file = File.open(SAMPLE_TDDIUM_CONFIG_FILE) { |file| file.read }
861
+ JSON.parse(tddium_file)["branches"][SAMPLE_BRANCH_NAME].should == SAMPLE_SUITE_ID
862
+ end
863
+ end
864
+
865
+ context "passing no cli options" do
866
+ it "should ask the user: '#{Tddium::Text::Prompt::USE_EXISTING_SUITE % SAMPLE_APP_NAME}' " do
867
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::USE_EXISTING_SUITE % SAMPLE_APP_NAME).and_return("something")
868
+ run_suite(tddium)
869
+ end
870
+ end
871
+
872
+ context "passing --name=my_suite" do
873
+ before do
874
+ stub_call_api_response(:get, Tddium::Api::Path::SUITES, SAMPLE_SUITES_RESPONSE, :and_return => SAMPLE_CALL_API_RESPONSE)
875
+ end
876
+
877
+ it "should not ask the user if they want to use the existing suite" do
878
+ tddium_client.should_not_receive(:ask).with(Tddium::Text::Prompt::USE_EXISTING_SUITE % "my_suite")
879
+ run_suite(tddium, :name => "my_suite")
880
+ end
881
+
882
+ it "should not POST the passed in values to the API" do
883
+ tddium_client.should_not_receive(:call_api).with(:post)
884
+ run_suite(tddium, :name => "my_suite")
885
+ end
886
+
887
+ it_should_behave_like "writing the suite to file"
888
+
889
+ end
890
+
891
+ context "the user wants to use the existing suite" do
892
+ before do
893
+ stub_call_api_response(:get, Tddium::Api::Path::SUITES, SAMPLE_SUITES_RESPONSE, :and_return => SAMPLE_CALL_API_RESPONSE)
894
+ end
895
+
896
+ it "should not send a 'POST' request to '#{Tddium::Api::Path::SUITES}'" do
897
+ tddium_client.should_not_receive(:call_api).with(:method => :post, :path => Tddium::Api::Path::SUITES)
898
+ run_suite(tddium)
899
+ end
900
+
901
+ it_should_behave_like "writing the suite to file"
902
+
903
+ it "should show the user: '#{Tddium::Text::Status::USING_SUITE % [SAMPLE_APP_NAME, SAMPLE_BRANCH_NAME]}'" do
904
+ tddium.should_receive(:say).with(Tddium::Text::Status::USING_SUITE % [SAMPLE_APP_NAME, SAMPLE_BRANCH_NAME])
905
+ run_suite(tddium)
906
+ end
907
+ end
908
+
909
+ context "the user does not want to use the existing suite" do
910
+ before{ tddium.stub(:ask).with(Tddium::Text::Prompt::USE_EXISTING_SUITE % SAMPLE_APP_NAME).and_return("some_other_suite") }
911
+
912
+ it "should ask for a test file pattern" do
913
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::TEST_PATTERN % Tddium::Default::TEST_PATTERN)
914
+ run_suite(tddium)
915
+ end
916
+
917
+ it "should send a 'POST' request to '#{Tddium::Api::Path::SUITES}'" do
918
+ call_api_should_receive(:method => :post, :path => Tddium::Api::Path::SUITES)
919
+ run_suite(tddium)
920
+ end
921
+
922
+ it "should post the user's current ruby version to the API" do
923
+ stub_ruby_version(tddium)
924
+ call_api_should_receive(:params => {:suite => hash_including(:ruby_version => SAMPLE_RUBY_VERSION)})
925
+ run_suite(tddium)
926
+ end
927
+
928
+ it "should post the user's current branch to the API" do
929
+ stub_ruby_version(tddium)
930
+ call_api_should_receive(:params => {:suite => hash_including(:branch => SAMPLE_BRANCH_NAME)})
931
+ run_suite(tddium)
932
+ end
933
+
934
+ it "should post the user's bundler version to the API" do
935
+ stub_ruby_version(tddium)
936
+ call_api_should_receive(:params => {:suite => hash_including(:bundler_version => SAMPLE_BUNDLER_VERSION)})
937
+ run_suite(tddium)
938
+ end
939
+
940
+ it "should post the user's rubygems version to the API" do
941
+ stub_ruby_version(tddium)
942
+ call_api_should_receive(:params => {:suite => hash_including(:rubygems_version => SAMPLE_RUBYGEMS_VERSION)})
943
+ run_suite(tddium)
944
+ end
945
+
946
+ context "using defaults" do
947
+ it "should POST the default test pattern to the API" do
948
+ call_api_should_receive(:params => {:suite => hash_including(:test_pattern => SAMPLE_TEST_PATTERN)})
949
+ run_suite(tddium)
950
+ end
951
+ end
952
+
953
+ context "interactive mode" do
954
+ before do
955
+ tddium.stub(:ask).with(Tddium::Text::Prompt::USE_EXISTING_SUITE % SAMPLE_APP_NAME).and_return("foobar")
956
+ tddium.stub(:ask).with(Tddium::Text::Prompt::TEST_PATTERN % Tddium::Default::TEST_PATTERN).and_return("**/*_test")
957
+ stub_default_suite_name
958
+ end
959
+
960
+ it "should POST the user's entered values to the API" do
961
+ call_api_should_receive(:method => :post, :params => {:suite => hash_including(:repo_name => "foobar", :test_pattern => "**/*_test")})
962
+ run_suite(tddium)
963
+ end
964
+ end
965
+
966
+ context "API response successful" do
967
+ before do
968
+ stub_call_api_response(:post, Tddium::Api::Path::SUITES, {"suite"=>{"id"=>SAMPLE_SUITE_ID, "git_repo_uri" => SAMPLE_GIT_REPO_URI}})
969
+ tddium.stub(:`).with(/^git remote/)
970
+ stub_git_push(tddium)
971
+ end
972
+
973
+ it_should_behave_like("writing the suite to file")
974
+
975
+ it "should remove any existing remotes named 'tddium'" do
976
+ tddium.should_receive(:`).with("git remote rm tddium")
977
+ run_suite(tddium)
978
+ end
979
+
980
+ it "should add a new remote called '#{Tddium::Git::REMOTE_NAME}'" do
981
+ stub_default_suite_name
982
+ tddium.should_receive(:`).with("git remote add #{Tddium::Git::REMOTE_NAME} #{SAMPLE_GIT_REPO_URI}")
983
+ run_suite(tddium)
984
+ end
985
+
986
+ context "in the branch 'oaktree'" do
987
+ before do
988
+ tddium.stub(:current_git_branch).and_return("oaktree")
989
+ end
990
+
991
+ it "should push the current git branch to tddium oaktree" do
992
+ tddium.should_receive(:system).with("git push tddium oaktree")
993
+ run_suite(tddium)
994
+ end
483
995
  end
484
996
  end
485
- end
997
+ it_should_behave_like "an unsuccessful api call"
998
+ end
486
999
  end
487
1000
  end
1001
+
1002
+ context "suite has already been registered" do
1003
+ before do
1004
+ stub_config_file(:api_key => true, :branches => true)
1005
+ end
1006
+
1007
+ context "'GET #{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}' is successful" do
1008
+ before do
1009
+ response = {
1010
+ "suite" => {
1011
+ "test_pattern" => "**/*_test.rb",
1012
+ "id" => SAMPLE_SUITE_ID
1013
+ }
1014
+ }
1015
+ stub_call_api_response(:get, "#{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}", response)
1016
+ end
1017
+
1018
+ it "should not ask for a suite name" do
1019
+ stub_default_suite_name
1020
+ tddium.should_not_receive(:ask).with(Tddium::Text::Prompt::SUITE_NAME % SAMPLE_APP_NAME)
1021
+ run_suite(tddium)
1022
+ end
1023
+
1024
+ it "should not look for the current ruby version" do
1025
+ tddium.should_not_receive(:`).with("ruby -v")
1026
+ run_suite(tddium)
1027
+ end
1028
+
1029
+ it "should prompt for a test pattern using the current test pattern as the default" do
1030
+ tddium.should_receive(:ask).with(/\*\*\/\*\_test\.rb/)
1031
+ run_suite(tddium)
1032
+ end
1033
+
1034
+ it "should send a 'PUT' request to '#{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}'" do
1035
+ call_api_should_receive(:method => :put, :path => "#{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}")
1036
+ run_suite(tddium)
1037
+ end
1038
+
1039
+ context "'PUT #{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}' is successful" do
1040
+ before { stub_call_api_response(:put, "#{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}", {}) }
1041
+ it "should display '#{Tddium::Text::Process::UPDATE_SUITE}'" do
1042
+ tddium.should_receive(:say).with(Tddium::Text::Process::UPDATE_SUITE)
1043
+ run_suite(tddium)
1044
+ end
1045
+ end
1046
+
1047
+ it_should_behave_like "sending the api key"
1048
+ it_should_behave_like "an unsuccessful api call"
1049
+ end
1050
+
1051
+ it_should_behave_like "an unsuccessful api call"
1052
+ end
488
1053
  end
489
1054
  end