tddium-preview 0.1.5 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tddium-preview (0.1.4)
4
+ tddium-preview (0.1.5)
5
5
  bundler
6
6
  highline
7
7
  json
@@ -14,8 +14,8 @@ GEM
14
14
  crack (0.1.8)
15
15
  diff-lcs (1.1.2)
16
16
  fakefs (0.3.1)
17
- highline (1.6.1)
18
- httparty (0.7.4)
17
+ highline (1.6.2)
18
+ httparty (0.7.7)
19
19
  crack (= 0.1.8)
20
20
  json (1.5.1)
21
21
  rake (0.8.7)
@@ -30,7 +30,7 @@ GEM
30
30
  simplecov (0.4.1)
31
31
  simplecov-html (~> 0.4.3)
32
32
  simplecov-html (0.4.3)
33
- tddium_client (0.0.6)
33
+ tddium_client (0.0.8)
34
34
  httparty
35
35
  json
36
36
  thor (0.14.6)
data/lib/tddium.rb CHANGED
@@ -9,6 +9,7 @@ require "json"
9
9
  require "tddium_client"
10
10
  require "base64"
11
11
  require File.expand_path("../tddium/constant", __FILE__)
12
+ require File.expand_path("../tddium/heroku", __FILE__)
12
13
 
13
14
  # Usage:
14
15
  #
@@ -26,7 +27,7 @@ require File.expand_path("../tddium/constant", __FILE__)
26
27
 
27
28
  class Tddium < Thor
28
29
  include TddiumConstant
29
-
30
+
30
31
  desc "account", "View/Manage account information"
31
32
  method_option :environment, :type => :string, :default => nil
32
33
  method_option :email, :type => :string, :default => nil
@@ -37,6 +38,10 @@ class Tddium < Thor
37
38
  if user_details = user_logged_in?
38
39
  # User is already logged in, so just display the info
39
40
  show_user_details(user_details)
41
+ elsif heroku_config = HerokuConfig.read_config
42
+ # User has logged in to heroku, and TDDIUM environment variables are
43
+ # present
44
+ handle_heroku_user(options, heroku_config)
40
45
  else
41
46
  params = get_user_credentials(options.merge(:invited => true))
42
47
 
@@ -49,9 +54,7 @@ class Tddium < Thor
49
54
  end
50
55
  end
51
56
 
52
- # Prompt for ssh-key file
53
- ssh_file = prompt(Text::Prompt::SSH_KEY, options[:ssh_key_file], Default::SSH_FILE)
54
- params[:user_git_pubkey] = File.open(File.expand_path(ssh_file)) {|file| file.read}
57
+ params[:user_git_pubkey] = prompt_ssh_key(options[:ssh_key_file])
55
58
 
56
59
  # Prompt for accepting license
57
60
  content = File.open(File.join(File.dirname(__FILE__), "..", License::FILE_NAME)) do |file|
@@ -420,6 +423,33 @@ class Tddium < Thor
420
423
  message.nil?
421
424
  end
422
425
 
426
+ def handle_heroku_user(options, heroku_config)
427
+ api_key = heroku_config['TDDIUM_API_KEY']
428
+ user = tddium_client.call_api(:get, Api::Path::USERS, {}, api_key) rescue nil
429
+ if user && user["user"]["heroku_needs_activation"] != true
430
+ say Text::Status::HEROKU_CONFIG
431
+ elsif user
432
+ say Text::Process::HEROKU_WELCOME
433
+ params = get_user_credentials(:email => heroku_config['TDDIUM_USER_NAME'])
434
+ params.delete(:email)
435
+ params[:password_confirmation] = HighLine.ask(Text::Prompt::PASSWORD_CONFIRMATION) { |q| q.echo = "*" }
436
+ params[:user_git_pubkey] = prompt_ssh_key(options[:ssh_key])
437
+
438
+ begin
439
+ user_id = user["user"]["id"]
440
+ result = tddium_client.call_api(:put, "#{Api::Path::USERS}/#{user_id}/", {:user=>params, :heroku_activation=>true}, api_key)
441
+ write_api_key(user["user"]["api_key"])
442
+ say Text::Status::HEROKU_CONFIG
443
+ rescue TddiumClient::Error::API => e
444
+ exit_failure Text::Error::HEROKU_MISCONFIGURED % e
445
+ rescue TddiumClient::Error::Base => e
446
+ exit_failure Text::Error::HEROKU_MISCONFIGURED % e
447
+ end
448
+ else
449
+ exit_failure Text::Error::HEROKU_MISCONFIGURED % "Unrecognized user"
450
+ end
451
+ end
452
+
423
453
  def login_user(options = {})
