tddium-preview 0.0.1 → 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.
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