saucy 0.1.3 → 0.1.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/Gemfile +15 -1
- data/Gemfile.lock +67 -1
- data/Rakefile +26 -0
- data/app/controllers/memberships_controller.rb +33 -1
- data/app/models/invitation.rb +1 -1
- data/app/models/membership.rb +22 -0
- data/app/models/permission.rb +17 -0
- data/app/models/signup.rb +3 -3
- data/app/views/memberships/edit.html.erb +18 -0
- data/app/views/memberships/index.html.erb +4 -4
- data/config/routes.rb +2 -3
- data/features/run_features.feature +4 -3
- data/features/step_definitions/rails_steps.rb +3 -0
- data/lib/generators/saucy/features/templates/factories.rb +4 -4
- data/lib/generators/saucy/features/templates/step_definitions/session_steps.rb +6 -3
- data/lib/generators/saucy/features/templates/step_definitions/user_steps.rb +6 -4
- data/lib/generators/saucy/install/templates/create_saucy_tables.rb +8 -6
- data/lib/saucy/account.rb +9 -5
- data/lib/saucy/project.rb +28 -5
- data/lib/saucy/user.rb +5 -12
- data/spec/controllers/memberships_controller_spec.rb +87 -5
- data/spec/environment.rb +91 -0
- data/spec/models/account_spec.rb +17 -6
- data/spec/models/membership_spec.rb +37 -0
- data/spec/models/permission_spec.rb +19 -0
- data/spec/models/project_spec.rb +39 -9
- data/spec/models/user_spec.rb +16 -42
- data/spec/scaffold/config/routes.rb +5 -0
- data/spec/spec_helper.rb +8 -1
- data/spec/support/authentication_helpers.rb +16 -6
- metadata +75 -74
- data/app/controllers/permissions_controller.rb +0 -17
- data/app/models/account_membership.rb +0 -8
- data/app/models/project_membership.rb +0 -14
- data/app/views/permissions/edit.html.erb +0 -15
- data/spec/controllers/permissions_controller_spec.rb +0 -69
- data/spec/models/account_membership_spec.rb +0 -13
- data/spec/models/project_membership_spec.rb +0 -22
data/lib/saucy/account.rb
CHANGED
@@ -3,12 +3,12 @@ module Saucy
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
has_many :
|
7
|
-
has_many :users, :through => :
|
6
|
+
has_many :memberships, :dependent => :destroy
|
7
|
+
has_many :users, :through => :memberships
|
8
8
|
has_many :projects, :dependent => :destroy
|
9
|
-
has_many :admins, :through => :
|
9
|
+
has_many :admins, :through => :memberships,
|
10
10
|
:source => :user,
|
11
|
-
:conditions => { '
|
11
|
+
:conditions => { 'memberships.admin' => true }
|
12
12
|
|
13
13
|
belongs_to :plan
|
14
14
|
|
@@ -31,7 +31,7 @@ module Saucy
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def has_member?(user)
|
34
|
-
|
34
|
+
memberships.exists?(:user_id => user.id)
|
35
35
|
end
|
36
36
|
|
37
37
|
def users_by_name
|
@@ -45,6 +45,10 @@ module Saucy
|
|
45
45
|
def projects_visible_to(user)
|
46
46
|
projects.visible_to(user)
|
47
47
|
end
|
48
|
+
|
49
|
+
def memberships_by_name
|
50
|
+
memberships.by_name
|
51
|
+
end
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
data/lib/saucy/project.rb
CHANGED
@@ -4,12 +4,19 @@ module Saucy
|
|
4
4
|
|
5
5
|
included do
|
6
6
|
belongs_to :account
|
7
|
-
has_many :
|
8
|
-
has_many :users, :through => :
|
7
|
+
has_many :permissions, :dependent => :destroy
|
8
|
+
has_many :users, :through => :permissions
|
9
9
|
|
10
10
|
validates_presence_of :account_id
|
11
11
|
|
12
12
|
after_create :assign_default_memberships
|
13
|
+
after_save :update_memberships
|
14
|
+
|
15
|
+
# We have to define this here instead of mixing it in,
|
16
|
+
# because ActiveRecord does the same
|
17
|
+
def user_ids=(new_user_ids)
|
18
|
+
@new_user_ids = new_user_ids.reject { |user_id| user_id.blank? }
|
19
|
+
end
|
13
20
|
end
|
14
21
|
|
15
22
|
module ClassMethods
|
@@ -24,14 +31,30 @@ module Saucy
|
|
24
31
|
|
25
32
|
module InstanceMethods
|
26
33
|
def has_member?(user)
|
27
|
-
|
34
|
+
permissions.
|
35
|
+
joins(:membership).
|
36
|
+
exists?(:memberships => { :user_id => user.id })
|
28
37
|
end
|
29
38
|
|
30
39
|
private
|
31
40
|
|
32
41
|
def assign_default_memberships
|
33
|
-
account.
|
34
|
-
self.
|
42
|
+
account.memberships.where(:admin => true).each do |membership|
|
43
|
+
self.permissions.create(:membership => membership)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def update_memberships
|
48
|
+
if @new_user_ids
|
49
|
+
removed_user_ids = self.user_ids - @new_user_ids
|
50
|
+
added_user_ids = @new_user_ids - self.user_ids
|
51
|
+
|
52
|
+
permissions.where(:user_id => removed_user_ids).destroy_all
|
53
|
+
added_user_ids.each do |added_user_id|
|
54
|
+
membership =
|
55
|
+
account.memberships.where(:user_id => added_user_id).first
|
56
|
+
permissions.create!(:membership => membership)
|
57
|
+
end
|
35
58
|
end
|
36
59
|
end
|
37
60
|
end
|
data/lib/saucy/user.rb
CHANGED
@@ -4,28 +4,21 @@ module Saucy
|
|
4
4
|
|
5
5
|
included do
|
6
6
|
attr_accessible :name, :project_ids, :email, :password_confirmation, :password
|
7
|
-
has_many :
|
8
|
-
has_many :
|
9
|
-
has_many :
|
10
|
-
has_many :
|
7
|
+
has_many :memberships
|
8
|
+
has_many :accounts, :through => :memberships
|
9
|
+
has_many :permissions
|
10
|
+
has_many :projects, :through => :permissions
|
11
11
|
validates_presence_of :name
|
12
12
|
end
|
13
13
|
|
14
14
|
module InstanceMethods
|
15
15
|
def admin_of?(account)
|
16
|
-
|
16
|
+
memberships.exists?(:account_id => account.id, :admin => true)
|
17
17
|
end
|
18
18
|
|
19
19
|
def member_of?(account_or_project)
|
20
20
|
account_or_project.has_member?(self)
|
21
21
|
end
|
22
|
-
|
23
|
-
def update_permissions_for(account, project_ids)
|
24
|
-
project_ids_for_other_accounts = projects.
|
25
|
-
reject { |project| project.account_id == account.id }.
|
26
|
-
map { |project| project.id }
|
27
|
-
self.project_ids = project_ids + project_ids_for_other_accounts
|
28
|
-
end
|
29
22
|
end
|
30
23
|
|
31
24
|
module ClassMethods
|
@@ -3,20 +3,30 @@ require 'spec_helper'
|
|
3
3
|
describe MembershipsController, "routes" do
|
4
4
|
it { should route(:get, "/accounts/abc/memberships").
|
5
5
|
to(:action => :index, :account_id => 'abc') }
|
6
|
+
it { should route(:get, "/memberships/abc/edit").
|
7
|
+
to(:action => :edit, :id => 'abc') }
|
8
|
+
it { should route(:put, "/memberships/abc").
|
9
|
+
to(:action => :update, :id => 'abc') }
|
10
|
+
it { should route(:delete, "/memberships/abc").
|
11
|
+
to(:action => :destroy, :id => 'abc') }
|
6
12
|
end
|
7
13
|
|
8
14
|
describe MembershipsController, "permissions", :as => :account_member do
|
15
|
+
let(:membership) { Factory(:membership, :account => account) }
|
9
16
|
it { should deny_access.
|
10
17
|
on(:get, :index, :account_id => account.to_param).
|
11
18
|
flash(/admin/) }
|
19
|
+
it { should deny_access.
|
20
|
+
on(:get, :edit, :id => membership.to_param).
|
21
|
+
flash(/admin/) }
|
12
22
|
end
|
13
23
|
|
14
24
|
describe MembershipsController, "index", :as => :account_admin do
|
15
|
-
let(:
|
25
|
+
let(:memberships) { [Factory.stub(:membership), Factory.stub(:membership)] }
|
16
26
|
|
17
27
|
before do
|
18
28
|
Account.stubs(:find_by_url! => account)
|
19
|
-
account.stubs(:
|
29
|
+
account.stubs(:memberships_by_name => memberships)
|
20
30
|
get :index, :account_id => account.to_param
|
21
31
|
end
|
22
32
|
|
@@ -25,9 +35,81 @@ describe MembershipsController, "index", :as => :account_admin do
|
|
25
35
|
should render_template(:index)
|
26
36
|
end
|
27
37
|
|
28
|
-
it "assigns
|
29
|
-
account.should have_received(:
|
30
|
-
should assign_to(:
|
38
|
+
it "assigns memberships by name" do
|
39
|
+
account.should have_received(:memberships_by_name)
|
40
|
+
should assign_to(:memberships).with(memberships)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe MembershipsController, "edit", :as => :account_admin do
|
45
|
+
let(:edited_membership) { Factory.stub(:membership, :account => account) }
|
46
|
+
let(:projects) { [Factory.stub(:project)] }
|
47
|
+
|
48
|
+
before do
|
49
|
+
Membership.stubs(:find => edited_membership)
|
50
|
+
account.stubs(:projects_by_name => projects)
|
51
|
+
get :edit, :id => edited_membership.to_param
|
52
|
+
end
|
53
|
+
|
54
|
+
it "renders the edit template" do
|
55
|
+
should respond_with(:success)
|
56
|
+
should render_template(:edit)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "assigns projects by name" do
|
60
|
+
account.should have_received(:projects_by_name)
|
61
|
+
should assign_to(:projects).with(projects)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "assigns the membership being edited" do
|
65
|
+
Membership.should have_received(:find).with(edited_membership.to_param,
|
66
|
+
:include => :account)
|
67
|
+
should assign_to(:membership).with(edited_membership)
|
31
68
|
end
|
32
69
|
end
|
33
70
|
|
71
|
+
describe MembershipsController, "update", :as => :account_admin do
|
72
|
+
let(:edited_membership) { Factory.stub(:membership, :account => account) }
|
73
|
+
let(:attributes) { 'some attributes' }
|
74
|
+
|
75
|
+
before do
|
76
|
+
Membership.stubs(:find => edited_membership)
|
77
|
+
edited_membership.stubs(:update_attributes!)
|
78
|
+
put :update, :id => edited_membership.to_param,
|
79
|
+
:membership => attributes
|
80
|
+
end
|
81
|
+
|
82
|
+
it "redirects to the account memberships index" do
|
83
|
+
should redirect_to(account_memberships_url(account))
|
84
|
+
end
|
85
|
+
|
86
|
+
it "update the membership" do
|
87
|
+
edited_membership.should have_received(:update_attributes!).with(attributes)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "sets a flash message" do
|
91
|
+
should set_the_flash.to(/update/i)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe MembershipsController, "destroy", :as => :account_admin do
|
96
|
+
let(:removed_membership) { Factory.stub(:membership, :account => account) }
|
97
|
+
|
98
|
+
before do
|
99
|
+
Membership.stubs(:find => removed_membership)
|
100
|
+
removed_membership.stubs(:destroy)
|
101
|
+
delete :destroy, :id => removed_membership.to_param
|
102
|
+
end
|
103
|
+
|
104
|
+
it "redirects to the account memberships index" do
|
105
|
+
should redirect_to(account_memberships_url(account))
|
106
|
+
end
|
107
|
+
|
108
|
+
it "removes the membership" do
|
109
|
+
removed_membership.should have_received(:destroy)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "sets a flash message" do
|
113
|
+
should set_the_flash.to(/remove/i)
|
114
|
+
end
|
115
|
+
end
|
data/spec/environment.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
PROJECT_ROOT = File.expand_path("../..", __FILE__)
|
2
|
+
$LOAD_PATH << File.join(PROJECT_ROOT, "lib")
|
3
|
+
|
4
|
+
require 'rails/all'
|
5
|
+
require 'saucy'
|
6
|
+
require 'clearance'
|
7
|
+
require 'factory_girl'
|
8
|
+
require 'bourne'
|
9
|
+
|
10
|
+
class ApplicationController < ActionController::Base
|
11
|
+
include Clearance::Authentication
|
12
|
+
include Saucy::AccountAuthorization
|
13
|
+
end
|
14
|
+
|
15
|
+
class ProjectsController < ApplicationController
|
16
|
+
include Saucy::ProjectsController
|
17
|
+
end
|
18
|
+
|
19
|
+
class User < ActiveRecord::Base
|
20
|
+
include Clearance::User
|
21
|
+
include Saucy::User
|
22
|
+
end
|
23
|
+
|
24
|
+
module Testapp
|
25
|
+
class Application < Rails::Application
|
26
|
+
config.action_mailer.default_url_options = { :host => 'localhost' }
|
27
|
+
config.encoding = "utf-8"
|
28
|
+
config.paths.config.database = "spec/scaffold/config/database.yml"
|
29
|
+
config.paths.app.models << "lib/generators/saucy/install/templates/models"
|
30
|
+
config.paths.config.routes << "spec/scaffold/config/routes.rb"
|
31
|
+
config.paths.app.views << "spec/scaffold/views"
|
32
|
+
config.paths.log = "tmp/log"
|
33
|
+
config.cache_classes = true
|
34
|
+
config.whiny_nils = true
|
35
|
+
config.consider_all_requests_local = true
|
36
|
+
config.action_controller.perform_caching = false
|
37
|
+
config.action_dispatch.show_exceptions = false
|
38
|
+
config.action_controller.allow_forgery_protection = false
|
39
|
+
config.action_mailer.delivery_method = :test
|
40
|
+
config.active_support.deprecation = :stderr
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Testapp::Application.initialize!
|
45
|
+
|
46
|
+
require "lib/generators/saucy/features/templates/factories"
|
47
|
+
require "lib/generators/saucy/install/templates/create_saucy_tables"
|
48
|
+
|
49
|
+
class ClearanceCreateUsers < ActiveRecord::Migration
|
50
|
+
def self.up
|
51
|
+
create_table(:users) do |t|
|
52
|
+
t.string :email
|
53
|
+
t.string :encrypted_password, :limit => 128
|
54
|
+
t.string :salt, :limit => 128
|
55
|
+
t.string :confirmation_token, :limit => 128
|
56
|
+
t.string :remember_token, :limit => 128
|
57
|
+
t.boolean :email_confirmed, :default => false, :null => false
|
58
|
+
t.timestamps
|
59
|
+
end
|
60
|
+
|
61
|
+
add_index :users, :email
|
62
|
+
add_index :users, :remember_token
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class ClearanceMailer
|
67
|
+
def self.change_password(user)
|
68
|
+
new
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.confirmation(user)
|
72
|
+
new
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.deliver_change_password(user)
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.deliver_confirmation(user)
|
79
|
+
end
|
80
|
+
|
81
|
+
def deliver
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
Clearance.configure do |config|
|
86
|
+
end
|
87
|
+
|
88
|
+
FileUtils.rm_f(File.join(PROJECT_ROOT, 'tmp', 'test.sqlite3'))
|
89
|
+
ClearanceCreateUsers.suppress_messages { ClearanceCreateUsers.migrate(:up) }
|
90
|
+
CreateSaucyTables.suppress_messages { CreateSaucyTables.migrate(:up) }
|
91
|
+
|
data/spec/models/account_spec.rb
CHANGED
@@ -3,8 +3,8 @@ require 'spec_helper'
|
|
3
3
|
describe Account do
|
4
4
|
subject { Factory(:account) }
|
5
5
|
|
6
|
-
it { should have_many(:
|
7
|
-
it { should have_many(:users).through(:
|
6
|
+
it { should have_many(:memberships) }
|
7
|
+
it { should have_many(:users).through(:memberships) }
|
8
8
|
it { should have_many(:projects) }
|
9
9
|
|
10
10
|
it { should validate_uniqueness_of(:name) }
|
@@ -39,9 +39,9 @@ describe Account do
|
|
39
39
|
non_admin = Factory(:user)
|
40
40
|
non_member = Factory(:user)
|
41
41
|
admins.each do |admin|
|
42
|
-
Factory(:
|
42
|
+
Factory(:membership, :user => admin, :account => subject, :admin => true)
|
43
43
|
end
|
44
|
-
Factory(:
|
44
|
+
Factory(:membership, :user => non_admin, :account => subject, :admin => false)
|
45
45
|
|
46
46
|
result = subject.admins
|
47
47
|
|
@@ -49,13 +49,24 @@ describe Account do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
it "has a member with a membership" do
|
52
|
-
membership = Factory(:
|
52
|
+
membership = Factory(:membership, :account => subject)
|
53
53
|
should have_member(membership.user)
|
54
54
|
end
|
55
55
|
|
56
56
|
it "doesn't have a member without a membership" do
|
57
|
-
membership = Factory(:
|
57
|
+
membership = Factory(:membership, :account => subject)
|
58
58
|
should_not have_member(Factory(:user))
|
59
59
|
end
|
60
|
+
|
61
|
+
it "finds memberships by name" do
|
62
|
+
expected = 'expected result'
|
63
|
+
memberships = stub('memberships', :by_name => expected)
|
64
|
+
account = Factory.stub(:account)
|
65
|
+
account.stubs(:memberships => memberships)
|
66
|
+
|
67
|
+
result = account.memberships_by_name
|
68
|
+
|
69
|
+
result.should == expected
|
70
|
+
end
|
60
71
|
end
|
61
72
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Membership do
|
4
|
+
it { should belong_to(:account) }
|
5
|
+
it { should belong_to(:user) }
|
6
|
+
it { should validate_presence_of(:account_id) }
|
7
|
+
it { should validate_presence_of(:user_id) }
|
8
|
+
it { should have_many(:permissions) }
|
9
|
+
it { should have_many(:projects).through(:permissions) }
|
10
|
+
|
11
|
+
describe "given an existing account membership" do
|
12
|
+
before { Factory(:membership) }
|
13
|
+
it { should validate_uniqueness_of(:user_id).scoped_to(:account_id) }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "delegates the user's name" do
|
17
|
+
user = Factory(:user)
|
18
|
+
membership = Factory(:membership, :user => user)
|
19
|
+
|
20
|
+
membership.name.should == user.name
|
21
|
+
end
|
22
|
+
|
23
|
+
it "delegates the user's email" do
|
24
|
+
user = Factory(:user)
|
25
|
+
membership = Factory(:membership, :user => user)
|
26
|
+
|
27
|
+
membership.email.should == user.email
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returns memberships by name" do
|
31
|
+
Factory(:membership, :user => Factory(:user, :name => "def"))
|
32
|
+
Factory(:membership, :user => Factory(:user, :name => "abc"))
|
33
|
+
Factory(:membership, :user => Factory(:user, :name => "ghi"))
|
34
|
+
|
35
|
+
Membership.by_name.map(&:name).should == %w(abc def ghi)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Permission do
|
4
|
+
it { should belong_to(:project) }
|
5
|
+
it { should belong_to(:membership) }
|
6
|
+
it { should belong_to(:user) }
|
7
|
+
|
8
|
+
it "caches the user from the account membership" do
|
9
|
+
membership = Factory(:membership)
|
10
|
+
permission = Factory(:permission,
|
11
|
+
:membership => membership)
|
12
|
+
permission.user_id.should == membership.user_id
|
13
|
+
end
|
14
|
+
|
15
|
+
it "doesn't allow the user to be assigned" do
|
16
|
+
expect { subject.user = Factory.build(:user) }.to raise_error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
data/spec/models/project_spec.rb
CHANGED
@@ -3,18 +3,19 @@ require 'spec_helper'
|
|
3
3
|
describe Project do
|
4
4
|
it { should belong_to(:account) }
|
5
5
|
it { should validate_presence_of(:account_id) }
|
6
|
-
it { should have_many(:
|
7
|
-
it { should have_many(:users) }
|
6
|
+
it { should have_many(:permissions) }
|
7
|
+
it { should have_many(:users).through(:permissions) }
|
8
8
|
|
9
9
|
it "finds projects visible to a user" do
|
10
10
|
account = Factory(:account)
|
11
11
|
user = Factory(:user)
|
12
|
-
Factory(:
|
12
|
+
membership = Factory(:membership, :user => user, :account => account)
|
13
13
|
visible_projects = [Factory(:project, :account => account),
|
14
14
|
Factory(:project, :account => account)]
|
15
15
|
invisible_project = Factory(:project, :account => account)
|
16
16
|
visible_projects.each do |visible_project|
|
17
|
-
Factory(:
|
17
|
+
Factory(:permission, :project => visible_project,
|
18
|
+
:membership => membership)
|
18
19
|
end
|
19
20
|
|
20
21
|
Project.visible_to(user).to_a.should =~ visible_projects
|
@@ -38,12 +39,12 @@ describe Project, "for an account with admin and non-admin users" do
|
|
38
39
|
subject { Factory(:project, :account => account) }
|
39
40
|
|
40
41
|
before do
|
41
|
-
Factory(:
|
42
|
-
Factory(:
|
42
|
+
Factory(:membership, :account => account, :user => non_admin, :admin => false)
|
43
|
+
Factory(:membership, :account => other_account,
|
43
44
|
:user => non_member,
|
44
45
|
:admin => true)
|
45
46
|
admins.each do |admin|
|
46
|
-
Factory(:
|
47
|
+
Factory(:membership, :user => admin, :account => account, :admin => true)
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
@@ -68,8 +69,10 @@ describe Project, "saved" do
|
|
68
69
|
|
69
70
|
it "has a member with a membership" do
|
70
71
|
user = Factory(:user)
|
71
|
-
Factory(:
|
72
|
-
|
72
|
+
membership = Factory(:membership, :account => subject.account,
|
73
|
+
:user => user)
|
74
|
+
membership = Factory(:permission, :project => subject,
|
75
|
+
:membership => membership)
|
73
76
|
should have_member(user)
|
74
77
|
end
|
75
78
|
|
@@ -78,3 +81,30 @@ describe Project, "saved" do
|
|
78
81
|
should_not have_member(user)
|
79
82
|
end
|
80
83
|
end
|
84
|
+
|
85
|
+
describe Project, "assigning a new user list" do
|
86
|
+
subject { Factory(:project) }
|
87
|
+
|
88
|
+
let(:account) { subject.account }
|
89
|
+
let!(:member) { Factory(:user) }
|
90
|
+
let!(:non_member) { Factory(:user) }
|
91
|
+
|
92
|
+
before do
|
93
|
+
member_membership =
|
94
|
+
Factory(:membership, :account => account, :user => member)
|
95
|
+
non_member_membership =
|
96
|
+
Factory(:membership, :account => account, :user => non_member)
|
97
|
+
Factory(:permission, :membership => member_membership,
|
98
|
+
:project => subject)
|
99
|
+
|
100
|
+
subject.reload.update_attributes!(:user_ids => [non_member.id, ""])
|
101
|
+
end
|
102
|
+
|
103
|
+
it "adds an added user" do
|
104
|
+
member.should_not be_member_of(subject)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "removes a removed user" do
|
108
|
+
non_member.should be_member_of(subject)
|
109
|
+
end
|
110
|
+
end
|