424
454
  # POST (email, password) to /users/sign_in to retrieve an API key
425
455
  begin
@@ -436,6 +466,14 @@ class Tddium < Thor
436
466
  value.empty? ? default_value : value
437
467
  end
438
468
 
469
+ def prompt_ssh_key(current)
470
+ # Prompt for ssh-key file
471
+ ssh_file = prompt(Text::Prompt::SSH_KEY, options[:ssh_key_file], Default::SSH_FILE)
472
+ data = File.open(File.expand_path(ssh_file)) {|file| file.read}
473
+ data
474
+ end
475
+
476
+
439
477
  def set_default_environment(env)
440
478
  if env.nil?
441
479
  tddium_client.environment = :development
@@ -91,6 +91,13 @@ tddium spec
91
91
  USING_PREVIOUS_USER_DATA_FILE = "Using the previous user data file '%s'"
92
92
  USING_PREVIOUS_MAX_PARALLELISM = "Using the previous value of max_parallelism = %s"
93
93
  USING_PREVIOUS_TEST_PATTERN = "Using the previous value of test_pattern = %s"
94
+ HEROKU_WELCOME = "
95
+ Thanks for installing the Tddium Heroku Add-On!
96
+
97
+ Next, set a password and provide an SSH key to authenticate your communication
98
+ with Tddium.
99
+
100
+ "
94
101
  end
95
102
 
96
103
  module Status
@@ -106,6 +113,20 @@ tddium spec
106
113
  ATTRIBUTE_DETAIL = " %s: %s"
107
114
  SEPARATOR = "====="
108
115
  USING_SUITE = "Using suite: '%s' on branch: '%s'"
116
+ HEROKU_CONFIG = "
117
+ Tddium is configured to work with your Heroku app.
118
+
119
+ Next, you should:
120
+
121
+ 1. Register your test suite by running:
122
+
123
+ $ tddium suite
124
+
125
+ 2. Start tests by running:
126
+
127
+ $ tddium spec
128
+
129
+ "
109
130
  end
110
131
 
111
132
  module Error
@@ -122,6 +143,7 @@ http://blog.tddium.com/home/
122
143
  NO_USER_DATA_FILE = "User data file '%s' does not exist"
123
144
  NO_MATCHING_FILES = "No files match '%s'"
124
145
  PASSWORD_ERROR = "Error changing password: %s"
146
+ HEROKU_MISCONFIGURED = "There was an error linking your Heroku account to Tddium: %s"
125
147
  end
126
148
  end
127
149
 
@@ -0,0 +1,24 @@
1
+ =begin
2
+ Copyright (c) 2011 Solano Labs All Rights Reserved
3
+ =end
4
+
5
+ class HerokuConfig
6
+ def self.read_config
7
+ result = nil
8
+ begin
9
+ config = {}
10
+ output = `heroku config -s`
11
+ output.lines.each do |line|
12
+ line.chomp!
13
+ k, v = line.split('=')
14
+ if k =~ /^TDDIUM_/ && v.length > 0
15
+ config[k] = v
16
+ end
17
+ end
18
+ result = config if config.keys.length > 0
19
+ rescue Errno::ENOENT
20
+ rescue Errno::EPERM
21
+ end
22
+ result
23
+ end
24
+ end
@@ -3,5 +3,5 @@ Copyright (c) 2011 Solano Labs All Rights Reserved
3
3
  =end
4
4
 
5
5
  module TddiumVersion
6
- VERSION = "0.1.5"
6
+ VERSION = "0.5.0"
7
7
  end
