shelly 0.1.34 → 0.1.35

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+ require "shelly/cli/organization"
3
+
4
+ describe Shelly::CLI::Organization do
5
+ before do
6
+ FileUtils.stub(:chmod)
7
+ @organization = Shelly::CLI::Organization.new
8
+ Shelly::CLI::Organization.stub(:new).and_return(@organization)
9
+ @client = mock
10
+ Shelly::Client.stub(:new).and_return(@client)
11
+ $stdout.stub(:puts)
12
+ $stdout.stub(:print)
13
+ @client.stub(:token).and_return("abc")
14
+ FileUtils.mkdir_p("/projects/foo")
15
+ Dir.chdir("/projects/foo")
16
+ end
17
+
18
+ describe "#list" do
19
+ before do
20
+ @client.stub(:token).and_return("abc")
21
+ @client.stub(:organizations).and_return([
22
+ {"name" => "aaa", "app_code_names" => ["app1"]},
23
+ {"name" => "ccc", "app_code_names" => ["app2", "app3"]}
24
+ ])
25
+ @client.stub(:app).with("app1").and_return("state" => "running")
26
+ @client.stub(:app).with("app2").and_return("state" => "turned_off")
27
+ @client.stub(:app).with("app3").and_return("state" => "no_code")
28
+ end
29
+
30
+ it "should ensure user has logged in" do
31
+ hooks(@organization, :list).should include(:logged_in?)
32
+ end
33
+
34
+ it "should print out all organizations with apps" do
35
+ $stdout.should_receive(:puts).with(green("You have access to the following organizations and clouds:"))
36
+ $stdout.should_receive(:puts).with(green("aaa"))
37
+ $stdout.should_receive(:puts).with(/app1 \s+ | running/)
38
+ $stdout.should_receive(:puts).with(green("ccc"))
39
+ $stdout.should_receive(:puts).with(/app2 \s+ | turned off/)
40
+ $stdout.should_receive(:puts).with(/app3 \s+ | no code/)
41
+ invoke(@organization, :list)
42
+ end
43
+ end
44
+ end
@@ -1,5 +1,6 @@
1
1
  require "spec_helper"
2
2
  require "shelly/cli/user"
3
+ require "shelly/cli/organization"
3
4
 
4
5
  describe Shelly::CLI::User do
5
6
  before do
@@ -15,40 +16,45 @@ describe Shelly::CLI::User do
15
16
  Dir.chdir("/projects/foo")
16
17
  @app = Shelly::App.new("foo-staging")
17
18
  File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\n") }
19
+
20
+ @client.stub(:members).and_return({})
18
21
  end
19
22
 
20
23
  describe "#help" do
21
24
  it "should show help" do
22
25
  $stdout.should_receive(:puts).with("Tasks:")