@@ -0,0 +1,54 @@
1
+ =begin
2
+ Copyright (c) 2011 Solano Labs All Rights Reserved
3
+ =end
4
+
5
+ require "rubygems"
6
+ require "rspec"
7
+ require "tddium/heroku"
8
+
9
+ describe HerokuConfig do
10
+ SAMPLE_HEROKU_CONFIG_TDDIUM = "
11
+ TDDIUM_API_KEY=abcdefg
12
+ TDDIUM_USER_NAME=app1234@heroku.com
13
+ "
14
+ SAMPLE_HEROKU_CONFIG_NO_TDDIUM = "
15
+ DB_URL=postgres://foo/bar
16
+ "
17
+ describe ".read_config" do
18
+ context "addon installed" do
19
+ before do
20
+ HerokuConfig.stub(:`).with("heroku config -s").and_return(SAMPLE_HEROKU_CONFIG_TDDIUM)
21
+ end
22
+
23
+ it "should return a hash of the TDDIUM config vars" do
24
+ result = HerokuConfig.read_config
25
+ result.should be_a(Hash)
26
+ result.each do |k,v|
27
+ k.should =~ /^TDDIUM_/
28
+ v.length.should > 0
29
+ end
30
+ result.should include('TDDIUM_API_KEY')
31
+ result['TDDIUM_API_KEY'].should == 'abcdefg'
32
+ end
33
+ end
34
+
35
+ context "addon not installed" do
36
+ before do
37
+ HerokuConfig.stub(:`).with("heroku config -s").and_return(SAMPLE_HEROKU_CONFIG_NO_TDDIUM)
38
+ end
39
+
40
+ it "should return nil" do
41
+ HerokuConfig.read_config.should be_nil
42
+ end
43
+ end
44
+
45
+ context "heroku not installed" do
46
+ before do
47
+ HerokuConfig.stub(:`).with("heroku config -s").and_raise(Errno::ENOENT)
48
+ end
49
+ it "should return nil" do
50
+ HerokuConfig.read_config.should be_nil
51
+ end
52
+ end
53
+ end
54
+ end
data/spec/tddium_spec.rb CHANGED
@@ -21,6 +21,7 @@ describe Tddium do
21
21
  SAMPLE_FILE_PATH2 = "./my_user_file2.png"
22
22
  SAMPLE_INVITATION_TOKEN = "TZce3NueiXp2lMTmaeRr"
23
23
  SAMPLE_GIT_REPO_URI = "ssh://git@api.tddium.com/home/git/repo/#{SAMPLE_APP_NAME}"
24
+ SAMPLE_HEROKU_CONFIG = {"TDDIUM_API_KEY" => SAMPLE_API_KEY, "TDDIUM_USER_NAME" => SAMPLE_EMAIL}
24
25
  SAMPLE_LICENSE_TEXT = "LICENSE"
25
26
  SAMPLE_PASSWORD = "foobar"
26
27
  SAMPLE_NEW_PASSWORD = "foobar2"
@@ -37,7 +38,20 @@ describe Tddium do
37
38
  SAMPLE_SUITES_RESPONSE = {"suites" => [SAMPLE_SUITE_RESPONSE]}
38
39
  SAMPLE_TDDIUM_CONFIG_FILE = ".tddium.test"
39
40
  SAMPLE_TEST_EXECUTION_STATS = "total 1, notstarted 0, started 1, passed 0, failed 0, pending 0, error 0", "start_time"
40
- SAMPLE_USER_RESPONSE = {"user"=> {"id"=>SAMPLE_USER_ID, "api_key" => SAMPLE_API_KEY, "email" => SAMPLE_EMAIL, "created_at" => SAMPLE_DATE_TIME, "recurly_url" => SAMPLE_RECURLY_URL}}
41
+ SAMPLE_USER_RESPONSE = {"status"=>0, "user"=>
42
+ { "id"=>SAMPLE_USER_ID,
43
+ "api_key" => SAMPLE_API_KEY,
44
+ "email" => SAMPLE_EMAIL,
45
+ "created_at" => SAMPLE_DATE_TIME,
46
+ "recurly_url" => SAMPLE_RECURLY_URL}}
47
+ SAMPLE_SSH_PUBKEY = "ssh-rsa 1234567890"
48
+ SAMPLE_HEROKU_USER_RESPONSE = {"user"=>
49
+ { "id"=>SAMPLE_USER_ID,
50
+ "api_key" => SAMPLE_API_KEY,
51
+ "email" => SAMPLE_EMAIL,
52
+ "created_at" => SAMPLE_DATE_TIME,
53
+ "heroku_needs_activation" => true,
54
+ "recurly_url" => SAMPLE_RECURLY_URL}}
41
55
  PASSWORD_ERROR_EXPLANATION = "bad confirmation"
42
56
  PASSWORD_ERROR_RESPONSE = {"status"=>1, "explanation"=> PASSWORD_ERROR_EXPLANATION}
43
57
 
@@ -91,7 +105,10 @@ describe Tddium do
91
105
  tddium_client_result = mock(TddiumClient::Result::API)
92
106
  response_mocks << tddium_client_result
93
107
  else
94
- tddium_client_result = mock(TddiumClient::Error::API, :body => current_response.to_json)
108
+ tddium_client_result = mock(TddiumClient::Error::API)
109
+ tddium_client_result.stub(:body => current_response.to_json,
110
+ :code => 200,
111
+ :response => mock(:header => mock(:msg => "OK")))
95
112
  result.and_raise(TddiumClient::Error::API.new(tddium_client_result))
96
113
  end
97
114
  current_response.each do |k, v|
@@ -157,7 +174,9 @@ describe Tddium do
157
174
  def stub_tddium_client
158
175
  TddiumClient::Client.stub(:new).and_return(tddium_client)
159
176
  tddium_client.stub(:environment).and_return("test")
160
- tddium_client.stub(:call_api).and_raise(TddiumClient::Error::Base)
177
+ tddium_client.stub(:call_api) do |x,y,z,k|
178
+ raise TddiumClient::Error::Base.new("unstubbed call_api(#{x.inspect},#{y.inspect},#{z.inspect},#{k.inspect})")
179
+ end
161
180
  end
162
181
 
163
182
  let(:tddium) { Tddium.new }
@@ -440,7 +459,7 @@ describe Tddium do
440
459
  tddium.stub(:ask).and_return("")
441
460
  HighLine.stub(:ask).and_return("")
442
461
  create_file(File.join(File.dirname(__FILE__), "..", Tddium::License::FILE_NAME), SAMPLE_LICENSE_TEXT)
443
- create_file(Tddium::Default::SSH_FILE, "ssh-rsa blah")
462
+ create_file(Tddium::Default::SSH_FILE, SAMPLE_SSH_PUBKEY)
444
463
  end
445
464
 
446
465
  it_should_behave_like "set the default environment"
@@ -468,6 +487,122 @@ describe Tddium do
468
487
 
469
488
  end
470
489
 
490
+ shared_examples_for "prompt for ssh key" do
491
+ context "--ssh-key-file is not supplied" do
492
+ it "should prompt the user for their ssh key file" do
493
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::SSH_KEY % Tddium::Default::SSH_FILE)
494
+ run_account(tddium)
495
+ end
496
+ end
497
+
498
+ context "--ssh-key-file is supplied" do
499
+ it "should not prompt the user for their ssh key file" do
500
+ tddium.should_not_receive(:ask).with(Tddium::Text::Prompt::SSH_KEY % Tddium::Default::SSH_FILE)
501
+ run_account(tddium, :ssh_key_file => Tddium::Default::SSH_FILE)
502
+ end
503
+ end
504
+ end
505
+
506
+ def account_should_fail(options={})
507
+ options[:environment] = "test" unless options.has_key?(:environment)
508
+ stub_cli_options(tddium, options)
509
+ tddium.stub(:exit_failure).and_raise(SystemExit)
510
+ yield if block_given?
511
+ expect { tddium.account }.to raise_error(SystemExit)
512
+ end
513
+
514
+ context "the user is logged in to heroku, but not to tddium" do
515
+ before do
516
+ HerokuConfig.stub(:read_config).and_return(SAMPLE_HEROKU_CONFIG)
517
+ @user_path = "#{Tddium::Api::Path::USERS}/#{SAMPLE_USER_ID}/"
518
+ end
519
+
520
+ context "the user has a properly configured add-on" do
521
+
522
+ context "first-time account activation" do
523
+ before do
524
+ stub_call_api_response(:get, Tddium::Api::Path::USERS, SAMPLE_HEROKU_USER_RESPONSE)
525
+ stub_call_api_response(:put, @user_path, {"status"=>0})
526
+ end
527
+
528
+ it_behaves_like "prompting for password" do
529
+ let(:password_prompt) {Tddium::Text::Prompt::PASSWORD}
530
+ end
531
+
532
+ it_behaves_like "prompting for password" do
533
+ let(:password_prompt) {Tddium::Text::Prompt::PASSWORD_CONFIRMATION}
534
+ end
535
+
536
+ it_behaves_like "prompt for ssh key"
537
+
538
+ it "should display the heroku welcome" do
539
+ tddium.should_receive(:say).with(Tddium::Text::Process::HEROKU_WELCOME)
540
+ run_account(tddium)
541
+ end
542
+
543
+ it "should send a 'PUT' request to user_path with passwords" do
544
+ HighLine.stub(:ask).with(Tddium::Text::Prompt::PASSWORD).and_return(SAMPLE_PASSWORD)
545
+ HighLine.stub(:ask).with(Tddium::Text::Prompt::PASSWORD_CONFIRMATION).and_return(SAMPLE_PASSWORD)
546
+ call_api_should_receive(:method => :put,
547
+ :path => /#{@user_path}$/,
548
+ :params => {:user =>
549
+ {:password => SAMPLE_PASSWORD,
550
+ :password_confirmation => SAMPLE_PASSWORD,
551
+ :user_git_pubkey => SAMPLE_SSH_PUBKEY},
552
+ :heroku_activation => true},
553
+ :api_key => SAMPLE_API_KEY)
554
+ account_should_fail # call_api_should_receive stubs call_api with an error
555
+ end
556
+
557
+ context "PUT with passwords is successful" do
558
+ before do
559
+ stub_call_api_response(:put, @user_path, {"status"=>0})
560
+ end
561
+
562
+ it_should_behave_like "writing the api key to the .tddium file"
563
+
564
+ it "should display the heroku configured welcome" do
565
+ tddium.should_receive(:say).with(Tddium::Text::Status::HEROKU_CONFIG)
566
+ run_account(tddium)
567
+ end
568
+ end
569
+
570
+ context "PUT is unsuccessful" do
571
+ before do
572
+ stub_call_api_response(:put, @user_path, {"status" => 1, "explanation"=> "PUT error"})
573
+ end
574
+
575
+ it "should display an error message and fail" do
576
+ account_should_fail do
577
+ tddium.should_receive(:exit_failure).with(Tddium::Text::Error::HEROKU_MISCONFIGURED % "200 OK (1) PUT error")
578
+ end
579
+ end
580
+ end
581
+ end
582
+
583
+ context "re-run after account is activated" do
584
+ before do
585
+ stub_call_api_response(:get, Tddium::Api::Path::USERS, SAMPLE_USER_RESPONSE)
586
+ end
587
+
588
+ it "should display the heroku configured welcome" do
589
+ tddium.should_receive(:say).with(Tddium::Text::Status::HEROKU_CONFIG)
590
+ run_account(tddium)
591
+ end
592
+ end
593
+ end
594
+
595
+ context "the heroku config contains an unrecognized API key" do
596
+ let(:call_api_result) {[403, "Forbidden"]}
597
+
598
+ it "should display an error message and fail" do
599
+ account_should_fail do
600
+ tddium.should_receive(:exit_failure).with(Tddium::Text::Error::HEROKU_MISCONFIGURED % "Unrecognized user")
601
+ end
602
+ end
603
+ end
604
+ end
605
+
471
606
  context "the user is not already logged in" do
472
607
  let(:call_api_result) {[403, "Forbidden"]}
473
608
 
@@ -489,19 +624,7 @@ describe Tddium do
489
624
  HighLine.stub(:ask).with(Tddium::Text::Prompt::PASSWORD_CONFIRMATION).and_return(SAMPLE_PASSWORD)
490
625
  end
491
626
 
492
- context "--ssh-key-file is not supplied" do
493
- it "should prompt the user for their ssh key file" do
494
- tddium.should_receive(:ask).with(Tddium::Text::Prompt::SSH_KEY % Tddium::Default::SSH_FILE)
495
- run_account(tddium)
496
- end
497
- end
498
-
499
- context "--ssh-key-file is supplied" do
500
- it "should not prompt the user for their ssh key file" do
501
- tddium.should_not_receive(:ask).with(Tddium::Text::Prompt::SSH_KEY % Tddium::Default::SSH_FILE)
502
- run_account(tddium, :ssh_key_file => Tddium::Default::SSH_FILE)
503
- end
504
- end
627
+ it_behaves_like "prompt for ssh key"
505
628
 
506
629
  it "should show the user the license" do
507
630
  tddium.should_receive(:say).with(SAMPLE_LICENSE_TEXT)
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: tddium-preview
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.5
5
+ version: 0.5.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Solano Labs
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-08 00:00:00 -07:00
13
+ date: 2011-05-27 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -138,7 +138,9 @@ files:
138
138
  - bin/tddium
139
139
  - lib/tddium.rb
140
140
  - lib/tddium/constant.rb
141
+ - lib/tddium/heroku.rb
141
142
  - lib/tddium/version.rb
143
+ - spec/heroku_spec.rb
142
144
  - spec/spec_helper.rb
143
145
  - spec/tddium_spec.rb
144
146
  - tddium.gemspec
@@ -166,10 +168,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
168
  requirements: []
167
169
 
168
170
  rubyforge_project: tddium
169
- rubygems_version: 1.5.2
171
+ rubygems_version: 1.6.2
170
172
  signing_key:
171
173
  specification_version: 3
172
174
  summary: tddium Hosted Ruby Testing
173
- test_files:
174
- - spec/spec_helper.rb
175
- - spec/tddium_spec.rb
175
+ test_files: []
176
+