23
- $stdout.should_receive(:puts).with(/add \[EMAIL\]\s+# Add new developer to clouds defined in Cloudfile/)
24
- $stdout.should_receive(:puts).with(/list\s+# List users with access to clouds defined in Cloudfile/)
26
+ $stdout.should_receive(:puts).with(/add \[EMAIL\]\s+# Add new developer to organization/)
27
+ $stdout.should_receive(:puts).with(/list\s+# List users with access to organizations/)
28
+ $stdout.should_receive(:puts).with(/delete \[EMAIL\]\s+# Remove developer from organization/)
25
29
  invoke(@cli_user, :help)
26
30
  end
27
31
  end
28
32
 
29
33
  describe "#list" do
34
+ let(:organizations){
35
+ [{"name" => "org1"}]
36
+ }
37
+
30
38
  let(:response) {
31
- [{'email' => 'user@example.com', 'active' => true},
32
- {'email' => 'auser2@example2.com', 'active' => false}]
39
+ [{'email' => 'user@example.com', 'active' => true, "owner" => true},
40
+ {'email' => 'user2@example2.com', 'active' => true, "owner" => false},
41
+ {'email' => 'user3@example3.com', 'active' => false, "owner" => true}]
33
42
  }
34
43
 
35
44
  it "should ensure user has logged in" do
36
45
  hooks(@cli_user, :list).should include(:logged_in?)
37
46
  end
38
47
 
39
- # multiple_clouds is tested in main_spec.rb in describe "#start" block
40
- it "should ensure multiple_clouds check" do
41
- @client.stub(:collaborations).and_return(response)
42
- @cli_user.should_receive(:multiple_clouds).and_return(@app)
43
- invoke(@cli_user, :list)
44
- end
45
-
46
48
  context "on success" do
47
- it "should display clouds and users" do
48
- @client.stub(:collaborations).and_return(response)
49
- $stdout.should_receive(:puts).with("Cloud foo-staging:")
50
- $stdout.should_receive(:puts).with(" user@example.com")
51
- $stdout.should_receive(:puts).with(" auser2@example2.com (invited)")
49
+ it "should display organization's users" do
50
+ @cli_user.options = {:organization => "foo-org"}
51
+ @client.stub(:organizations).and_return(organizations)
52
+ @client.stub(:members).and_return(response)
53
+ $stdout.should_receive(:puts).with("Organizations with users:")
54
+ $stdout.should_receive(:puts).with(green " org1")
55
+ $stdout.should_receive(:puts).with(/user@example.com\s+ \| owner/)
56
+ $stdout.should_receive(:puts).with(/user2@example2.com\s+ \| member/)
57
+ $stdout.should_receive(:puts).with(/user3@example3.com \(invited\)\s+ \| owner/)
52
58
  invoke(@cli_user, :list)
53
59
  end
54
60
  end
@@ -56,78 +62,108 @@ describe Shelly::CLI::User do
56
62
 
57
63
  describe "#add" do
58
64
  before do
59
- @user = Shelly::User.new
60
- @client.stub(:apps).and_return([{"code_name" => "abc"}, {"code_name" => "fooo"}])
61
- Shelly::User.stub(:new).and_return(@user)
65
+ @organization = Shelly::Organization.new("name" => "foo-org")
66
+ Shelly::Organization.stub(:new).and_return(@organization)
67
+ @cli_user.options = {:organization => "foo-org"}
62
68
  end
63
69
 
64
70
  it "should ensure user has logged in" do
65
71
  hooks(@cli_user, :add).should include(:logged_in?)
66
72
  end
67
73
 
68
-
69
74
  context "on success" do
70
75
  before do
71
- @client.should_receive(:send_invitation).with("foo-staging", "megan@example.com")
72
- end
73
-
74
- # multiple_clouds is tested in main_spec.rb in describe "#start" block
75
- it "should ensure multiple_clouds check" do
76
- @cli_user.should_receive(:multiple_clouds).and_return(@app)
77
- invoke(@cli_user, :add, "megan@example.com")
76
+ @client.should_receive(:send_invitation).with("foo-org", "megan@example.com", true)
78
77
  end
79
78
 
80
79
  it "should ask about email" do
81
- fake_stdin(["megan@example.com"]) do
80
+ $stdout.should_receive(:puts).with(green "Sending invitation to megan@example.com to work on foo-org organization")
81
+ fake_stdin(["megan@example.com", "yes"]) do
82
82
  invoke(@cli_user, :add)
83
83
  end
84
84
  end
85
85
 
86
- it "should receive clouds from the Cloudfile" do
87
- invoke(@cli_user, :add, "megan@example.com")
86
+ it "should use email from argument" do
87
+ $stdout.should_receive(:puts).with(green "Sending invitation to megan@example.com to work on foo-org organization")
88
+ fake_stdin(["yes"]) do
89
+ invoke(@cli_user, :add, "megan@example.com")
90
+ end
91
+ end
92
+ end
93
+
94
+ context "on failure" do
95
+ it "should list all user's organizations" do
96
+ @cli_user.options = {}
97
+ $stdout.should_receive(:puts).with(red "You have to specify organization")
98
+ $stdout.should_receive(:puts).with("Select organization using `shelly user add [EMAIL] --organization ORGANIZATION_NAME`")
99
+ Shelly::CLI::Organization.stub_chain(:new, :list)
100
+ lambda do
101
+ invoke(@cli_user, :add, "megan@example.com")
102
+ end.should raise_error(SystemExit)
103
+ end
104
+
105
+ it "should display forbidden exception" do
106
+ exception = Shelly::Client::ForbiddenException.new({})
107
+ @client.stub(:send_invitation).and_raise(exception)
108
+ $stdout.should_receive(:puts).with(red "You have to be organization's owner to add new members")
109
+
110
+ lambda do
111
+ fake_stdin(["yes"]) { invoke(@cli_user, :add, "megan@example.com") }
112
+ end.should raise_error(SystemExit)
113
+ end
114
+
115
+ it "should display not found" do
116
+ response = {"resource" => "organization"}
117
+ exception = Shelly::Client::NotFoundException.new(response)
118
+ @client.stub(:send_invitation).and_raise(exception)
119
+
120
+ $stdout.should_receive(:puts).with(red "Organization 'foo-org' not found")
121
+ $stdout.should_receive(:puts).with(red "You can list organizations you have access to with `shelly organization list`")
122
+ lambda do
123
+ fake_stdin(["yes"]) { invoke(@cli_user, :add, "megan@example.com") }
124
+ end.should raise_error(SystemExit)
88
125
  end
89
126
 
90
- it "should receive clouds from the Cloudfile" do
91
- $stdout.should_receive(:puts).with("\e[32mSending invitation to megan@example.com to work on foo-staging\e[0m")
92
- invoke(@cli_user, :add, "megan@example.com")
127
+ it "should display validation exception" do
128
+ body = {"message" => "Validation Failed", "errors" => [["email", "megan@example.com has been already taken"]]}
129
+ exception = Shelly::Client::ValidationException.new(body)
130
+ @client.stub(:send_invitation).and_raise(exception)
131
+ $stdout.should_receive(:puts).with(red "User megan@example.com is already in the organization foo-org")
132
+
133
+ lambda do
134
+ fake_stdin(["yes"]) { invoke(@cli_user, :add, "megan@example.com") }
135
+ end.should raise_error(SystemExit)
93
136
  end
94
137
  end
95
138
  end
96
139
 
97
140
  describe "#delete" do
98
141
  before do
99
- @user = Shelly::User.new
100
- @client.stub(:apps).and_return([{"code_name" => "abc"}, {"code_name" => "fooo"}])
101
- Shelly::User.stub(:new).and_return(@user)
142
+ @organization = Shelly::Organization.new("name" => "foo-org")
143
+ Shelly::Organization.stub(:new).and_return(@organization)
144
+ @cli_user.options = {:organization => "foo-org"}
102
145
  end
103
146
 
104
147
  it "should ensure user has logged in" do
105
148
  hooks(@cli_user, :delete).should include(:logged_in?)
106
149
  end
107
150
 
108
- # multiple_clouds is tested in main_spec.rb in describe "#start" block
109
- it "should ensure multiple_clouds check" do
110
- @client.should_receive(:delete_collaboration).with("foo-staging", "megan@example.com")
111
- @cli_user.should_receive(:multiple_clouds).and_return(@app)
112
- invoke(@cli_user, :delete, "megan@example.com")
113
- end
114
-
115
151
  context "on success" do
116
152
  it "should ask about email" do
117
- @client.should_receive(:delete_collaboration).with("foo-staging", "megan@example.com")
153
+ @client.should_receive(:delete_member).with("foo-org", "megan@example.com")
118
154
  fake_stdin(["megan@example.com"]) do
119
155
  invoke(@cli_user, :delete)
120
156
  end
121
157
  end
122
158
 
123
159
  it "should receive email from param" do
124
- @client.should_receive(:delete_collaboration).with("foo-staging", "megan@example.com")
160
+ @client.should_receive(:delete_member).with("foo-org", "megan@example.com")
125
161
  invoke(@cli_user, :delete, "megan@example.com")
126
162
  end
127
163
 
128
164
  it "should show that user was removed" do
129
- @client.stub(:delete_collaboration)
130
- $stdout.should_receive(:puts).with("User megan@example.com deleted from cloud foo-staging")
165
+ @client.stub(:delete_member)
166
+ $stdout.should_receive(:puts).with("User megan@example.com deleted from organization foo-org")
131
167
  invoke(@cli_user, :delete, "megan@example.com")
132
168
  end
133
169
  end
@@ -135,7 +171,7 @@ describe Shelly::CLI::User do
135
171
  context "on failure" do
136
172
  it "should show that user wasn't found" do
137
173
  exception = Shelly::Client::NotFoundException.new("resource" => "user")
138
- @client.stub(:delete_collaboration).and_raise(exception)
174
+ @client.stub(:delete_member).and_raise(exception)
139
175
  $stdout.should_receive(:puts).with(red "User 'megan@example.com' not found")
140
176
  $stdout.should_receive(:puts).with(red "You can list users with `shelly user list`")
141
177
  lambda {
@@ -143,15 +179,35 @@ describe Shelly::CLI::User do
143
179
  }.should raise_error(SystemExit)
144
180
  end
145
181
 
182
+ it "should show that organization wasn't found" do
183
+ exception = Shelly::Client::NotFoundException.new("resource" => "organization")
184
+ @client.stub(:delete_member).and_raise(exception)
185
+ $stdout.should_receive(:puts).with(red "Organization 'foo-org' not found")
186
+ $stdout.should_receive(:puts).with(red "You can list organizations you have access to with `shelly organization list`")
187
+ lambda {
188
+ invoke(@cli_user, :delete, "megan@example.com")
189
+ }.should raise_error(SystemExit)
190
+ end
191
+
146
192
  it "should show that user can't delete own collaboration" do
147
193
  exception = Shelly::Client::ConflictException.new("message" =>
148
194
  "Can't remove own collaboration")
149
- @client.stub(:delete_collaboration).and_raise(exception)
195
+ @client.stub(:delete_member).and_raise(exception)
150
196
  $stdout.should_receive(:puts).with(red "Can't remove own collaboration")
151
197
  lambda {
152
198
  invoke(@cli_user, :delete, "megan@example.com")
153
199
  }.should raise_error(SystemExit)
154
200
  end
201
+
202
+ it "should show forbidden exception" do
203
+ exception = Shelly::Client::ForbiddenException.new({})
204
+ @client.stub(:delete_member).and_raise(exception)
205
+ $stdout.should_receive(:puts).with(red "You have to be organization's owner to remove members")
206
+
207
+ lambda {
208
+ invoke(@cli_user, :delete, "megan@example.com")
209
+ }.should raise_error(SystemExit)
210
+ end
155
211
  end
156
212
  end
157
213
  end
@@ -165,17 +165,43 @@ describe Shelly::Client do
165
165
 
166
166
  describe "#create_app" do
167
167
  it "should send post with app's attributes" do
168
- @client.should_receive(:post).with("/apps", :app => {:code_name => "foo", :ruby_version => "1.9.2"})
168
+ @client.should_receive(:post).with("/apps", :app => {:code_name => "foo", :ruby_version => "1.9.2"}, :organization_name => nil)
169
169
  @client.create_app(:code_name => "foo", :ruby_version => "1.9.2")
170
170
  end
171
+
172
+ it "should send post with app's attributes and organization name" do
173
+ @client.should_receive(:post).with("/apps", :app => {:code_name => "foo", :ruby_version => "1.9.2"}, :organization_name => "foo")
174
+ @client.create_app(:code_name => "foo", :ruby_version => "1.9.2", :organization_name => "foo")
175
+ end
176
+
177
+ end
178
+
179
+ describe "#organizations" do
180
+ it "should fetch organizations from API" do
181
+ FakeWeb.register_uri(:get, api_url("organizations"),
182
+ :body => [{:name => "org1", :app_code_names => ["app1"]},
183
+ {:name => "org2", :app_code_names => ["app2"]}].to_json)
184
+ response = @client.organizations
185
+ response.should == [{"name" => "org1", "app_code_names" => ["app1"]},
186
+ {"name" => "org2", "app_code_names" => ["app2"]}]
187
+ end
188
+ end
189
+
190
+ describe "#organization" do
191
+ it "should fetch organization from API" do
192
+ FakeWeb.register_uri(:get, api_url("organizations/foo-org"),
193
+ :body => {:name => "org1", :app_code_names => ["app1"]}.to_json)
194
+ response = @client.organization("foo-org")
195
+ response.should == {"name" => "org1", "app_code_names" => ["app1"]}
196
+ end
171
197
  end
172
198
 
173
- describe "#collaborations" do
199
+ describe "#members" do
174
200
  it "should send get request with app code_names" do
175
- FakeWeb.register_uri(:get, api_url("apps/staging-foo/collaborations"),
201
+ FakeWeb.register_uri(:get, api_url("organizations/staging-foo/memberships"),
176
202
  :body => [{:email => "test@example.com", :active => true},
177
203
  {:email => "test2@example.com", :active => false}].to_json)
178
- response = @client.collaborations("staging-foo")
204
+ response = @client.members("staging-foo")
179
205
  response.should == [{"email" => "test@example.com", 'active' => true},
180
206
  {"email" => "test2@example.com", 'active' => false}]
181
207
  end
@@ -229,7 +255,7 @@ describe Shelly::Client do
229
255
 
230
256
  describe "#send_invitation" do
231
257
  it "should send post with developer's email" do
232
- FakeWeb.register_uri(:post, api_url("apps/staging-foo/collaborations"), :body => {}.to_json)
258
+ FakeWeb.register_uri(:post, api_url("organizations/staging-foo/memberships"), :body => {}.to_json)
233
259
  response = @client.send_invitation("staging-foo", "megan@example.com")
234
260
  response.should == {}
235
261
  end
@@ -237,8 +263,8 @@ describe Shelly::Client do
237
263
 
238
264
  describe "#delete_collaboration" do
239
265
  it "should send delete with developer's email in url" do
240
- FakeWeb.register_uri(:delete, api_url("apps/staging-foo/collaborations/megan@example.com"), :body => {}.to_json)
241
- @client.delete_collaboration("staging-foo", "megan@example.com")
266
+ FakeWeb.register_uri(:delete, api_url("organizations/staging-foo/memberships/megan@example.com"), :body => {}.to_json)
267
+ @client.delete_member("staging-foo", "megan@example.com")
242
268
  end
243
269
  end
244
270
 
@@ -0,0 +1,78 @@
1
+ require "spec_helper"
2
+ require "shelly/organization"
3
+
4
+ describe Shelly::Organization do
5
+ before do
6
+ @client = mock
7
+ Shelly::Client.stub(:new).and_return(@client)
8
+ @organization = Shelly::Organization.new({"name" => "foo-org",
9
+ "app_code_names" => ['foo-staging']})
10
+ end
11
+
12
+ describe "#apps" do
13
+ it "should initialize App objects" do
14
+ Shelly::App.should_receive(:new).with('foo-staging')
15
+ @organization.apps
16
+ end
17
+ end
18
+
19
+ describe "#memberships" do
20
+ before do
21
+ response = [{"email" => "bb@example.com", "active" => true, "owner" => true},
22
+ {"email" => "aa@example.com", "active" => true, "owner" => false},
23
+ {"email" => "cc@example.com", "active" => false, "owner" => true},
24
+ {"email" => "dd@example.com", "active" => false, "owner" => false}]
25
+ @client.stub(:members).with("foo-org").and_return(response)
26
+ end
27
+
28
+ it "should fetch organization's users" do
29
+ @client.should_receive(:members).with("foo-org")
30
+ @organization.memberships
31
+ end
32
+
33
+ it "should sort members by email" do
34
+ members = @organization.memberships
35
+ members.should == [{"email"=>"aa@example.com", "active"=>true, "owner"=>false},
36
+ {"email"=>"bb@example.com", "active"=>true, "owner"=>true},
37
+ {"email"=>"cc@example.com", "active"=>false, "owner"=>true},
38
+ {"email"=>"dd@example.com", "active"=>false, "owner"=>false}]
39
+ end
40
+
41
+
42
+ context "owners" do
43
+ it "should return only owners without inactive members" do
44
+ owners = @organization.owners
45
+ owners.should == [{"email"=>"bb@example.com", "active"=>true, "owner"=>true}]
46
+ end
47
+ end
48
+
49
+ context "members" do
50
+ it "should return only members without inactive members" do
51
+ members = @organization.members
52
+ members.should == [{"email"=>"aa@example.com", "active"=>true, "owner"=>false}]
53
+ end
54
+ end
55
+
56
+ context "inactive_members" do
57
+ it "should return only inactive members" do
58
+ inactive = @organization.inactive_members
59
+ inactive.should == [{"email"=>"cc@example.com", "active"=>false, "owner"=>true},
60
+ {"email"=>"dd@example.com", "active"=>false, "owner"=>false}]
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "#send_invitation" do
66
+ it "should send invitation" do
67
+ @client.should_receive(:send_invitation).with("foo-org", "megan@example.com", true)
68
+ @organization.send_invitation("megan@example.com", true)
69
+ end
70
+ end
71
+
72
+ describe "#delete_member" do
73
+ it "should delete collaboration" do
74
+ @client.should_receive(:delete_member).with("foo-org", "megan@example.com")
75
+ @organization.delete_member("megan@example.com")
76
+ end
77
+ end
78
+ end
@@ -104,20 +104,6 @@ describe Shelly::User do
104
104
  end
105
105
  end
106
106
 
107
- describe "#send_invitation" do
108
- it "should send invitation" do
109
- @client.should_receive(:send_invitation).with("foo-staging", "megan@example.com")
110
- @user.send_invitation("foo-staging", "megan@example.com")
111
- end
112
- end
113
-
114
- describe "#delete_collaboration" do
115
- it "should delete collaboration" do
116
- @client.should_receive(:delete_collaboration).with("foo-staging", "megan@example.com")
117
- @user.delete_collaboration("foo-staging", "megan@example.com")
118
- end
119
- end
120
-
121
107
  describe "#ssh_key_path" do
122
108
  it "should return path to public dsa key file in the first place" do
123
109
  @user.ssh_key_path.should == File.expand_path("~/.ssh/id_dsa.pub")
@@ -195,5 +181,13 @@ describe Shelly::User do
195
181
  @user.apps
196
182
  end
197
183
  end
198
- end
199
184
 
185
+ describe "#organizations" do
186
+ it "should initialaize organizations objects" do
187
+ organizations = [{"name" => "org1"}]
188
+ @client.should_receive(:organizations).and_return(organizations)
189
+ Shelly::Organization.should_receive(:new).with({"name" => "org1"})
190
+ @user.organizations
191
+ end
192
+ end
193
+ end